I have an Arduino project that is using an ATtiny13A to control a power button. The system is powered using a single cell lipo with a nominal voltage of 3.7V. Here is the schematic and layout of the area in question, they are both clickable to see the full image (the usb charger system on the far left of the schematic image and the boost converter are not shown in the layout image as both of those system have been tested and work properly).
In the image above my board design is a two layer board. Most of signal traces are on the top layer where most of the components are placed (red), and the bottom layer is a universal ground layer for every component on the board, shown in green. As the title says I’m using an ATtiny13A and I am using ICSP to upload code to the chip. The BMS is ran using a FS312F-G as the IC, and a FS8205A N-channel MOSFET. I’m using a KIA3415 P-channel MOSFET to control whether power reaches the boost converter or not using the ATtiny13A pin 3, labeled “GATE” with pin 2 labeled “BTN” acting as the external interrupt pin which is connected to the power switch located on the back side of the board.
The ATtiny13A is programmed with the following code:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#define BTN 3
#define GATE 4
#define timer_init() (TIMSK0 |= (1 << OCIE0A))
#define BTN_HOLD_MS 1500 // Press button for 1 second
enum Device_Status
{
POWER_OFF,
RUNNING
};
enum Btn_Status
{
BTN_UP,
BTN_DOWN,
BTN_IGNORE
};
void setup()
{
sei(); // Enable interrupts
PORTB |= (1 << BTN); // Enable PULL_UP resistor
GIMSK |= (1 << PCIE); // Enable Pin Change Interrupts
PCMSK |= (1 << BTN); // Use PCINTn as interrupt pin (Button I/O pin)
TCCR0A |= (1 << WGM01); // Set CTC mode on Timer 1
TIMSK0 |= (1 << OCIE0A); // Enable the Timer/Counter0 Compare Match A interrupt
TCCR0B |= (1 << CS01); // Set prescaler to 8
OCR0A = 125; // Set the output compare reg so tops at 1 ms
DDRB |= (1 << GATE); // replaces pinMode(GATE, OUTPUT);
PORTB |= (1 << GATE); // replaces digitalWrite(GATE, HIGH);
}
void power_off()
{
PORTB |= (1 << GATE);
cli(); // Disable interrupts before next commands
wdt_disable(); // Disable watch dog timer to save power
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode power down
sleep_enable();
sleep_bod_disable(); // Disable brown-out detector
sei(); // Enable interrupts
sleep_cpu();
sleep_disable();
}
volatile unsigned int timer; // milliseconds counter
Btn_Status btn_status; // Status of the button
int main()
{
setup();
Device_Status status = POWER_OFF; // Set start ON or OFF when power is connected
btn_status = BTN_UP;
DDRB |= (1 << GATE); // Set as output
for (;;)
{
if (btn_status == BTN_DOWN)
{
if (timer > BTN_HOLD_MS) // Check if button has been pressed enough
{
if (status == RUNNING)
status = POWER_OFF;
else
{
status = RUNNING;
// setup of the device here if needed;
PORTB &= ~(1 << GATE); // ON
}
btn_status = BTN_IGNORE; // If status already changed don't swap it again
}
}
else
{
if (status) // Is status RUNNING?
{
/* main code here */
PORTB &= ~(1 << GATE); // ON
/* -------------- */
}
else
{
PORTB |= (1 << GATE); // OFF
power_off();
}
}
}
}
ISR(PCINT0_vect)
{
if (!((PINB >> BTN) & 0x01)) // Check if button is down
{
btn_status = BTN_DOWN;
timer_init();
timer = 0;
}
else
btn_status = BTN_UP;
}
ISR(TIM0_COMPA_vect)
{
timer++;
}
The code above is suppose to allow my power button to act as a soft latching switch. When the button is pressed it triggers an external inturrpt on pin 2, waking the chip from sleep and counting how long its been pressed. If it reaches the threshold it then drives pin 3 labeled “GATE” low, which in turn would allow the P-channel fet to switch and allow power to flow from the battery to the boost converter, thus powering the rest of the system. If the button is depressed again for a certain length of time, the gate pin is driven high, turning off the fet, and putting the ATtiny13A into sleep until pressed again. I found the code above online and was able to get it working with a ATtiny13A DIP package on a breadboard. I was using a different MOSFET than the one listed above but it appeared to function properly. I’m not sure if there is some blatantly obvious issue with my code above. I’m rather new to coding, especially when dealing with registers and chips in this way.
The issue I’m having is that when I connect a lipo to the board the ATtiny13a doesn’t turn on the MOSFET. If I short the drain pin of the MOSFET to the positive side of the battery pad it turns on the board and THEN the ATtiny13a controls it as expected. If I disconnect the battery and reconnect, the same issue arises…WHY? What is causing this issue???
Any help or guidance on this problem of mine would be greatly appreciated!