When you create a parametric model in FreeCAD. The model will look very bland. You can add different colors to your 3d model face and you can even make your model transparent to help view the underneath wireframes.
But when you have to present the work to a more general audience you can’t really show a dull-colored 3D object. You need to have the 3D model in some rendering environment which will add colors, shadows, lights, a camera, etc.
As you can see in the above image it is not very pleasing to look at. It will not look very good on a website or printed in a pamphlet.
So we export the 3d model from the FreeCAD to a .stl file.
That STL file will be imported into the blender software.
There in the blender environment, we can add different lights, cameras, colors, and textures to make it look more pleasing to view and create a nice scene.
As you can see these images are more presentable to a wider audience.
They are two software packages designed by two independent teams. Both of them are free to use.
To create a product you will need an enclosure that will house all the essential components inside it. And this enclosure can be built in FreeCAD.
I am using FreeCAD 0.20.1
There are some Addons that I have installed.
You can install Addon from “Tools > Addon Manager”
KiCad StepUP workbench
Glass
PieMenu
A2Plus (for making assembly from different individual parts)
Fasteners Workbench (Easy to use the preconstructed model of many standard nuts, bolts, screws, washers, etc.)
KiCad StepUP workbench provides an ECAD-MCAD collaboration tool.
From what I learned in FreeCAD you create Sketch that can be exported to KiCad PCB.
The KiCad uses the Sketch created in the FreeCAD as Edge Cuts.
Edge Cuts are the outline of the PCB in which all your components along with all the tracks, via, hole, and other miscellaneous items must reside.
Youtube video from user mathcodeprint
This video demonstrates a basic example.
It is not a perfect collaborating tool. There are other software tools available from big companies but they are not affordable for a budding engineer.
The ECAD/MCAD collabration proccess:
Design your schematic in Kicad.
Assign Footprint and make sure that each footprint have a 3d model assigned to its footprint.
make a pcb and update the component from the schematics. place a grid origin. Using the grid origin draw a rectangle in the edge cut layer.
Save the pcb.
After doing the above steps open the PCB in the FreeCAD KiCadStepUp workbench.
Load the PCB into the freecad environment using the “ksu PushPull > Load Board” option
Make changes to the sketch and the 3d model.
If you select a 3d model and make changes to its position.
To make changes to the 3d model. You have to select that particular model. And then you have to select the model from the Model view. Right click on the model in the Model view and select Transform.
Three orthogonal arrow will be preseneted to you in three different color. You can move the model by selecting the conical arrow heads.
You have to push the changes by selecting that model into the kicad pcb.
After you have saved the kicad will automatically adust its footprint automatically.
It is this PUSH PULL method of making the changes to your pcb dimension and component positions.
Whenever you have to mount a pcb in place. Most of the time it is easier if we use the screws it on/in the enclosures.
There are standards for screws which are already available in the market. Which will reduce the BOM cost.
If you happen to calculate the screw dimensions based on the mechanical stresses. That would be the best. Since it gives you an optimum result in terms of material choice, strength and cost of the screw.
But in when you want to just mount the PCB on a plastic enclosure then you need to know the dimension in order to provide the provisions for the holes.
There are a few websites which will help in finding the appropriate size screw.
MC34063 is an integrated circuit which has all the essential components to make a DC-DC switching voltage regulator.
There are other popular switching regulators in the market. And the mc34063 IC is not the very best. But this chip is cheap.
As you can see from the block diagram. This chip contains an AND gate, an SR latch, two transistors, A 1.25V reference voltage and an op-amp configured as a comparator.
You can just choose any value of the component and think they will work.
There are very basic calculations which you need to perform in sequential order. The calculations are given in the datasheet.
You need to calculate in this particular sequence only.
ton/toff
(ton + toff)
toff
ton
CT
Ipk(switch)
Rsc
L(min)
Co
You can also take the help of an online calculator for mc34063
By following you can create the cheapest switching power supply.
There are a few considerations with this integrated circuit.
There is a lot of switching noise. So you will need a bigger capacitor if you want to dampen those noise signals.
If you want to reduce the size of the inductor used. Then you will need to use a higher switching frequency.
You need to remember that the L(min) you have selected is for a particular base frequency. The maximum frequency will be set up according to the load connected to it. And the maximum frequency of the oscillator is 100KHz according to the datasheet.
Sometimes we are so busy in our work or in our day-to-day life that we forget to water our plants on time. Or in the summertime when the plants need additional water to sustain themselves in the high-temperature region like New Delhi.
This is a simple project that one can assemble and implement within a few minutes.
To make this project you will need some modules which are readily available in the market.
Arduino UNO x 1
Moisture Sensor x 1
A 5V relay x 1
5V water pump x 1
A short length of plastic or rubber tube x 1 – 1.5m
Rechargeable Power Bank x 1
#define sense A0
#define relay 9
void setup() {
// put your setup code here, to run once:
pinMode(sense, INPUT);
pinMode(relay, OUTPUT);
Serial.begin(9600);
}
int val;
void loop() {
// put your main code here, to run repeatedly:
val = analogRead(sense);
Serial.println(val);
if (val < 600) /* adjust this value to control how much soil must be moist */
{
digitalWrite(relay, HIGH);
}
else
{
digitalWrite(relay, LOW);
}
delay(400);
}
On the STM32F429 board, there is one I2c extension connector. This connector has eight pins. Which is used to connect to other I2C peripherals such as RTC, EEPROM and other microcontrollers etc.
DS1307 connected to I2C
In the hardware schematics, it is labelled as ACP/RF E2P connector.
The I2C3 SDA and SCL lines are pulled up via a 4.7 k ohm resistor to VCC 3.3V.
This is the basic code that I used to set/get the data in/from the DS1307 via I2c.
/* USER CODE BEGIN 4 */
struct Time{
uint8_t sec;
uint8_t min;
uint8_t hour;
uint8_t weekday;
uint8_t day;
uint8_t month;
uint8_t year;
};
/* USER CODE END 4 */
/* USER CODE BEGIN Header_StartDefaultTask */
/**
* @brief Function implementing the defaultTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartDefaultTask */
void StartDefaultTask(void const * argument)
{
/* init code for USB_HOST */
MX_USB_HOST_Init();
/* USER CODE BEGIN 5 */
char buff[30];
uint8_t *ptr1;
uint8_t *ptr2;
ptr2 = (uint8_t *)buff;
struct Time Set_time,Get_Time;
Set_time.sec = 0;
Set_time.min = 0;
Set_time.hour = 0;
Set_time.day = 0;
Set_time.month = 04;
Set_time.year = 0;
Set_time.weekday = 0;
HAL_I2C_Mem_Write(&hi2c3, 0xd0, 0, 1,&Set_time.sec, 7, 1000);
/* Infinite loop */
for(;;)
{
HAL_I2C_Mem_Read(&hi2c3, 0xD1, 0, 1, &Get_Time.sec, 7, 1000);
osDelay(1000);
ptr1 = (uint8_t *)"Hello\n";
HAL_UART_Transmit(&huart1, ptr1, 6, 1000);
sprintf(buff,"%02x:%02x:%02x - %02x - %02x/%02x/%02x \n",
Get_Time.hour,
Get_Time.min,
Get_Time.sec,
Get_Time.weekday,
Get_Time.day,
Get_Time.month,
Get_Time.year);
HAL_UART_Transmit(&huart1, ptr2,26, 1000);
}
/* USER CODE END 5 */
}
In this code, I created a structure for the time, weekday and date. Which is similar to the internal registers of DS1307.
The Structure then creates two instances called set_time and Get_time. The Set_time object is filled with the values and then its location is transfered to the HAL_I2C_Mem_Write function. Which sends this data through polling to the DS1307.
Similarly the Get_time structure is used to retrieve the data from the DS1307 using the HAL_I2C_Mem_Read function. Which reads 7 bytes from the DS1307.
The retrieved time and date are then sent via the UART to display on a terminal.
AT24C32 is an i2c compatible serial EEPROM which can be programmed using a microcontroller.
The AT24C32 provides 32,768 bits of serial electrically erasable and programmable read-only memory (EEPROM). The device’s cascadable feature allows up to 8 devices to share a common 2- wire bus. The device is optimized for use in many industrial and commercial applications where low power and low voltage operation are essential. The AT24C32/64 is available in space-saving 8-pin JEDEC PDIP, 8-pin JEDEC SOIC, 8-pin EIAJ SOIC, and 8-pin TSSOP (AT24C64) packages and is accessed via a 2-wire serial interface. In addition, the entire family is available in 2.7V (2.7V to 5.5V) and 1.8V (1.8V to 5.5V) versions.
/*
* main.c
*
* Created: 8/24/2022 10:53:05 PM
* Author: abhay
*/
#define F_CPU 16000000
#include <xc.h>
#include "util/delay.h"
#include "uart.h"
#include <stdio.h>
#define FALSE 0
#define TRUE 1
void EEOpen();
uint8_t EEWriteByte(uint16_t,uint8_t);
uint8_t EEReadByte(uint16_t address);
int main(void)
{
UART_Init();
EEOpen();
char buff[20];
sprintf(buff,"Hello EEPROM TEST \nBy: \t ABHAY");
UART_SendString(buff);
//Fill whole eeprom 32KB (32768 bytes)
//with number 7
uint16_t address;
char failed;
failed = 0 ;
for(address=0;address< (32768);address++)
{
sprintf(buff,"address = %d \n",address);
UART_SendString(buff);
if(EEWriteByte(address,5)==0)
{
//Write Failed
sprintf(buff,"write Failed %x \n",address);
UART_SendString(buff);
failed = 1;
break;
}
}
if(!failed)
{
//We have Done it !!!
sprintf(buff,"Write Success !\n");
UART_SendString(buff);
}
while(1)
{
//TODO:: Please write your application code
//Check if every location in EEPROM has
//number 7 stored
failed=0;
for(address=0;address < 32768 ; address++)
{
if(EEReadByte(address)!=5)
{
//Failed !
sprintf(buff,"Verify Failed %x \n",address);
UART_SendString(buff);
failed=1;
break;
}
}
if(!failed)
{
//We have Done it !!!
sprintf(buff,"Write Success !\n");
UART_SendString(buff);
}
}
}
void EEOpen()
{
//Set up TWI Module
TWBR0 = 5;
TWSR0 &= (~((1<<TWPS1)|(1<<TWPS0)));
}
uint8_t EEWriteByte(uint16_t address,uint8_t data)
{
do
{
//Put Start Condition on TWI Bus
TWCR0=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x08)
return FALSE;
//Now write SLA+W
//EEPROM @ 00h
TWDR0=0b10100000;
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
}while((TWSR0 & 0xF8) != 0x18);
//Now write ADDRH
TWDR0=(address>>8);
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x28)
return FALSE;
//Now write ADDRL
TWDR0=(address);
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x28)
return FALSE;
//Now write DATA
TWDR0=(data);
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x28)
return FALSE;
//Put Stop Condition on bus
TWCR0=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
//Wait for STOP to finish
while(TWCR0 & (1<<TWSTO));
//Wait untill Writing is complete
_delay_ms(1);
//Return TRUE
return TRUE;
}
uint8_t EEReadByte(uint16_t address)
{
uint8_t data;
//Initiate a Dummy Write Sequence to start Random Read
do
{
//Put Start Condition on TWI Bus
TWCR0=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x08)
return FALSE;
//Now write SLA+W
//EEPROM @ 00h
TWDR0=0b10100000;
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
}while((TWSR0 & 0xF8) != 0x18);
//Now write ADDRH
TWDR0=(address>>8);
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x28)
return FALSE;
//Now write ADDRL
TWDR0=(address);
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x28)
return FALSE;
//*************************DUMMY WRITE SEQUENCE END **********************
//Put Start Condition on TWI Bus
TWCR0=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x10)
return FALSE;
//Now write SLA+R
//EEPROM @ 00h
TWDR0=0b10100001;
//Initiate Transfer
TWCR0=(1<<TWINT)|(1<<TWEN);
//Poll Till Done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x40)
return FALSE;
//Now enable Reception of data by clearing TWINT
TWCR0=(1<<TWINT)|(1<<TWEN);
//Wait till done
while(!(TWCR0 & (1<<TWINT)));
//Check status
if((TWSR0 & 0xF8) != 0x58)
return FALSE;
//Read the data
data=TWDR0;
//Put Stop Condition on bus
TWCR0=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
//Wait for STOP to finish
while(TWCR0 & (1<<TWSTO));
//Return TRUE
return data;
}
The DS1307 Real Time Clock uses I2c communication lines to connect with the microcontroller.
I2C uses two lines commonly known as Serial Data/Address or SDA and Serial Clock Line or SCL. The two lines SDA and SCL are standardised and they are implemented using either an open collector or open drain configuration. What this means is that you need to pull these lines UP to VCC. For complete information on how the i2C is implemented in ATmega328PB, you need to go through the section of the datasheet called TWI or Two-Wire Serial Interface.
To start I2C in ATmega328PB, first the SCL frequency needs to set which must be under 100KHz .
To set the SCL frequency you set two registers TWBR0 and TWSR0.
TWSR0 has two bit 0 and bit 1; which sets the prescaler for the clock to the TWI.
Then TWBR0 needs to be set which can anything from 0 to 255.
THen you need to write the I2C functions for start, repeated start, data trasmission and recepetion and stop.
/*
* main.c
*
* Created: 8/20/2022 2:08:09 PM
* Author: abhay
*/
#define F_CPU 16000000
#include <xc.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "util/delay.h"
#include "uart.h"
#define Device_Write_address 0xD0 /* Define RTC DS1307 slave address for write operation */
#define Device_Read_address 0xD1 /* Make LSB bit high of slave address for read operation */
#define TimeFormat12 0x40 /* Define 12 hour format */
#define AMPM 0x20
int second,minute,hour,day,date,month,year;
void TWI_init_master(void) // Function to initialize master
{
TWBR0=127; // Bit rate
TWSR0= (1<<TWPS1)|(1<<TWPS0); // Setting prescalar bits
// SCL freq= F_CPU/(16+2(TWBR).4^TWPS)
}
uint8_t I2C_Start(char write_address); /* I2C start function */
uint8_t I2C_Repeated_Start(char read_address); /* I2C repeated start function */
void I2C_Stop(); /* I2C stop function */
void I2C_Start_Wait(char write_address); /* I2C start wait function */
uint8_t I2C_Write(char data); /* I2C write function */
int I2C_Read_Ack(); /* I2C read ack function */
int I2C_Read_Nack(); /* I2C read nack function */
void RTC_Read_Clock(char read_clock_address)
{
I2C_Start(Device_Write_address); /* Start I2C communication with RTC */
I2C_Write(read_clock_address); /* Write address to read */
I2C_Repeated_Start(Device_Read_address); /* Repeated start with device read address */
second = I2C_Read_Ack(); /* Read second */
minute = I2C_Read_Ack(); /* Read minute */
hour = I2C_Read_Nack(); /* Read hour with Nack */
I2C_Stop(); /* Stop i2C communication */
}
void RTC_Read_Calendar(char read_calendar_address)
{
I2C_Start(Device_Write_address);
I2C_Write(read_calendar_address);
I2C_Repeated_Start(Device_Read_address);
day = I2C_Read_Ack(); /* Read day */
date = I2C_Read_Ack(); /* Read date */
month = I2C_Read_Ack(); /* Read month */
year = I2C_Read_Nack(); /* Read the year with Nack */
I2C_Stop(); /* Stop i2C communication */
}
int main(void)
{
char buffer[20];
const char* days[7]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
UART_Init();
TWI_init_master();
sei();
I2C_Start(Device_Write_address); /* Start I2C communication with RTC */
I2C_Write(0); /* Write address to read */
I2C_Write(0x00); //sec
I2C_Write(0x00); //min /* Write address to read */
I2C_Write(0x17); //hour
I2C_Write(0x03); //tuesday
I2C_Write(0x23); //day
I2C_Write(0x09); //month
I2C_Write(0x21); //year
I2C_Stop(); /* Stop i2C communication */
while(1)
{
//TODO:: Please write your application code
RTC_Read_Clock(0);
//UART_Transmit(second);
sprintf(buffer, "\n%02x:%02x:%02x ", (hour & 0b00011111), minute, second);
UART_SendString(buffer);
RTC_Read_Calendar(3);
sprintf(buffer, "%02x/%02x/%02x %s", date, month, year,days[day-1]);
UART_SendString(buffer);
_delay_ms(1000);
}
}
uint8_t I2C_Start(char write_address) /* I2C start function */
{
uint8_t status; /* Declare variable */
TWCR0 = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT); /* Enable TWI, generate start condition and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (start condition) */
status = TWSR0 & 0xF8; /* Read TWI status register with masking lower three bits */
if (status != 0x08) /* Check weather start condition transmitted successfully or not? */
return 0; /* If not then return 0 to indicate start condition fail */
TWDR0 = write_address; /* If yes then write SLA+W in TWI data register */
TWCR0 = (1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (Write operation) */
status = TWSR0 & 0xF8; /* Read TWI status register with masking lower three bits */
if (status == 0x18) /* Check weather SLA+W transmitted & ack received or not? */
return 1; /* If yes then return 1 to indicate ack received i.e. ready to accept data byte */
if (status == 0x20) /* Check weather SLA+W transmitted & nack received or not? */
return 2; /* If yes then return 2 to indicate nack received i.e. device is busy */
else
return 3; /* Else return 3 to indicate SLA+W failed */
}
uint8_t I2C_Repeated_Start(char read_address) /* I2C repeated start function */
{
uint8_t status; /* Declare variable */
TWCR0 = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT); /* Enable TWI, generate start condition and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (start condition) */
status = TWSR0 & 0xF8; /* Read TWI status register with masking lower three bits */
if (status != 0x10) /* Check weather repeated start condition transmitted successfully or not? */
return 0; /* If no then return 0 to indicate repeated start condition fail */
TWDR0 = read_address; /* If yes then write SLA+R in TWI data register */
TWCR0 = (1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (Write operation) */
status = TWSR0 & 0xF8; /* Read TWI status register with masking lower three bits */
if (status == 0x40) /* Check weather SLA+R transmitted & ack received or not? */
return 1; /* If yes then return 1 to indicate ack received */
if (status == 0x20) /* Check weather SLA+R transmitted & nack received or not? */
return 2; /* If yes then return 2 to indicate nack received i.e. device is busy */
else
return 3; /* Else return 3 to indicate SLA+W failed */
}
void I2C_Stop() /* I2C stop function */
{
TWCR0=(1<<TWSTO)|(1<<TWINT)|(1<<TWEN); /* Enable TWI, generate stop condition and clear interrupt flag */
while(TWCR0 & (1<<TWSTO)); /* Wait until stop condition execution */
}
void I2C_Start_Wait(char write_address) /* I2C start wait function */
{
uint8_t status; /* Declare variable */
while (1)
{
TWCR0 = (1<<TWSTA)|(1<<TWEN)|(1<<TWINT); /* Enable TWI, generate start condition and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (start condition) */
status = TWSR0 & 0xF8; /* Read TWI status register with masking lower three bits */
if (status != 0x08) /* Check weather start condition transmitted successfully or not? */
continue; /* If no then continue with start loop again */
TWDR0 = write_address; /* If yes then write SLA+W in TWI data register */
TWCR0 = (1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (Write operation) */
status = TWSR0 & 0xF8; /* Read TWI status register with masking lower three bits */
if (status != 0x18 ) /* Check weather SLA+W transmitted & ack received or not? */
{
I2C_Stop(); /* If not then generate stop condition */
continue; /* continue with start loop again */
}
break; /* If yes then break loop */
}
}
uint8_t I2C_Write(char data) /* I2C write function */
{
uint8_t status; /* Declare variable */
TWDR0 = data; /* Copy data in TWI data register */
TWCR0 = (1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (Write operation) */
status = TWSR0 & 0xF8; /* Read TWI status register with masking lower three bits */
if (status == 0x28) /* Check weather data transmitted & ack received or not? */
return 0; /* If yes then return 0 to indicate ack received */
if (status == 0x30) /* Check weather data transmitted & nack received or not? */
return 1; /* If yes then return 1 to indicate nack received */
else
return 2; /* Else return 2 to indicate data transmission failed */
}
int I2C_Read_Ack() /* I2C read ack function */
{
TWCR0=(1<<TWEN)|(1<<TWINT)|(1<<TWEA); /* Enable TWI, generation of ack and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (read operation) */
return TWDR0; /* Return received data */
}
int I2C_Read_Nack() /* I2C read nack function */
{
TWCR0=(1<<TWEN)|(1<<TWINT); /* Enable TWI and clear interrupt flag */
while (!(TWCR0 & (1<<TWINT))); /* Wait until TWI finish its current job (read operation) */
return TWDR0; /* Return received data */
}
When you enable the communication using the UART. You have the flexibility to either use the Polling or Interrupt method to continue with your programming.
Polling halts the execution of the program and waits for the UART peripheral to receive something so that program execution must continue. But it eats a lot of the computing time.
So, Interrupt Service Routine is written and implemented such the program execution does not stop. It will stop when there is an interrupt and when there is data in the UDR0 register of UART. Then the ISR will execute and then transfer the control to the main program. Which saves a lot of computing time.
you have to add an interrupt library in your program.
#include <avr/interrupt.h>
Then you need to enable the Global interrupt flag.
.
.
.
int main()
{
.
.
.
sei(); // This is Set Enable Interryupt
while(1)
{
// This is your application code.
}
}
Then you need to enable the UART receive complete interrupt. by setting ‘1’ to RXCIE0 bit of USCR0B register.
Write the ISR function which takes “USART0_RX_vect” as the argument.
The above code shows you how to implement UART receive complete ISR. It is not a full initialisation code. You still have to write the UBRR and the frame control to enable the uart peripheral.
I have two PC mice one is Belkin which is bought in 2012, and the other one is HP which I bought in 2019. Both the mouse had a similar problem. Everything was working perfectly fine. But suddenly their left button started behaving in a weird manner. When i click on an object and try to hold the object. The button loses the signal and then it tries again. It also does double clicking. Most of the time it double-clicks whenever you try to do a single click.
I opened the mouse and then i opened the switch housing and just rubbed the contact so that any deposit would be removed. After that, I put the mouse back together. And it started working normally.
You can follow the instruction given in the video below.