ATtiny13A power button hardware/coding issue

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!

Sorry to say this but that narrative is pretty incomprehensible, it becomes TL;DR. Mentioning an atMega328 multiple times and then not showing it on a schematic isn’t helpful. It sounds like the boost converter is and the ‘328 is just noise in the actual conversation you need to have.

Based on what I can see… have you verified the BTN pin goes from high to low when pressing the button?

And have you verified that the Gate pin goes low after the button is held down? And that the mosfet drain goes high when the gate goes low? And so forth until you find a voltage that isn't what you expect it to be.

WattsThat: Sorry to say this but that narrative is pretty incomprehensible, it becomes TL;DR. Mentioning an atMega328 multiple times and then not showing it on a schematic isn’t helpful. It sounds like the boost converter is and the ‘328 is just noise in the actual conversation you need to have.

Based on what I can see... have you verified the BTN pin goes from high to low when pressing the button?

Sorry about that, I was just trying to be detailed. The board that is working has the BTN pin going from high to low when pressed yes. I'm attaching the negative probe of my multimeter to the main ground on the back of the board when making the measurement. My second board doesn't show any voltage when doing the same at the pin, despite the ATtiny showing 3.7V at the power pin. If I attached my ground probe to the ground terminal of the battery pad it reads 2.4v when not being pressed, and goes to 2.75V when pressed :confused:

The other strange thing is that if I change the above code from

int main()
{
    setup();
    Device_Status status = POWER_OFF; // Set start ON or OFF when power is connected

to

int main()
{
    setup();
    Device_Status status = RUNNING; // Set start ON or OFF when power is connected

using the ICSP then after the code is loaded the board powers up as it should and I'm able to turn the device on and off. However the reverse isn't true.

Ok so quick update, for whatever reason it appears that my bench power supply was causing some problems. So the crux of the problem is this

When I have a new board and have programmed attiny. When I hook up a lipo to the battery terminals it doesn't turn on the board. If I short Pin 3 of the MOSFET to the postive battery terminal it turns on the board and THEN the ATtiny controls the MOSFET as expected, turning it on and off. If I disconnect the battery and reconnect, the same issue arises, I can only get the chip to work properly once I've shorted that pin...WHY?

When I disconnect and reconnect the lipo the BTN pin is reading about 2.85V and when I press the power button it's going low as expected. However the GATE pin is reading the same voltage as the lipo but when I press the power button it's not going low to turn on the MOSFET. Why would shorting the drain pin of the MOSFET to the positive battery terminal change this?

Update 2: I did more testing, disconnecting the battery again and reconnecting. Now the BTN pin is going from 2.8V to 3.14V when pressed....I have no idea why it was acting as expected before and now its not.

Problem solved. It was the battery protection IC. From page 8 of the datasheet.

"When a battery is connected to FS312F-G for the first time, it may not enter the normal condition (dischargeable my not be enabled). In this case, short the CS and VSS pins or connect to a charger to restore to the normal condition."