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.
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.
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.
I recently bought a few Arduino Uno clones. They were not cheap. They utilise the ch34 IC, which is a USB to UART solution. They all have SMD atmega328pb soldered on them.
The problem is that two of them stopped working with the Arduino ide. On inspection, i found out that my software was not updated so firstly I updated the software which now includes a configuration for the atmega328pb.
But somehow the internal bootloader in these SMD chips got corrupted and it stopped working. I then probed the chip with AVRdude prograamer.
Found that the chip is atmega328pb. The configurations were not included at the time of installation. But the avrdude program allows you added other avr parts from Atmel.
An LM358p is a dual opamp IC which I used in a single supply configuration. I drive the LM358 just shy of its absolute maximum voltage which is +30V. So I gave I supplied 28.8V (+-0.1V). It works flawless but the power supply is a Meanwell switching supply which introduces transient when plugging into the mains supply.
The transient arise when I was plugging in the AC wire to the mains. I used an anchor 6A 3-pin male plug for connection. It was at the brief moment when the transient arise.
The transient which arises apparently has enough power that it blew the epoxy off the silicon and it did with a loud bang.
Blown LM358P due to transients
Doing rough calculation at the moment this happened
Let’s say the transient is double the supply voltage of = 2 x 28.9 V= 57.8V
let’s say the current drawn by the IC is 40mA which is its absolute maximum.
power = voltage x current = 57.8V x 40mA = 2.312W
so for a brief moment, this 2W is radiated by the silicon chip. Which caused the heating up of the epoxy and generating enough expanding force which blew out like that.
but let’s take a more reasonable transient voltage(ISO 7637-2: 2011) of approximately 110V at a rise time of 0.5uS.