0
\$\begingroup\$

I stumble across an issue which I can't solve in multiple attempts. I'm trying to turn on and turn off an OLED SSD1306 display attached to the hardware I2C on Atmega328PB. The device has button on PD3 and P-channel MOSFET gate attached to PD6. The problem is, the output is initialized properly and the display is on, also it turns off properly, but cannot be turned on again. (PORTD &= ~(1 << PD6)) doesn't change the state of the output. That is confirmed and with voltmeter. As soon as comment the display libraries and code, the output pin works fine and I can flip the state. I test that with multiple different libraries in Arduino and also with C OLED libraries with avr-gcc code. Can't find anything in those libraries to interfere with the port manipulation and I'm looking for help.

#include <avr/io.h>
#include <util/delay.h>

#include "main.h"
#include "i2c.h"
#include "SSD1306.h"

uint8_t powerOn = 1;

int main(void) {
  initIOs();
  OLED_Init();  // Initialize the OLED
  OLED_Clear(); // Clear the display

  while (1) {
    OLED_SetCursor(0, 0);        // Set the cursor position to (0,0)
    OLED_Printf("Hello World!"); // Print out some text

    if (!(PIND & (1 << PD3)) && !(powerOn)) {
      PORTD &= ~(1 << PD6);
      _delay_ms(500);
      OLED_Clear(); // Clear the display (for good measure)
      OLED_SetCursor(0, 0);        // Set the cursor position to (0,0)
      OLED_Printf("Hello World!"); // Print out some text
      powerOn = 1;
    }
    if (!(PIND & (1 << PD3)) && (powerOn)) {
      OLED_Clear(); // Clear the display when turning off
      _delay_ms(500);
      PORTD |= (1 << PD6);
      powerOn = 0;
    }

    _delay_ms(50); // Add a small delay for switch debouncing
  }
  return 0; // Never reached
}

void initIOs(void) {
  DDRD |= (1 << PD6); // Set power switch pin as output
  PORTD &= ~(1 << PD6);    // Set power switch pin low

  DDRD &= ~(1 << PD3);  // Set power button pin as input
  PORTD |= (1 << PD3); // Set power button pin pull-up resistor

  _delay_ms(100); // Delay for stabilization
}
```
\$\endgroup\$
4
  • \$\begingroup\$ What is the part number of the P channel mosfet? What is the voltage level at its source and at what voltage are you driving the Atmega328PB ? \$\endgroup\$
    – 6v6gt
    Commented Apr 18 at 20:41
  • \$\begingroup\$ The mosfet is IRLML6402. The operational voltage for MCU and the display is 4.3V and that is and the mosfet source voltage. There is 100 Ohm resistor between MCU output to gate, and 100 KOhm resistor between gate to source. \$\endgroup\$
    – lz_linux
    Commented Apr 19 at 2:50
  • \$\begingroup\$ Welcome to SE/EE! Please take the tour to learn how this site works, and read "How to Ask". Then come back and edit your question to add the schematic of your circuit. Please use the site's provided schematic editor. Add new information to your question, comment are not for this. \$\endgroup\$ Commented Apr 19 at 5:37
  • \$\begingroup\$ @lz_linux. The mosfet is good for the voltages you mentioned. You could try re-initialising the oled display in the code after re-applying power to it. \$\endgroup\$
    – 6v6gt
    Commented Apr 19 at 5:52

1 Answer 1

0
\$\begingroup\$

I have no clue how the Arduino libraries work and what does your schematics look like, but I think the libraries are not really causing the problem, they just can't handle the way you are using them, and the program execution gets stuck because it can't do what you want in an impossible scenario.

It seems that you turn off power to the display and then send it a command to clear display. That can't work. It has no power any more when you send the command, or at least it is fading away already, so the clear command might be sent OK, but don't count on it.

Even if it did work, after the power has faded away and is off, you are constantly trying to set the cursor and print Hello, regardless of power being on or off. That definitely can't work without power.

Those are already two places where the code can hang into a loop waiting for commands to display be complete and they never do.

The next problem might happen when turning the display on again.

Also you initialize the GPIOs into state it gives power to display. Therefore the init and clear functions are done only once after AVR starts running. But if you then manage to turn LCD on, you are immediately sending commands to it, without initializing it again. It might need the init function or not. Again, you need to read the library manual how to use it, or in most cases, just read the source code to understand what it really does if the manual does not tell you.

Likely turning off the display power hangs the I2C bus - if you are using I2C bus. Your display might try to suck power from I2C bus pins as the resistors try to pull the bus up. Unless you have the pull-ups on the unpowered LCD side. Or the LCD does not clamp the bus voltages. But display won't respond even if the bus is OK.

Dynamically turning devices off on buses need careful planning for the hardware and software.

And Arduino libraries are very simple and rarely have any fail-safe mechanisms implemented. For example the I2C libraries may assume every transfer on I2C bus can always be done succesfully and there never will be any problems so it not need to handle the problems if something fails.

\$\endgroup\$
2
  • \$\begingroup\$ If the display draw power from SDA or SCL it will stay on, or at least it will try to stay on. Instead it shut down reliably. A don't see reason the MCU output, not to go low when commanded it is isolated thru 100 Ohm resistor from the gate of the mosfet. In the same time during IO pin initialization function it goes low just fine. Also if I just comment the code for the display it switch between high and low without and issue. \$\endgroup\$
    – lz_linux
    Commented Apr 19 at 4:02
  • \$\begingroup\$ @lz_linux You changed the code and solved only 1 part of the problem. Your code still wants to write to display every 50ms without considering if display power is turned on or off. And the third problem not initializing the display after power-up. \$\endgroup\$
    – Justme
    Commented Apr 19 at 8:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.