• Standard Screws

    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.

    https://www.fasteners.eu/standards/ISO/

  • MC34063 DC-DC Step-Down Voltage Regulator

    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.

    1. ton/toff
    2. (ton + toff)
    3. toff
    4. ton
    5. CT
    6. Ipk(switch)
    7. Rsc
    8. L(min)
    9. Co

    You can also take the help of an online calculator for mc34063

    http://www.nomad.ee/micros/mc34063a/

    or you can create a spreadsheet.

    You must read the SLVA252B Application of the MC34063 Switching Regulator

    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.

  • How to make a plant watering system using Arduino Uno

    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);
    }
  • How to connect STM32F429I-DISC1 board to DS1307 using I2C

    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.

  • How to use AT24C32 EEPROM with ATmega328PB in Microchip Studio

    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;
    }
    

  • How to use DS1307 RTC with ATmega328PB via I2C in Microchip Studio

    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 */
    }
    
  • How to use UART Receive complete ISR of ATmega328PB using microchip studio

    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.

    char Received_char;
    ISR(USART0_RX_vect)
    {
    	Received_char = UDR0;
    }
    
    int main()
    {
    UCSR0B = (1 << RXCIE0)|(1<<RXEN0)|(1<<TXEN0); 
    .
    .
    .
    sei();
    while(1);
    {
    }
    
    }

    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.

  • Mouse Double Clicking Problem Solved

    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.

  • How to use internal temperature sensor of ATmega328pb

    ATmega328PB is a new semiconductor microcontroller from Microchip semiconductors. I have used its previous generation which is ATmega328 and ATmega328P. They were usually found on Arduino Uno and Arduino nano.

    This new IC has a temperature sensor built into it. Which is handy for measuring the die temperature. Which can make device stable in high-temperature design. It is not accurate as a dedicated temperature sensor. But it gives you a rough idea. Using this you can the processes.

    It is not an Ambient temperature Sensor.

    /*
     * main.c
     *
     * Created: 8/15/2022 4:06:41 PM
     *  Author: abhay
     */ 
    #define F_CPU 16*1000000
    #include <xc.h>
    #include "uart.h"
    #include "util/delay.h"
    #include <stdlib.h>
    long Ctemp;
    unsigned int Ftemp;
    
    int main(void)
    {
    		DDRD &= ~(1 << DDD0);							// PD0 - Rx Input
    		DDRD |= (1 << DDD1);							// PD1 - Tx Ouput
    		USART_Init();
    		
    	/* Replace with your application code */
    	ADMUX = (1<<REFS1) | (1<<REFS0) | (0<<ADLAR) | (1<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0);
    	ADCSRA =  (1<<ADPS2) |(1<<ADPS1) | (1<<ADEN);
    	
    	ADCSRA |= (1<<ADSC);
    	
    	while ((ADCSRA & (1<<ADSC)) !=0);
    	
    	while (1)
    	{
    		ADCSRA |= (1<<ADSC);
    		while ((ADCSRA & (1<<ADSC)) !=0);
    		
    		Ctemp = ((ADC - 247)/1.22)*1000;
    		Ftemp = (Ctemp * 1.8) + 32;
    		
    		USART_Transmit( (((int)Ctemp/100000)%10) + 48);
    		USART_Transmit( (((int)Ctemp/10000)%10) + 48);
    		USART_Transmit( (((int)Ctemp/1000)%10) + 48);
    		USART_Transmit('.');
    		USART_Transmit( (((int)Ctemp/100)%10) + 48);
    		USART_Transmit( (((int)Ctemp/10)%10) + 48);
    		USART_Transmit( ((int)Ctemp%10) + 48);
    		
    		USART_Transmit('\n');
    		_delay_ms(1000);
    	}
    	return -1;
    }
    
  • How to add USBASP as External Tool in Microchip studio

    Download microchip studio from here https://www.microchip.com/en-us/tools-resources/develop/microchip-studi

    Install the program.

    I use USBASP to program AVR ATmega328pb.

    Go to Tools > External Tools > ADD

    Command: location of avrdude

    C:\WinAVR-20100110\bin\avrdude.exe

    Arguments:

    -c usbasp -p m328pb -U flash:w:$(ProjectDir)Debug\$(TargetName).hex:i

    Check the Use Output window to be able to see the output of the avrdude inside the microchip studio terminal.