The I2C LCD display is a simple way to show text, sensor readings, and status messages in Arduino projects while using only two communication pins. In this project, we will interface a 16×2 I2C LCD with an Arduino Uno and display text on the screen.
Using the In-Browser Flash feature, you can upload the program directly from your browser without copying the code manually.
Components Required
Arduino Uno
16×2 I2C LCD Display
USB Cable
Jumper Wires
About the I2C LCD Display
A standard 16×2 LCD normally requires many Arduino pins. The I2C module attached to the LCD reduces the connection requirement to only four pins:
VCC
GND
SDA
SCL
This makes wiring simpler and leaves more pins available for other sensors and modules.
Circuit Connections
I2C LCD Pin
Arduino Uno Pin
VCC
5V
GND
GND
SDA
A4
SCL
A5
Circuit Diagram
Open circuit
Arduino Code
#include <Wire.h> #include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() { lcd.init(); lcd.backlight();
lcd.setCursor(0, 0); lcd.print("Hello EXASUB");
lcd.setCursor(0, 1); lcd.print("Arduino Uno"); }
void loop() { }
In-Browser Flash
Upload the program directly to your Arduino Uno using the button below.
How to use the In-Browser Flash button
How the Code Works
Include Required Libraries
#include <Wire.h> #include <LiquidCrystal_I2C.h>
The Wire library enables I2C communication, while the LiquidCrystal_I2C library controls the LCD display.
Create LCD Object
LiquidCrystal_I2C lcd(0x27, 16, 2);
This creates an LCD object with:
I2C Address: 0x27
16 columns
2 rows
Initialize LCD
lcd.init(); lcd.backlight();
The LCD is initialized and the backlight is turned on.
Set Cursor Position
lcd.setCursor(0, 0);
Moves the cursor to the first column of the first row.
lcd.setCursor(0, 1);
Moves the cursor to the first column of the second row.
if(error == 0) { Serial.print("I2C device found at 0x"); Serial.println(address, HEX); } }
delay(5000); }
Open the Serial Monitor to view the detected I2C address.
Applications
Digital clocks
Temperature displays
Home automation systems
Menu-driven projects
Sensor monitoring systems
Robotics projects
Conclusion
In this project, we learned how to interface a 16×2 I2C LCD display with an Arduino Uno and display text on the screen using only two communication pins. I2C LCDs are widely used in Arduino projects because they simplify wiring and provide an easy way to display information.
Use the In-Browser Flash button above to quickly upload the project and start experimenting with LCD displays.
(Street Light Automation, Smart Gate & Air Quality Alert)
Smart cities are built by combining automation, sensing, and decision-making. In this project, a Smart City model was developed using an Arduino UNO and commonly available sensors to demonstrate how embedded systems can be used for urban automation.
This project focuses on real-world logic, not just blinking LEDs.
📌 Project Demonstration Video
🎥 Watch the complete working demonstration here:
👉 The video shows the automatic street lights, smart gate operation, and air quality alert system working in real time.
Project Overview
The model demonstrates four smart city subsystems working together:
Automatic Street Light System (LDR based)
Smart Entry Gate / Traffic Control (Ultrasonic + Servo)
Air Quality Monitoring System (MQ135 sensor)
Alert System (Buzzer for pollution warning)
Each subsystem works independently but is controlled by a single Arduino UNO, simulating how real smart-city nodes operate.
Components Used
Arduino UNO
LDR (Light Dependent Resistor – discrete, not module)
Ultrasonic Sensor (HC-SR04)
Servo Motor (gate control)
MQ135 Air Quality Sensor
Buzzer
LEDs (street lights)
330 Ω resistors (current limiting)
Breadboard, jumper wires, external LED wiring
🔌 Circuit Diagram
🧩 Complete circuit diagram for this project:
Open circuit
The circuit includes:
LDR voltage divider connected to an analog input
Ultrasonic sensor connected to digital pins
Servo motor connected to a PWM pin
MQ135 sensor connected to an analog input
Buzzer connected to a digital output
LED street lights driven through resistors
Street Light Implementation (Important Design Detail)
To simulate street lights, multiple LEDs were used.
Instead of driving LEDs directly from the Arduino pin, the following safe current-limiting method was implemented:
Two GPIO pins were used for street lighting
Each GPIO pin was connected through a 330 Ω resistor
The other end of each resistor was connected to 4–5 LEDs in parallel
Why this method was used
The resistor limits the current drawn from the GPIO pin
Using two GPIOs distributes the load instead of stressing a single pin
Parallel LEDs represent multiple street lights connected to one junction
This approach keeps the circuit safe for the Arduino while still allowing multiple LEDs to turn ON together during night conditions.
Automatic Street Light Logic (LDR)
The LDR continuously measures ambient light
During daytime:
LDR value is high
Street LEDs remain OFF
During night:
LDR value drops below a threshold
Street LEDs turn ON automatically
This demonstrates energy conservation, a core principle of smart cities.
Smart Gate / Traffic Control System
An ultrasonic sensor is placed near the entry point of the model.
When a vehicle or object comes within a fixed distance:
The ultrasonic sensor detects it
The servo motor rotates
The gate opens automatically
When the object moves away:
The gate closes again
This simulates automatic toll gates, parking entry systems, and traffic barriers.
Air Quality Monitoring (MQ135 Sensor)
To introduce environmental monitoring, an MQ135 air quality sensor was added.
The sensor measures pollution levels in the surrounding air
When the pollution value crosses a preset threshold:
The buzzer turns ON
This acts as an air pollution warning
This models how pollution monitoring stations work in smart cities.
Alert System (Buzzer)
The buzzer is used as a city alert mechanism.
OFF during normal air conditions
ON when pollution exceeds safe limits
This introduces the concept of public warning systems and real-time environmental alerts.
💻 Firmware Upload (Arduino Code)
⚡ Flash the firmware directly to Arduino UNO:
👉 This allows users to upload the tested firmware without opening the Arduino IDE.
#include <Servo.h>
#define TRIG_PIN 9
#define ECHO_PIN 8
#define LED_PIN 3
#define LED_PIN1 5
#define LDR_PIN A0
#define MQ135_PIN A1
#define BUZZER_PIN 7
#define SERVO_PIN 6
Servo gateServo;
long duration;
int distance;
int ldrValue;
int airValue;
int LDR_THRESHOLD = 500; // adjust after testing
int DIST_THRESHOLD = 15; // cm
int AIR_THRESHOLD = 400; // MQ135 threshold (adjust)
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(LED_PIN1, OUTPUT);
pinMode(BUZZER_PIN, OUTPUT);
gateServo.attach(SERVO_PIN);
gateServo.write(90); // gate closed
Serial.begin(9600);
Serial.println("Smart City System Starting...");
}
void loop() {
/* ---------- LDR STREET LIGHT ---------- */
ldrValue = analogRead(LDR_PIN);
if (ldrValue < LDR_THRESHOLD) {
analogWrite(LED_PIN, 255); // street light ON
digitalWrite(LED_PIN1, HIGH);
} else {
digitalWrite(LED_PIN, LOW); // street light OFF
digitalWrite(LED_PIN1, LOW);
}
/* ---------- ULTRASONIC SENSOR ---------- */
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW);
duration = pulseIn(ECHO_PIN, HIGH, 30000);
distance = duration * 0.034 / 2;
/* ---------- SERVO GATE CONTROL ---------- */
if (distance > 0 && distance < DIST_THRESHOLD) {
gateServo.write(0); // open gate
} else {
gateServo.write(90); // close gate
}
/* ---------- MQ135 AIR QUALITY ---------- */
airValue = analogRead(MQ135_PIN);
if (airValue > AIR_THRESHOLD) {
digitalWrite(BUZZER_PIN, HIGH); // pollution alert
} else {
digitalWrite(BUZZER_PIN, LOW);
}
/* ---------- SERIAL MONITOR ---------- */
Serial.print("LDR: ");
Serial.print(ldrValue);
Serial.print(" | Distance: ");
Serial.print(distance);
Serial.print(" cm | Air: ");
Serial.println(airValue);
delay(1000);
}
Software Logic Summary
The Arduino program continuously performs:
Ambient light measurement (LDR)
Distance measurement (Ultrasonic)
Air quality measurement (MQ135)
Decision-making based on thresholds
Actuator control (LEDs, servo, buzzer)
All logic runs in a loop, similar to how embedded systems operate in real infrastructure.
Educational Value
This project helps learners understand:
GPIO usage and current limiting
Sensor interfacing and calibration
Real-world automation logic
Embedded decision-making
Power and safety considerations
Smart city concepts beyond theory
Unlike ready-made kits, this setup uses discrete components, encouraging deeper understanding and troubleshooting skills.
Conclusion
This Smart City project demonstrates how simple electronics and embedded programming can be combined to address urban automation challenges such as energy efficiency, traffic control, and pollution monitoring.
It serves as a reference implementation for students and educators exploring smart-city concepts using Arduino.
Most “AI robot face” demos rely on heavy machine-learning models, cloud APIs, or large datasets. This project explores a different approach:
Using simple geometry and browser-based vision to create an expressive robot head that reacts to human movement in real time.
The robot head tracks left, right, up, and down head motion and mirrors it using animated eyes displayed on a small OLED screen — all controlled directly from a web browser.
No dataset. No model training. No server.
What This Project Does
Detects a human face using the browser camera
Estimates head orientation (yaw & pitch)
Sends motion data to an Arduino using Web Serial
Animates eye movement on a 0.96″ OLED display
Allows direction inversion (mirror correction) at runtime
The result is a small robot head that feels responsive and alive.
System Architecture
Browser Camera
↓
Face Geometry (MediaPipe)
↓
Yaw & Pitch Calculation
↓
Web Serial (USB)
↓
Arduino UNO
↓
OLED Eye Animation
All computation happens locally in the browser.
Hardware Used
Arduino UNO
0.96″ OLED (SSD1306, I2C)
USB cable
3D-printed enclosure
Software Stack
HTML + JavaScript
MediaPipe Face Mesh
Web Serial API
Arduino (C++)
Key Design Decisions
1. Pupils Move, Not Eyeballs
Moving only the pupils inside fixed eyeballs makes the face feel more natural and expressive.
2. Face-Relative Geometry
Head motion is measured relative to facial landmarks, not camera pixels. This makes movement symmetric and stable.
3. Runtime Direction Flip
A toggle button allows instant correction for mirrored cameras without changing code.
Educational Value
This project can be used to teach:
Coordinate systems
Geometry-based tracking
Browser ↔ hardware communication
Human-centered design
It is suitable for classrooms, labs, and exhibitions.
Conclusion
This robot head demonstrates that intelligence is not just about models, but about understanding interaction.
By combining browser vision, simple math, and embedded hardware, we can build systems that feel responsive, expressive, and intuitive — without complexity.
Try It Live
Allow camera access, connect the Arduino, and move your head left, right, up, and down.
An RGB LED is a special type of LED that contains three LEDs inside one package — Red, Green, and Blue. Using these three colours, the Arduino can blend them at different brightness levels to produce hundreds of colours like yellow, cyan, purple, pink, white, sky-blue, etc.
In this example, we are using a Common-Cathode RGB LED, which means:
All three LEDs share one common negative (–) pin
The individual colour pins (R, G, B) must be connected through 220Ω resistors
The Arduino controls brightness using PWM pins
Red → D3
Green → D5
Blue → D6
This forms the basis for colour-mixing projects used in IoT, indicators, robots, and UI feedback systems.
Below, you can see the circuit wiring diagram, the mBlock representation, and the equivalent Arduino IDE code. Finally, you can flash the firmware directly from this page using ExaSub’s online uploader — no Arduino IDE installation required.
Open circuit
Arduino IDE CODE
// RGB LED with Arduino Nano
// Common Cathode RGB LED
// R -> D3, G -> D5, B -> D6
int redPin = 3;
int greenPin = 5;
int bluePin = 6;
void setup() {
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
}
void loop() {
setColor(255, 0, 0); // Red
delay(800);
setColor(0, 255, 0); // Green
delay(800);
setColor(0, 0, 255); // Blue
delay(800);
setColor(255, 255, 0); // Yellow (Red + Green)
delay(800);
setColor(80, 0, 255); // Purple
delay(800);
setColor(0, 255, 255); // Cyan (Green + Blue)
delay(800);
setColor(255, 255, 255); // White
delay(800);
setColor(0, 0, 0); // Off
delay(800);
}
// Function to mix RGB
void setColor(int r, int g, int b) {
analogWrite(redPin, 255 - r); // common cathode → invert logic
analogWrite(greenPin, 255 - g);
analogWrite(bluePin, 255 - b);
}
Mblock Code
Flash Arduino UNO/Nano Directly From Browser Click on Button
Note: Nano with old bootloader is not supported. Use the code with the arduino IDE for the Nano with old bootloader.
#define m1p 7
#define m1n 6
#define m2p 5
#define m2n 4
#define echopin 9
#define trigpin 10
void motor_forward();
void motor_stop();
void motor_left();
void motor_right();
void motor_back();
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(m1p, OUTPUT);
pinMode(m1n, OUTPUT);
pinMode(m2p, OUTPUT);
pinMode(m2n, OUTPUT);
pinMode(echopin, INPUT);
pinMode(trigpin, OUTPUT);
}
long duration, distance;
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(trigpin, LOW);
delayMicroseconds(2);
digitalWrite(trigpin, HIGH);
delayMicroseconds(10);
digitalWrite(trigpin, LOW);
duration = pulseIn(echopin, HIGH);
distance = (duration *0.0343 / 2);
Serial.println(distance);
// Serial.println(" cm");
//delay(1000);
//Serial.println(distance); //print data serially
if (distance > 25) { // if distance is more than 25 move bot forward
motor_forward();
delay(20);
motor_forward();
}
else {
// motor_stop();
//delay(500);
// motor_back();
// delay(3000);
motor_stop(); // if distance is less than 25 move bot right
delay(50);
motor_back();
delay(100);
motor_right();
delay(100);
}
}
void motor_back(){
digitalWrite(m1p, LOW);
digitalWrite(m1n, HIGH);
digitalWrite(m2p, HIGH);
digitalWrite(m2n, LOW);
}
void motor_forward(){
digitalWrite(m1p, HIGH);
digitalWrite(m1n, LOW);
digitalWrite(m2p, LOW);
digitalWrite(m2n, HIGH);
}
void motor_stop(){
digitalWrite(m1p, LOW);
digitalWrite(m1n, LOW);
digitalWrite(m2p, LOW);
digitalWrite(m2n, LOW);
}
void motor_left(){
digitalWrite(m1p, HIGH);
digitalWrite(m1n, LOW);
digitalWrite(m2p, LOW);
digitalWrite(m2n, LOW);
}
void motor_right(){
digitalWrite(m1p, LOW);
digitalWrite(m1n, LOW);
digitalWrite(m2p, HIGH);
digitalWrite(m2n, LOW);
}
Code Explanation
The code is a simple obstacle avoidance program for a robot using an ultrasonic sensor and two motors. Let’s break down the code and explain each section:
In this section, the code defines constants for motor pins (m1p, m1n, m2p, m2n) and pins for the ultrasonic sensor (echopin for echo and trigpin for trigger).
Here, the code declares five functions (motor_forward, motor_stop, motor_left, motor_right, motor_back) that will be used to control the movement of the robot.
In the loop function, the ultrasonic sensor is triggered to measure the distance. If the measured distance is greater than 25, the robot moves forward. Otherwise, it stops, moves back a bit, and then turns right.
These functions define the motor control logic for moving the robot in different directions. For example, motor_forward makes the robot move forward by setting the appropriate motor pins.
In summary, this code implements a basic obstacle avoidance mechanism for a robot using an ultrasonic sensor. If the robot detects an obstacle within 25 cm, it stops, moves back a bit, and then turns right. Otherwise, it continues moving forward. The motor control is achieved through the defined functions that set the appropriate pin states for the motor driver.
Arduino, with its user-friendly environment and a vast array of libraries, opens up a world of possibilities for electronic enthusiasts and hobbyists. One of the key features that makes Arduino a versatile platform is the ability to use interrupts. In this blog post, we will explore the use of attachInterrupt() in the Arduino IDE to toggle an LED with the press of a button.
Understanding attachInterrupt()
The attachInterrupt() function in Arduino is a powerful tool that allows you to execute a specified function (interrupt service routine or ISR) when a certain condition occurs on a digital pin. This capability is particularly useful for handling external events without constantly polling the pin in the main loop, thus improving efficiency and responsiveness.
Before we delve into the code, let’s gather the necessary components for this project:
Arduino board (e.g., Arduino Uno)
LED
Resistor (220-330 ohms)
Push button
Jumper wires
Wiring the Circuit
Connect the components as follows:
Connect the longer leg of the LED (anode) to a current-limiting resistor (220-330 ohms) then the other end of the resistor to pin A2 on the Arduino.
Connect the shorter leg of the LED (cathode) GND on the Arduino.
Connect one side of the push button to pin 2 on the Arduino.
Connect the other side of the push button to the GND on the Arduino.
The Arduino Sketch
Now, let’s dive into the Arduino sketch that utilizes attachInterrupt() to toggle the LED state when the button is pressed.
int led=A2;
int button=2;
volatile byte state = LOW;
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(led, OUTPUT);
pinMode(button, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(2),blink,CHANGE);
}
void blink()
{
state = !state;
}
void loop()
{
digitalWrite(led, !state);
}
Breaking Down the Code
We define led and button as the respective pin numbers for the LED and the push button.
volatile byte state is a variable that holds the state of the LED, and it’s marked as volatile to indicate that it can be modified in an ISR.
In the setup() function, we set the LED pin and button pin modes. Additionally, we attach an interrupt to the button using attachInterrupt(), specifying the function blink to be executed on a state change (CHANGE) of the button pin.
The blink() function toggles the state variable when the interrupt is triggered.
In the loop() function, we continuously update the LED state based on the value of the state variable.
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
Call the uart_init() function in your setup() function to initialize UART communication:
void setup() {
// Other setup code...
uart_init();
// More setup code...
}
Use uart_transmit() to send data:
void loop() {
// Transmit a character
uart_transmit('A');
// Delay between transmissions
_delay_ms(1000);
}
Make sure to connect the appropriate UART pins (TX) to the corresponding pins on your Arduino board. Additionally, set the correct BAUDRATE value based on your desired communication speed.
Complete Code
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << TXEN0); // Enable transmitter
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8-bit data format
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
void setup() {
// Other setup code...
uart_init();
// More setup code...
}
void loop() {
// Transmit a character
uart_transmit('A');
// Delay between transmissions
_delay_ms(1000);
}
Demo Program That Transmits String of Characters
#include <avr/io.h>
#include <util/delay.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << TXEN0); // Enable transmitter
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8-bit data format
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
void uart_transmit_string(const char* str) {
for (size_t i = 0; str[i] != '\0'; ++i) {
uart_transmit(str[i]);
_delay_ms(100); // Delay between character transmissions
}
}
void setup() {
// Initialize UART
uart_init();
}
void loop() {
// Transmit a string
uart_transmit_string("Hello, world!");
// Delay before transmitting again
_delay_ms(2000);
}
Um Daten über UART mit dem ATmega328P Mikrocontroller in AVR C unter Verwendung der Arduino IDE zu übertragen, können Sie die folgenden Schritte befolgen:
Implementieren Sie die Funktion zum Senden von Daten:
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Warten auf leeren Sendepuffer
UDR0 = data; // Daten in den Puffer schreiben und senden
}
Rufen Sie die Funktion uart_init() in Ihrer setup() Funktion auf, um die UART-Kommunikation zu initialisieren:
void setup() {
// Andere Setup-Code...
uart_init();
// Weitere Setup-Code...
}
Verwenden Sie uart_transmit(), um Daten zu senden:
void loop() {
// Ein Zeichen übertragen
uart_transmit('A');
// Verzögerung zwischen den Übertragungen
_delay_ms(1000);
}
Stellen Sie sicher, dass Sie die entsprechenden UART-Pins (TX) mit den entsprechenden Pins auf Ihrem Arduino-Board verbinden. Stellen Sie außerdem den korrekten BAUDRATE-Wert entsprechend Ihrer gewünschten Kommunikationsgeschwindigkeit ein.
Vollständiger Code
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << TXEN0); // Enable transmitter
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8-bit data format
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
void setup() {
// Other setup code...
uart_init();
// More setup code...
}
void loop() {
// Transmit a character
uart_transmit('A');
// Delay between transmissions
_delay_ms(1000);
}
Demo-Programm zum Senden einer Zeichenkette von Zeichen
#include <avr/io.h>
#include <util/delay.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << TXEN0); // Enable transmitter
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8-bit data format
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
void uart_transmit_string(const char* str) {
for (size_t i = 0; str[i] != '\0'; ++i) {
uart_transmit(str[i]);
_delay_ms(100); // Delay between character transmissions
}
}
void setup() {
// Initialize UART
uart_init();
}
void loop() {
// Transmit a string
uart_transmit_string("Hello, world!");
// Delay before transmitting again
_delay_ms(2000);
}
एटीमेगा328पी माइक्रोकंट्रोलर के साथ AVR C और Arduino IDE का उपयोग करके UART के माध्यम से डेटा भेजने के लिए, आप निम्नलिखित चरणों का पालन कर सकते हैं:
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // खाली ट्रांसमिट बफर के लिए प्रतीक्षा करें
UDR0 = data; // डेटा को बफर में डालें, डेटा भेजें
}
आपकी सेटअप() फ़ंक्शन में uart_init() फ़ंक्शन को कॉल करें, UART संचार को प्रारंभ करने के लिए:
void setup() {
// अन्य सेटअप कोड...
uart_init();
// अधिक सेटअप कोड...
}
डेटा भेजने के लिए uart_transmit() का उपयोग करें:
void loop() {
// एक वर्ण भेजें
uart_transmit('A');
// भेजने के बीच में विलंब
_delay_ms(1000);
}
उचित UART पिन (TX) को अपने Arduino बोर्ड के संबंधित पिनों से कनेक्ट करने का सुनिश्चित करें। इसके अलावा, अपनी इच्छित संचार गति के आधार पर सही BAUDRATE मान सेट करें।
पूरा कोड:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << TXEN0); // Enable transmitter
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8-bit data format
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
void setup() {
// Other setup code...
uart_init();
// More setup code...
}
void loop() {
// Transmit a character
uart_transmit('A');
// Delay between transmissions
_delay_ms(1000);
}
वर्ण स्ट्रिंग भेजने का डेमो प्रोग्राम
#include <avr/io.h>
#include <util/delay.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << TXEN0); // Enable transmitter
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // 8-bit data format
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
void uart_transmit_string(const char* str) {
for (size_t i = 0; str[i] != '\0'; ++i) {
uart_transmit(str[i]);
_delay_ms(100); // Delay between character transmissions
}
}
void setup() {
// Initialize UART
uart_init();
}
void loop() {
// Transmit a string
uart_transmit_string("Hello, world!");
// Delay before transmitting again
_delay_ms(2000);
}
Implement functions for transmitting and receiving data:
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // Wait for empty transmit buffer
UDR0 = data; // Put data into the buffer, sends the data
}
uint8_t uart_receive() {
while (!(UCSR0A & (1 << RXC0))); // Wait for data to be received
return UDR0; // Get and return received data from buffer
}
(Optional) Implement a function to transmit a string:
void uart_transmit_string(const char* str) {
for (size_t i = 0; str[i] != '\0'; ++i) {
uart_transmit(str[i]);
}
}
Finally, call the uart_init() function in your setup() function to initialize UART communication:
void setup() {
// Other setup code...
uart_init();
// More setup code...
}
Now, you can use uart_transmit() to send individual characters and uart_receive() to receive data. If needed, you can use uart_transmit_string() to send strings.
Note that the above code assumes you are using the default hardware UART (UART0) on the ATmega328P, and the UART pins (RX and TX) are connected to the corresponding pins on your Arduino board.
Make sure to set the correct BAUDRATE value based on your desired communication speed. Also, ensure that the F_CPU macro is defined with the correct clock frequency of your microcontroller.
Remember to include the necessary header files in your Arduino sketch and define the setup() and loop() functions as required for Arduino compatibility.
Please note that configuring the UART in this way bypasses some of the Arduino’s built-in serial functionality, so you won’t be able to use Serial.print() or Serial.read() with this setup.
Code for a demo program
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
uint8_t uart_receive() {
while (!(UCSR0A & (1 << RXC0)));
return UDR0;
}
void uart_transmit_string(const char* str) {
for (size_t i = 0; str[i] != '\0'; ++i) {
uart_transmit(str[i]);
}
}
void setup() {
// Initialize UART
uart_init();
// Set PB5 (Arduino digital pin 13) as output
DDRB |= (1 << PB5);
}
void loop() {
// Read input from UART
uint8_t receivedData = uart_receive();
// Echo back received data
uart_transmit(receivedData);
// Toggle the built-in LED (PB5) on each received character
PORTB ^= (1 << PB5);
// Delay for a short period to observe the LED blink
_delay_ms(500);
}
In this demo program, the ATmega328P’s UART is initialized in the setup() function, and then in the loop() function, it continuously reads incoming data and sends it back (echo) over UART. Additionally, it toggles the built-in LED (PB5) on each received character, providing a visual indication.
Um die UART-Kommunikation mit dem ATmega328P-Mikrocontroller in AVR C mithilfe der Arduino IDE zu initialisieren, können Sie den folgenden Schritten folgen:
Fügen Sie die erforderlichen Header-Dateien hinzu:
Jetzt können Sie uart_transmit() verwenden, um einzelne Zeichen zu senden, und uart_receive() zum Empfangen von Daten. Bei Bedarf können Sie uart_transmit_string() verwenden, um Zeichenketten zu senden.
Beachten Sie, dass der obige Code davon ausgeht, dass Sie die standardmäßige Hardware-UART (UART0) des ATmega328P verwenden und dass die UART-Pins (RX und TX) mit den entsprechenden Pins auf Ihrem Arduino-Board verbunden sind.
Stellen Sie sicher, dass Sie den korrekten BAUDRATE-Wert entsprechend Ihrer gewünschten Übertragungsgeschwindigkeit festlegen. Stellen Sie außerdem sicher, dass die F_CPU-Makrodefinition die richtige Taktgeschwindigkeit Ihres Mikrocontrollers enthält.
Vergessen Sie nicht, die erforderlichen Header-Dateien in Ihren Arduino-Sketch einzufügen und die setup() und loop() Funktionen gemäß den Anforderungen der Arduino-Kompatibilität zu definieren.
Bitte beachten Sie, dass durch die Konfiguration der UART auf diese Weise einige der integrierten seriellen Funktionen des Arduino umgangen werden. Sie können daher nicht Serial.print() oder Serial.read() mit dieser Konfiguration verwenden.
In diesem Demo-Programm wird die UART des ATmega328P im setup() Funktion initialisiert. In der loop() Funktion liest es kontinuierlich eingehende Daten und sendet sie zurück (Echo) über UART. Darüber hinaus wird die integrierte LED (PB5) bei jedem empfangenen Zeichen umgeschaltet, um eine visuelle Anzeige zu bieten.
ATmega328P माइक्रोकंट्रोलर के साथ AVR C और Arduino IDE का उपयोग करके UART संचार को प्रारंभ करने के लिए, आप निम्नलिखित चरणों का पालन कर सकते हैं:
डेटा भेजने और प्राप्त करने के लिए फ़ंक्शन को अमल में लाएं:
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0))); // खाली भेजने वाले बफ़र के लिए प्रतीक्षा करें
UDR0 = data; // डेटा बफ़र में डेटा डालें, डेटा भेजें
}
uint8_t uart_receive() {
while (!(UCSR0A & (1 << RXC0))); // डेटा प्राप्त होने की प्रतीक्षा करें
return UDR0; // बफ़र से प्राप्त और डेटा लौटाएं
}
(ऐच्छिक) स्ट्रिंग भेजने के लिए एक फ़ंक्शन को अमल में लाएं:
void uart_transmit_string(const char* str) {
for (size_t i =
0; str[i] != '\0'; ++i) {
uart_transmit(str[i]);
}
}
अंतिम रूप में, अपने सेटअप() फ़ंक्शन में uart_init() फ़ंक्शन को बुलाएं और UART संचार को प्रारंभ करें:
void setup() {
// अन्य सेटअप कोड...
uart_init();
// अधिक सेटअप कोड...
}
अब, आप uart_transmit() का उपयोग अक्षरों को भेजने के लिए कर सकते हैं और uart_receive() का उपयोग डेटा प्राप्त करने के लिए कर सकते हैं। आवश्यकता होने पर, आप uart_transmit_string() का उपयोग स्ट्रिंग भेजने के लिए कर सकते हैं।
ध्यान दें कि ऊपर का कोड मानता है कि आप ATmega328P पर डिफ़ॉल्ट हार्डवेयर UART (UART0) का उपयोग कर रहे हैं, और UART पिन (RX और TX) आपके Arduino बोर्ड पर संबंधित पिनों से कनेक्ट हैं।
अपनी Arduino स्केच में आवश्यक हैडर फ़ाइलें शामिल करने और Arduino संगतता के लिए सेटअप() और लूप() फ़ंक्शन को परिभाषित करने के लिए याद रखें।
कृपया ध्यान दें कि इस तरीके से UART को कॉन्फ़िगर करने से अर्डुइनो के कुछ निर्मित सीरियल कार्यक्षमता का बाहर जाना होता है, इसलिए इस सेटअप के साथ Serial.print() या Serial.read() का उपयोग नहीं कर सकेंगे।
डेमो प्रोग्राम के लिए कोड
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#define BAUDRATE 9600
#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1)
void uart_init() {
UBRR0H = (uint8_t)(BAUD_PRESCALLER >> 8);
UBRR0L = (uint8_t)(BAUD_PRESCALLER);
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
}
void uart_transmit(uint8_t data) {
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = data;
}
uint8_t uart_receive() {
while (!(UCSR0A & (1 << RXC0)));
return UDR0;
}
void uart_transmit_string(const char* str) {
for (size_t i = 0; str[i] != '\0'; ++i) {
uart_transmit(str[i]);
}
}
void setup() {
// UART को प्रारंभ करें
uart_init();
// PB5 (Arduino डिजिटल पिन 13) को आउटपुट के रूप में सेट करें
DDRB |= (1 << PB5);
}
void loop() {
// UART से इनपुट पढ़ें
uint8_t receivedData = uart_receive();
// प्राप्त डेटा को वापस भेजें (इको)
uart_transmit(receivedData);
// प्राप्त वर्णकों पर बिल्ट-इन LED (PB5) को टॉगल करें, यह दिखाने के लिए
PORTB ^= (1 << PB5);
// LED ब्लिंक को देखने के लिए थोड़ी सी देरी के लिए विलंब करें
_delay_ms(500);
}
इस डेमो प्रोग्राम में, ATmega328P का UART सेटअप() फ़ंक्शन में प्रारंभित होता है, और फिर लूप() फ़ंक्शन में, यह निरंतर आने वाले डेटा को पढ़ता है और उसे वापस (इको) UART के माध्यम से भेजता है। इसके अलावा, यह प्राप्त प्रत्येक आंकड़े पर बिल्ट-इन LED (PB5) को टॉगल करता है, जिससे एक लैंप एफेक्ट प्रदर्शित होता है।
SONAR uses the concept of ultrasonic waves that get reflected from the object in front of it. And the time it takes between the transmission and reception tells us about the distance it has traveled.
Components Required
Arduino UNO
Servo Motor
Ultrasonic Sensor
Jumper wires
Laptop
Circuit Diagram
After making the connection you have to make a sketch and copy paste the below Arduino code into your arduino and upload the code.
Then you have to extract the processing software and open the processing.exe and copy and paste the processing code given below.
After you done that you have to connect your ardunio to your computer.
Open the arduino software.
Go to the TOOLS > PORTS
In the port list you will the something like com26 or com6
You have to remeber this com## (HERE ## represent the number)
Then in the processing code you have to change this line shown in the figure below
Arduino Code
// Includes the Servo library
#include <Servo.h>.
// Defines Tirg and Echo pins of the Ultrasonic Sensor
const int trigPin = 10;
const int echoPin = 11;
// Variables for the duration and the distance
long duration;
int distance;
Servo myServo; // Creates a servo object for controlling the servo motor
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600);
myServo.attach(12); // Defines on which pin is the servo motor attached
}
void loop() {
// rotates the servo motor from 15 to 165 degrees
for(int i=15;i<=165;i++){
myServo.write(i);
delay(30);
distance = calculateDistance();// Calls a function for calculating the distance measured by the Ultrasonic sensor for each degree
Serial.print(i); // Sends the current degree into the Serial Port
Serial.print(","); // Sends addition character right next to the previous value needed later in the Processing IDE for indexing
Serial.print(distance); // Sends the distance value into the Serial Port
Serial.print("."); // Sends addition character right next to the previous value needed later in the Processing IDE for indexing
}
// Repeats the previous lines from 165 to 15 degrees
for(int i=165;i>15;i--){
myServo.write(i);
delay(30);
distance = calculateDistance();
Serial.print(i);
Serial.print(",");
Serial.print(distance);
Serial.print(".");
}
}
// Function for calculating the distance measured by the Ultrasonic sensor
int calculateDistance(){
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH); // Reads the echoPin, returns the sound wave travel time in microseconds
distance= duration*0.034/2;
return distance;
}
Processing Code
import processing.serial.*; // imports library for serial communication
import java.awt.event.KeyEvent; // imports library for reading the data from the serial port
import java.io.IOException;
Serial myPort; // defines Object Serial
// defubes variables
String angle="";
String distance="";
String data="";
String noObject;
float pixsDistance;
int iAngle, iDistance;
int index1=0;
int index2=0;
PFont orcFont;
void setup() {
size (1200, 700); // ***CHANGE THIS TO YOUR SCREEN RESOLUTION***
smooth();
myPort = new Serial(this,"COM18", 9600); // starts the serial communication
myPort.bufferUntil('.'); // reads the data from the serial port up to the character '.'. So actually it reads this: angle,distance.
}
void draw() {
fill(98,245,31);
// simulating motion blur and slow fade of the moving line
noStroke();
fill(0,4);
rect(0, 0, width, height-height*0.065);
fill(98,245,31); // green color
// calls the functions for drawing the radar
drawRadar();
drawLine();
drawObject();
drawText();
}
void serialEvent (Serial myPort) { // starts reading data from the Serial Port
// reads the data from the Serial Port up to the character '.' and puts it into the String variable "data".
data = myPort.readStringUntil('.');
data = data.substring(0,data.length()-1);
index1 = data.indexOf(","); // find the character ',' and puts it into the variable "index1"
angle= data.substring(0, index1); // read the data from position "0" to position of the variable index1 or thats the value of the angle the Arduino Board sent into the Serial Port
distance= data.substring(index1+1, data.length()); // read the data from position "index1" to the end of the data pr thats the value of the distance
// converts the String variables into Integer
iAngle = int(angle);
iDistance = int(distance);
}
void drawRadar() {
pushMatrix();
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
noFill();
strokeWeight(2);
stroke(98,245,31);
// draws the arc lines
arc(0,0,(width-width*0.0625),(width-width*0.0625),PI,TWO_PI);
arc(0,0,(width-width*0.27),(width-width*0.27),PI,TWO_PI);
arc(0,0,(width-width*0.479),(width-width*0.479),PI,TWO_PI);
arc(0,0,(width-width*0.687),(width-width*0.687),PI,TWO_PI);
// draws the angle lines
line(-width/2,0,width/2,0);
line(0,0,(-width/2)*cos(radians(30)),(-width/2)*sin(radians(30)));
line(0,0,(-width/2)*cos(radians(60)),(-width/2)*sin(radians(60)));
line(0,0,(-width/2)*cos(radians(90)),(-width/2)*sin(radians(90)));
line(0,0,(-width/2)*cos(radians(120)),(-width/2)*sin(radians(120)));
line(0,0,(-width/2)*cos(radians(150)),(-width/2)*sin(radians(150)));
line((-width/2)*cos(radians(30)),0,width/2,0);
popMatrix();
}
void drawObject() {
pushMatrix();
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
strokeWeight(9);
stroke(255,10,10); // red color
pixsDistance = iDistance*((height-height*0.1666)*0.025); // covers the distance from the sensor from cm to pixels
// limiting the range to 40 cms
if(iDistance<40){
// draws the object according to the angle and the distance
line(pixsDistance*cos(radians(iAngle)),-pixsDistance*sin(radians(iAngle)),(width-width*0.505)*cos(radians(iAngle)),-(width-width*0.505)*sin(radians(iAngle)));
}
popMatrix();
}
void drawLine() {
pushMatrix();
strokeWeight(9);
stroke(30,250,60);
translate(width/2,height-height*0.074); // moves the starting coordinats to new location
line(0,0,(height-height*0.12)*cos(radians(iAngle)),-(height-height*0.12)*sin(radians(iAngle))); // draws the line according to the angle
popMatrix();
}
void drawText() { // draws the texts on the screen
pushMatrix();
if(iDistance>40) {
noObject = "Out of Range";
}
else {
noObject = "In Range";
}
fill(0,0,0);
noStroke();
rect(0, height-height*0.0648, width, height);
fill(98,245,31);
textSize(25);
text("10cm",width-width*0.3854,height-height*0.0833);
text("20cm",width-width*0.281,height-height*0.0833);
text("30cm",width-width*0.177,height-height*0.0833);
text("40cm",width-width*0.0729,height-height*0.0833);
textSize(40);
text("exasub.com", width-width*0.875, height-height*0.0277);
text("Angle: " + iAngle +" °", width-width*0.48, height-height*0.0277);
text("Distance: ", width-width*0.26, height-height*0.0277);
if(iDistance<40) {
text(" " + iDistance +" cm", width-width*0.225, height-height*0.0277);
}
textSize(25);
fill(98,245,60);
translate((width-width*0.4994)+width/2*cos(radians(30)),(height-height*0.0907)-width/2*sin(radians(30)));
rotate(-radians(-60));
text("30°",0,0);
resetMatrix();
translate((width-width*0.503)+width/2*cos(radians(60)),(height-height*0.0888)-width/2*sin(radians(60)));
rotate(-radians(-30));
text("60°",0,0);
resetMatrix();
translate((width-width*0.507)+width/2*cos(radians(90)),(height-height*0.0833)-width/2*sin(radians(90)));
rotate(radians(0));
text("90°",0,0);
resetMatrix();
translate(width-width*0.513+width/2*cos(radians(120)),(height-height*0.07129)-width/2*sin(radians(120)));
rotate(radians(-30));
text("120°",0,0);
resetMatrix();
translate((width-width*0.5104)+width/2*cos(radians(150)),(height-height*0.0574)-width/2*sin(radians(150)));
rotate(radians(-60));
text("150°",0,0);
popMatrix();
}