text:
Arduino ESP32F-TFT-1.44 Driver
Datasheet https://github.com/espressif/esp-hosted/files/5190376/ESP-32F.pdf
The below code is not working.
I can see only White screen

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>

#define TFT_CS        26 // Hallowing display control pins: chip select
#define TFT_RST       16 // Display reset
#define TFT_DC        17 // Display data/command select
#define TFT_BACKLIGHT  13 // Display backlight pin

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 (including HalloWing) use:
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// For 1.54" TFT with ST7789:
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// OPTION 2 lets you interface the display using ANY TWO or THREE PINS,
// tradeoff being that performance is not as fast as hardware SPI above.
#define TFT_MOSI 19  // Data out
#define TFT_SCLK 18  // Clock out
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

float p = 3.1415926;

void setup(void) {
  Serial.begin(115200);
  Serial.print(F("Hello! ST77xx TFT Test"));

  //#ifdef ADAFRUIT_HALLOWING
  // HalloWing is a special case. It uses a ST7735R display just like the
  // breakout board, but the orientation and backlight control are different.
  tft.initR(INITR_HALLOWING);        // Initialize HalloWing-oriented screen
  pinMode(TFT_BACKLIGHT, OUTPUT);
  digitalWrite(TFT_BACKLIGHT, HIGH); // Backlight on
  //#else
  // Use this initializer if using a 1.8" TFT screen:
  //  tft.initR(INITR_BLACKTAB);      // Init ST7735S chip, black tab

  // OR use this initializer (uncomment) if using a 1.44" TFT:
  //  tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  // OR use this initializer (uncomment) if using a 0.96" 180x60 TFT:
  //  tft.initR(INITR_MINI160x80);  // Init ST7735S mini display

  // OR use this initializer (uncomment) if using a 1.54" 240x240 TFT:
  //tft.init(240, 240);           // Init ST7789 240x240
  //#endif

  Serial.println(F("Initialized"));

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);
  delay(500);

  // large block of text
  tft.fillScreen(ST77XX_BLACK);
  testdrawtext("Hello World asdf sdf adfsdf sdf sdf sdf sdf sdf ", ST77XX_BLACK);
  delay(1000);

  Serial.println("done");
  delay(1000);
}

void loop() {
  tft.invertDisplay(true);
  delay(500);
  tft.invertDisplay(false);
  delay(500);
}

void testdrawtext(char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

are we supposed to guess what you expect the code to do, and what happens when you run the code, and what question you want to ask?

I can see only black screen.

then, what is the point of the lengthy program? ... reduce the code to minimum required to display a simple text message, such as "test" ... there should be an example sketch included with the library, try that first

from experience, I had the same problem with various displays with the example code above. using software SPI solved the problem many times. try it out. it's applicable in the code above with just some commenting.

What actual display do you have? Is it a ST7735 based one?

I checked my datasheet, but, there is no information, only TFT-1.44

According to the circuit diagram you provided, the TFT_MOSI is connected to pin 23, not pin 19. Pin 19 is for MISO, not MOSI.

@hcheung : thanks, that will be answer

#include <WiFi.h>

#include <time.h>
#include "AudioFileSourcePROGMEM.h"
#include "AudioGeneratorTalkie.h"
#include "AudioOutputI2S.h"

#ifndef STASSID
#define STASSID "WIFI_SSID"
#define STAPSK  "WIFI_PASSWORD"
#endif

const char *ssid = STASSID;
const char *pass = STAPSK;

long timezone = 7;
byte daysavetime = 1;

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <Adafruit_ST7789.h> // Hardware-specific library for ST7789
#include <SPI.h>

#define TFT_CS        26 // Hallowing display control pins: chip select
#define TFT_RST       16 // Display reset
#define TFT_DC        17 // Display data/command select
#define TFT_BACKLIGHT  13 // Display backlight pin

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

// For 1.44" and 1.8" TFT with ST7735 (including HalloWing) use:
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// For 1.54" TFT with ST7789:
//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// OPTION 2 lets you interface the display using ANY TWO or THREE PINS,
// tradeoff being that performance is not as fast as hardware SPI above.
#define TFT_MOSI 23  // Data out
#define TFT_SCLK 18  // Clock out
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

float p = 3.1415926;

AudioGeneratorTalkie *talkie;
AudioOutputI2S *out;

bool GetLocalTime(struct tm * info, uint32_t ms) {
  uint32_t count = ms / 10;
  time_t now;

  time(&now);
  localtime_r(&now, info);

  if (info->tm_year > (2016 - 1900)) {
    return true;
  }

  while (count--) {
    delay(10);
    time(&now);
    localtime_r(&now, info);
    if (info->tm_year > (2016 - 1900)) {
      return true;
    }
  }
  return false;
}

int threshold = 40;
bool touch1detected = false;
bool touch2detected = false;

void gotTouch1() {
  touch1detected = true;
}

void gotTouch2() {
  touch2detected = true;
}
void initLCD() {
  tft.initR(INITR_HALLOWING);        // Initialize HalloWing-oriented screen
  pinMode(TFT_BACKLIGHT, OUTPUT);
  digitalWrite(TFT_BACKLIGHT, HIGH); // Backlight on

  Serial.println(F("Initialized"));

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);
  delay(500);

  // large block of text
  tft.fillScreen(ST77XX_BLACK);

}
void setup(void) {

  touchAttachInterrupt(T2, gotTouch1, threshold);
  touchAttachInterrupt(T0, gotTouch2, threshold);

  Serial.begin(115200);
  Serial.print(F("Hello! ST77xx TFT Test"));

  initLCD();

  /*
    delay(1000);

    // tft print function!
    tftPrintTest();
    delay(4000);

    // a single pixel
    tft.drawPixel(tft.width() / 2, tft.height() / 2, ST77XX_GREEN);
    delay(500);

    // line draw test
    testlines(ST77XX_YELLOW);
    delay(500);

    // optimized lines
    testfastlines(ST77XX_RED, ST77XX_BLUE);
    delay(500);

    testdrawrects(ST77XX_GREEN);
    delay(500);

    testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA);
    delay(500);

    tft.fillScreen(ST77XX_BLACK);
    testfillcircles(10, ST77XX_BLUE);
    testdrawcircles(10, ST77XX_WHITE);
    delay(500);

    testroundrects();
    delay(500);

    testtriangles();
    delay(500);

    mediabuttons();
    delay(500);

    Serial.println("done");
    delay(1000);

    //*/

  Serial.print("Connecting to ");
  Serial.println(ssid);
  testdrawtext("Connecting to ", ST77XX_WHITE);

  WiFi.begin(ssid, pass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("WiFi connected");

  tft.fillScreen(ST77XX_BLACK);
  testdrawtext(strcat("WiFi connected ", ""), ST77XX_WHITE);
  clearText();
  delay(1000);

  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.println("Contacting Time Server");

  configTime(3600 * timezone, daysavetime * 3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
  struct tm tmstruct ;
  do {
    tmstruct.tm_year = 0;
    Serial.printf(".");
    GetLocalTime(&tmstruct, 5000);
    delay(100);
  } while (tmstruct.tm_year < 100);

  audioLogger = &Serial;
  out = new AudioOutputI2S(0, 1);
  talkie = new AudioGeneratorTalkie();
  talkie->begin(nullptr, out);
}

char temp[300];

int alarmHours = 5;
int alarmMinutes = 44;

void loop() {
  //  tft.invertDisplay(true);
  //  delay(500);
  //  tft.invertDisplay(false);
  //  delay(500);

  struct tm tmstruct ;
  tmstruct.tm_year = 0;
  GetLocalTime(&tmstruct, 5000);
//  Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d Alarm %2d : %2d\n",
//                tmstruct.tm_year + 1900, tmstruct.tm_mon + 1,
//                tmstruct.tm_mday, tmstruct.tm_hour,
//                tmstruct.tm_min, tmstruct.tm_sec,
//                alarmHours, alarmMinutes);
  Serial.printf("\nNow is : %02d:%02d:%02d\n",
                tmstruct.tm_hour,
                tmstruct.tm_min, tmstruct.tm_sec);

  //  sprintf(temp, "%d-%02d-%02d% 02d:%02d:%02d Alarm %2d : %2d\n", tmstruct.tm_year + 1900, tmstruct.tm_mon + 1, tmstruct.tm_mday, tmstruct.tm_hour, tmstruct.tm_min, tmstruct.tm_sec, alarmHours, alarmMinutes);
  sprintf(temp, "%02d:%02d:%02d", tmstruct.tm_hour, tmstruct.tm_min, tmstruct.tm_sec);

  if (60 * alarmHours + alarmMinutes <= 60 * tmstruct.tm_hour + tmstruct.tm_min) {
    Serial.printf("-Alarm-");
    Serial.printf("\n** Now is : %d-%02d-%02d %02d:%02d:%02d Alarm %2d : %2d\n",
                  tmstruct.tm_year + 1900, tmstruct.tm_mon + 1,
                  tmstruct.tm_mday, tmstruct.tm_hour,
                  tmstruct.tm_min, tmstruct.tm_sec,
                  alarmHours, alarmMinutes);
    //    sayTime(tmstruct.tm_hour, tmstruct.tm_min, talkie);
    //    initLCD();
  }

  //  clearText();

  tft.fillRect(40, 30, 50, 10, ST77XX_BLACK );
  //  testdrawtext(temp, ST77XX_WHITE);
  tft.setCursor(40, 30);
  tft.setTextColor(ST77XX_WHITE);
  //  tft.setTextWrap(true);
  tft.print(temp);

  delay(1000);

  if (touch1detected) {
    touch1detected = false;
    Serial.println("Touch 1 detected");
    alarmMinutes = alarmMinutes + 10;
  }
  if (touch2detected) {
    touch2detected = false;
    Serial.println("Touch 2 detected");
    alarmMinutes = alarmMinutes + 10;
  }
}

void testlines(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x = 0; x < tft.width(); x += 6) {
    tft.drawLine(0, 0, x, tft.height() - 1, color);
    delay(0);
  }
  for (int16_t y = 0; y < tft.height(); y += 6) {
    tft.drawLine(0, 0, tft.width() - 1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x = 0; x < tft.width(); x += 6) {
    tft.drawLine(tft.width() - 1, 0, x, tft.height() - 1, color);
    delay(0);
  }
  for (int16_t y = 0; y < tft.height(); y += 6) {
    tft.drawLine(tft.width() - 1, 0, 0, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x = 0; x < tft.width(); x += 6) {
    tft.drawLine(0, tft.height() - 1, x, 0, color);
    delay(0);
  }
  for (int16_t y = 0; y < tft.height(); y += 6) {
    tft.drawLine(0, tft.height() - 1, tft.width() - 1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x = 0; x < tft.width(); x += 6) {
    tft.drawLine(tft.width() - 1, tft.height() - 1, x, 0, color);
    delay(0);
  }
  for (int16_t y = 0; y < tft.height(); y += 6) {
    tft.drawLine(tft.width() - 1, tft.height() - 1, 0, y, color);
    delay(0);
  }
}

char prevText[300];

void clearText() {
  testdrawtext(prevText, ST77XX_BLACK);
}

void testdrawtext(char *text, uint16_t color) {
  strcpy(prevText, text);
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t y = 0; y < tft.height(); y += 5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x = 0; x < tft.width(); x += 5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x = 0; x < tft.width(); x += 6) {
    tft.drawRect(tft.width() / 2 - x / 2, tft.height() / 2 - x / 2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x = tft.width() - 1; x > 6; x -= 6) {
    tft.fillRect(tft.width() / 2 - x / 2, tft.height() / 2 - x / 2 , x, x, color1);
    tft.drawRect(tft.width() / 2 - x / 2, tft.height() / 2 - x / 2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x = radius; x < tft.width(); x += radius * 2) {
    for (int16_t y = radius; y < tft.height(); y += radius * 2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x = 0; x < tft.width() + radius; x += radius * 2) {
    for (int16_t y = 0; y < tft.height() + radius; y += radius * 2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(ST77XX_BLACK);
  int color = 0xF800;
  int t;
  int w = tft.width() / 2;
  int x = tft.height() - 1;
  int y = 0;
  int z = tft.width();
  for (t = 0 ; t <= 15; t++) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x -= 4;
    y += 4;
    z -= 4;
    color += 100;
  }
}

void testroundrects() {
  tft.fillScreen(ST77XX_BLACK);
  int color = 100;
  int i;
  int t;
  for (t = 0 ; t <= 4; t += 1) {
    int x = 0;
    int y = 0;
    int w = tft.width() - 2;
    int h = tft.height() - 2;
    for (i = 0 ; i <= 16; i += 1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x += 2;
      y += 3;
      w -= 4;
      h -= 6;
      color += 1100;
    }
    color += 100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi ? ");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(ST77XX_WHITE);
  tft.println("Sketch has been");
  tft.println("running for : ");
  tft.setTextColor(ST77XX_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(ST77XX_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(ST77XX_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN);
}

Please add an explanation for why this is an answer to the question. What does this code do and how does it solve the problem? What's with the audio stuff?


text:
The PCM libary won't work on an Arduino Nano
I'm using the PCM(http://highlowtech.org/?p=1963) library on the Arduino nano, I'm plugging the speaker(https://www.amazon.com/gp/product/B07WZP4QFK/ref=ox_sc_act_title_3?smid=A2O4FZXIRZDLHA&psc=1) into pin 11 and ground, but the example file won't work.

They don't say much about their wiring on that site.  And you haven't shown your wiring.  It seems likely that the code is fine but what you have attached to pin 11 isn't.  Description, diagram, pictures etc would be helpful.

added a diagram

I have a sense of what the answer will be when someone posts it.  It probably won't be me, unless on one else does.  For their sake, show the actual speaker, and in particular, any writing on it.  It may be useful for them in writing a more complete answer of what you need to do.

Ok I'll get a picture of the actual speaker

By the way, you have said pin 11 but you have drawn a diagram showing a connection to D3.

oh thats my mistake I'll fix that when I upload the photos

what brought you to the conclusion that the PCM library does not work on the nano?

You can see my wiring and I used the example sketch provided in the library, but no sound will come out. I have also tried it on the uno and it works.

test the pin ... replace the speaker with an LED

it didn't work, does that mean the board is faulty?

Perhaps.  If you were testing it with the LED (and resistor) instead of speaker using the example sketch, you might as well go a step further and test that same pin by substituting its number into the blink sketch.  I have some reservations about how you're hooking a 4 ohm speaker directly to an Arduino pin.  It's possible that doing this killed the pin.  Normally, I'd say likely, but that you "tried it on the uno and it works" casts some doubt on that theory.  It seems like a bad idea in any case, and until you know differently I'd avoid hooking it directly to your pins.

I guess the Nano had a sketch which was setting pin 11 HIGH (using SPI?) as you turned it on with a 4 Ohm speaker attached without any other resistance. It created a short circuit and damaged the pin's circuit.
Using tone() or the PCM library with a speaker connected without additional resistor doesn't damage the pin immediately because it is then HIGH only for very short moments, but it stresses the pin circuit too.
The linked page recommends to use direct speaker connection because it is much louder then with a resistor in series, but this is a wrong advice. It should recommend an amplifier module for example with LM386 IC.
A piezo speaker has higher resistance so it can be connected directly to Arduino pin, but a piezo sounds loud only in high frequencies so with the PCM library the sound is like whispering.

so what can I do?

the thing you gain if you gain nothing, is experience

is there really nothing I can do here, because I have more nano boards

use a 100 Ohm resistor in series with the speaker to test the library, but the sound will be weak. for good results use an amplifier module. shops have small amplifier modules for Arduino

ok, thank you! If this project didn't work out, my dad might never buy me parts again so this really helps

just to confirm, the board I used to test the speaker is dead so I can't use it anymore

And do you know any good tutorials?

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Atmega328 and 4Digit 7 Segment ghost blinking!
I hooked up 4 7Seg leds (CC) with NPN transistors on the cathode of each digit. I am using 74HC595 shift register connected in the circuit in a pretty common fashion. The code I am running is the basic scanning code for the 7seg. The problem is that I see the scanned numbers on other LED digits too. Attached is the image. I call them "ghosts". The circuit I am using has an Atmega328 with an internal 8MHz Osc. The resistors on the segments are 220Ohm and 4 BC547's on the cathodes of the digits with 1kOhm resistors on their base.

below is the code:
void loop() {

      cathode_high(); // blank the screen

      break_number(number);

      display_number();
     delay(1);

}

void break_number(int num) { // seperate the input number into 4 single digits

  first_digit = num / 1000;
  digits[0] = first_digit;

  int first_left = num - (first_digit * 1000);
  second_digit = first_left / 100;
  digits[1] = second_digit;
  int second_left = first_left - (second_digit * 100);
  third_digit = second_left / 10;
  digits[2] = third_digit;
  fourth_digit = second_left - (third_digit * 10);
  digits[3] = fourth_digit;

}

void display_number() { //scanning

  cathode_high();
  digitalWrite(latch, LOW);
  shiftOut(data, clk, LSBFIRST, numbers[digits[count]]);
  digitalWrite(CAS[count], HIGH);
  digitalWrite(latch, HIGH);
  count++;
  if (count == 4) {
    count = 0;
  }
}

void cathode_high() { //turn off all 4 digit
  digitalWrite(CA_1, LOW);
  digitalWrite(CA_2, LOW);
  digitalWrite(CA_3, LOW);
  digitalWrite(CA_4, LOW);
}
Any help would be highly appreciated. Thanx in advance!

PNP on each cathode?! Surely you mean NPN...? You'd use PNP with a common anode, not a common cathode display.

Oh yes... I am sorry. 547 is an NPN.

If you only ever display one digit (never increment count) do you still see ghosting on that digit?

Could you measure the voltage on the Cathode pins when they're supposedly turned off? My guess is the BC547's do not completely turn off current through the display, or turn off very slowly, which explains the "ghost" when switching between digits. If you have an oscilloscope you could watch the voltage on the BC547's collector.

@Majenko Thanx for the effort. It is solved.

@StarCat It was a coding error. Its done now. Thanx anyway!!

@jsotola I have corrected it. Thanx

You change cathodes (digits) before latching in the new data. So for a spit second the data for the previous digits is shown on the current digit.
Swapping digitalWrite(CAS[count], HIGH); and digitalWrite(latch, HIGH); should fix that.

Bingo!! It worked. Thank You!

Glad it worked. digitalWrite is relatively slow. Thought I've had "ghosting" with direct port manipulation too.

Is there a way we can turn On/Off a full digit using the scanning method with 74hc595? As far as I understand, we cannot because the display_number() function is switching the digit pins already for scan.

I'd add one more element in the numbers array for the "no digit", with all segments off. To turn of a digit, you can then set the digit to the "number" 10.

Well, I understood the first part (adding a number to the array) and in my case the 7th element would render all digits blank, but unclear on the second part. And specially "number" 10

The numbers array is a lookup table for how to display a certain number (that is; which segments to turn on. Where index 0 gives you the segments that need to be on to show the character "0" on your 7-segment display. Index 1 for character "1" etc. I'd add an index 10 at the end for the empty character. The to set a digit to blank, use something like digits[1]=10;. Why did you numbers array only have 6 elements? I was expecting it to have 10 (indexes 0..9).

You could even add more indexes for the characters "AbCdEF-_" (which are about all the characters you can make on a 7-segment display).

Aahh I got you! Sorry I got confused in digit numbers. Earlier I had 4digits but now they are 6. So, had to add another element in the numbers array....great let me try it. I am making a reverse time counter for a machine. 6 digits mean, H M S . It is working good only I just wanted to blink the digit while setting the countdown time.

Ahh, now I get it. Note that you also have a decimal point. You could also use those to indicate a different mode (e.g. "time setting mode"). Just a thought.

Hey, Sorry I got stuck somewhere else. I have this on my mind too. Will try and get back. Thanx for all the support again.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Stepper motor slow when reading from MPU 6050 sensor
I'm trying to get an inverted pendulum project working (following the instructions here), and while my stepper motor moves the cart just fine when that's the only code in the Arduino sketch, as soon as I add the MPU 6050 sensor for detecting the angle of the pendulum, the cart moves much slower, far too slow to be useful for keeping the pendulum upright.
I imagine the timing of the motor commands is messed up by the sensor reads, but I'm not sure how to avoid the problem. Also, the author of the example posted essentially the same code as his working solution for proportional control, so there may be something else that I'm missing that messes my motor performance up.
Does anyone have any suggestions for how to get the stepper motor turning fast enough while also reading data from the MPU 6050?
My code is below. I'm using a Nema 17 stepper motor with an A4988 driver, a 12 V 10 A power supply, and this Aukru MPU-6050. To be sure that updates to the speed and Serial prints aren't the problem, I use an interval of 500 ms between updates/printing.
#include "I2Cdev.h"
#include <AccelStepper.h>
#include "MPU6050_6Axis_MotionApps20.h"

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

MPU6050 mpu;

#define INTERRUPT_PIN 2  // use pin 2 on Arduino Uno & most boards

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}

// Defines pins numbers
const int stepPin = 3;
const int dirPin = 4;
AccelStepper stepper(1,stepPin,dirPin);

int motorSpeed, currentPos;
unsigned long t_start, t_elapsed;
int interval = 500; // ms between printing speed

int speedMax = 4000;
float k_proportional = 4;

float angleCurrent, speedSet;

void setup() {
  // join I2C bus (I2Cdev library doesn't do this automatically)
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
      Wire.begin();
      Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif

  Serial.begin(115200);

  // initialize device
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  pinMode(INTERRUPT_PIN, INPUT);

  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

      // enable Arduino interrupt detection
      Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
      mpuIntStatus = mpu.getIntStatus();

      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      // ERROR!
      // 1 = initial memory load failed
      // 2 = DMP configuration updates failed
      // (if it's going to break, usually the code will be 1)
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
  }

  stepper.setMaxSpeed(speedMax);
  stepper.setAcceleration(10000);
  stepper.setSpeed(2000);
}

void loop() {
    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
        if (mpuInterrupt && fifoCount < packetSize) {
          // try to get out of the infinite loop
          fifoCount = mpu.getFIFOCount();
        }
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
      // wait for correct available data length, should be a VERY short wait
      while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

      // read a packet from FIFO
      mpu.getFIFOBytes(fifoBuffer, packetSize);

      // track FIFO count here in case there is > 1 packet available
      // (this lets us immediately read more without waiting for an interrupt)
      fifoCount -= packetSize;

      // display Euler angles in degrees
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    }

  t_elapsed = millis() - t_start;

  if (t_elapsed >= interval) {
    t_start += interval;
    motorSpeed=setMotorSpeed();
    stepper.setSpeed(motorSpeed);
    Serial.print("Roll ");
    Serial.print(ypr[2] * 180/M_PI);
    Serial.print("Motor speed: ");
    Serial.println(motorSpeed);
  }

  stepper.runSpeed();
}

int setMotorSpeed() {
  // Proportional control
  angleCurrent = ypr[2];
  speedSet = constrain(-angleCurrent*k_proportional*speedMax, -speedMax, speedMax);
  return speedSet;
}

Edit: Adding my code which limits the sensor logic to the same interval as the speed update, based on the answer by chrisl. The cart moves quite a bit faster, though still not fast enough to keep the pendulum upright.
#include "I2Cdev.h"
#include <AccelStepper.h>
#include "MPU6050_6Axis_MotionApps20.h"

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

MPU6050 mpu;

#define INTERRUPT_PIN 2  // use pin 2 on Arduino Uno & most boards

// MPU control/status vars
bool dmpReady = false;  // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector

// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool mpuInterrupt = false;     // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}

// Defines pins numbers
const int stepPin = 3;
const int dirPin = 4;
AccelStepper stepper(1,stepPin,dirPin);

int motorSpeed, currentPos;
unsigned long t_start, t_elapsed, t_mpu, t_start_mpu;
int interval = 50; // ms between printing speed
unsigned long count = 0;

int speedMax = 800;
float k_proportional = 3;

float angleCurrent, speedSet;

void setup() {
  // join I2C bus (I2Cdev library doesn't do this automatically)
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
      Wire.begin();
      Wire.setClock(400000); // 400kHz I2C clock. Comment this line if having compilation difficulties
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
      Fastwire::setup(400, true);
  #endif

  Serial.begin(115200);

  // initialize device
  Serial.println(F("Initializing I2C devices..."));
  mpu.initialize();
  pinMode(INTERRUPT_PIN, INPUT);

  // verify connection
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));

  // load and configure the DMP
  Serial.println(F("Initializing DMP..."));
  devStatus = mpu.dmpInitialize();

  // supply your own gyro offsets here, scaled for min sensitivity
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788); // 1688 factory default for my test chip

  // make sure it worked (returns 0 if so)
  if (devStatus == 0) {
      // turn on the DMP, now that it's ready
      Serial.println(F("Enabling DMP..."));
      mpu.setDMPEnabled(true);

      // enable Arduino interrupt detection
      Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
      attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);
      mpuIntStatus = mpu.getIntStatus();

      // set our DMP Ready flag so the main loop() function knows it's okay to use it
      Serial.println(F("DMP ready! Waiting for first interrupt..."));
      dmpReady = true;

      // get expected DMP packet size for later comparison
      packetSize = mpu.dmpGetFIFOPacketSize();
  } else {
      // ERROR!
      // 1 = initial memory load failed
      // 2 = DMP configuration updates failed
      // (if it's going to break, usually the code will be 1)
      Serial.print(F("DMP Initialization failed (code "));
      Serial.print(devStatus);
      Serial.println(F(")"));
  }

  stepper.setMaxSpeed(speedMax);
  stepper.setAcceleration(10000);
  stepper.setSpeed(100);
}

void loop() {

  t_elapsed = millis() - t_start;
  count += 1;

  if (t_elapsed >= interval) {
    t_start += interval;

    // wait for MPU interrupt or extra packet(s) available
    // Slows down cart tremendously, but code freezes without it
    while (!mpuInterrupt && fifoCount < packetSize) {
        if (mpuInterrupt && fifoCount < packetSize) {
          // try to get out of the infinite loop
          fifoCount = mpu.getFIFOCount();
        }
    }

    // reset interrupt flag and get INT_STATUS byte
    mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)

    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
      // wait for correct available data length, should be a VERY short wait
      while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

      // read a packet from FIFO
      mpu.getFIFOBytes(fifoBuffer, packetSize);

      // track FIFO count here in case there is > 1 packet available
      // (this lets us immediately read more without waiting for an interrupt)
      fifoCount -= packetSize;

      // display Euler angles in degrees
      mpu.dmpGetQuaternion(&q, fifoBuffer);
      mpu.dmpGetGravity(&gravity, &q);
      mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
    }

    motorSpeed=setMotorSpeed();
    // Use one potentiometer to turn system on or off (A0)
    int A0val = analogRead(A0);
    // Use another potentiometer to tune response time (or max speed)
    int A1val = analogRead(A1);
    //speedMax = 2*A1val;
    interval = A1val/2;
    Serial.print("Roll: ");
    Serial.print(ypr[2] * 180/M_PI);
    Serial.print(", motor speed: ");
    Serial.print(motorSpeed);
    Serial.print(", A0: ");
    Serial.print(A0val);
    Serial.print(", interval: ");
    Serial.print(interval);
    //Serial.print(", speedMax: ");
    //Serial.print(speedMax);
    Serial.print(", iterations: ");
    Serial.println(count);
    count=0;
    if (A0val > 512)
      stepper.setSpeed(motorSpeed);
    else
      stepper.setSpeed(0);
  }

  stepper.runSpeed();
}

int setMotorSpeed() {
  // Proportional control
  angleCurrent = ypr[2];
  speedSet = constrain(-angleCurrent*k_proportional*speedMax, -speedMax, speedMax);
  return speedSet;
}

how about, did you manage to finish the project?

I cannot say, why that principle works for the author of that tutorial. Though I can guess the reason, why your motors runs so slow.
The function, that actually drives the motor, is stepper.runSpeed(). You call it exactly once at the end of the loop() function. Though that function is designed to be called very often, as it only checks, if it is time to do a step, and then do so. It just an do max 1 step per execution. So you get 1 step per loop() iteration.
And at the start of the loop() you wait for the MPU data to be ready with this line:
while (!mpuInterrupt && fifoCount < packetSize)

So you do the steps at max with the same rate, that you read the MPU. That seems to be not enough for your setup.
You can try calling the runSpeed() function more often (and with that removing the limit on the steps). Either rewrite your code to only do the MPU communication, if the MPU data is ready, and proceed with the other code otherwise. Or you can insert the runSpeed() function into the while loops, that are waiting for the MPU data. The first option would be cleaner and would make the code easier to extent.

That makes sense, thanks. My solution was to put all the MPU reading code inside the if (t_elapsed >= interval) block so that the sensor values are only read at set intervals and runSpeed() gets called every step. My cart speed is still slower than it is without the MPU (around 2/3 as fast), but it's much closer now. I'm still unsure how to get a smooth, fast speed -- I think my max right now is around 200 rpm, and setting the motor speed above around 1000 gives me trouble, but at least it's in the ballpark now.


text:
How do I connect an MPU6050 sensor to an Arduino MKR WIFI 1010?
I've been trying to connect an MPU6050 to my MKR WIFI 1010 following these general instructions and using the I2CDev library, but I keep running into problems.
For a while the Arduino just didn't show up as connected in the IDE when all the pins were connected, which I think I've gathered was due to a lack of pull-up resistors for the SCL/SDA pins. Adding 10 kOhm pull-up resistors helped a little (in making the Arduino visible) but it would hang when trying to upload the example sketch. 2.2 kOhm resistors seemed to do the trick, where now the example sketches (MPU6050_DMP6 or MPU6050_raw) can be uploaded. They still fail to read any actual values, however. The raw sketch gives 0 for everything, and the DMP6 sketch prints
Initializing I2C devices...
Testing device connections...
MPU6050 connection failed

Send any character to begin DMP programming and demo:
Initializing DMP...
DMP Initialization failed (code 1)

Does anyone know why the sensor still fails to give any measurements? I connect VCC and GND from the sensor to VCC (3.3V) and GND from my Arduino. SCL and SDA from the sensor are connected to VCC via 2.2 kOhm resistors and to the SCL and SDA pins of the Arduino (12 and 11). And INT from the sensor is connected to digital pin 2. (I tried this on a couple other pins like 0 and 1 since it seems from the tech specs that 2 is not an External Interrupt pin, but that didn't change anything.)
The sensor and examples worked without any extra effort on my Arduino Uno, but unfortunately I fried that with a 12V power supply by accident. I'll probably just get another Uno, but I'm curious why this didn't work, if I'm missing something about I2C or the MKR WIFI.
I'll also note that I had to add
define #BUFFER_LENGTH 64

to wire.h in order to get sketches including I2Cdev to compile (following these instructions).

Yes, it was defined as 64, good catch. (Edited now.) I did not run any I2C scanner sketch, but I can try that. The wiring for SDA/SCL used a breadboard with both pins from the sensor connected to their own rows, a 2.2 kOhm resistor from each row to the +3.3V column (which itself connects to VCC on both the Arduino and sensor), and jumper cables from those rows to pins 11 and 12 on the Arduino for SDA/SCL respectively. The other wiring is GND (sensor) to negative column on breadboard to GND (Arduino) and INT (sensor) to digital pin 2 (which I wasn't sure about, so I also tried 0 and 1).

try the I2CScanner sketch without the pullups too

I'm seeing "I2C device found at address 0x60" and "I2C device found at address 0x6B", regardless of whether anything is plugged into my Arduino. When I tried to connect the sensor without the pull-up resistors, I got the error message "java.io.IOException: jssc.SerialPortException: Port name - COM3; Method name - setEventsMask(); Exception type - Can't set mask" and the orange CHRG light came on (with quick pulsing)

the MKR1010 has I2C devices on board

So it never detected the sensor then. Could different pull up resistors help? 4.7 kOhm seems to be a typical value used

what module with MPU6050 do you have?

This one from Aukru: https://www.amazon.com/Aukru-Arduino-Accelerometer-6050-Gyroscope/dp/B019SX74TE/

My hunch is the MPU 6050 is broken. I got a new Arduino Uno and the I2C scanner hangs when the MPU is connected, regardless of whether I have pull-up resistors. (And it worked perfectly fine with no extra pull-up resistors with my previous Arduino Uno before I fried it.) I'll order a new MPU-6050.

The sensor was indeed broken, and I had no problems after ordering a new one.


text:
Artefacts on display when adding seemingly unrelated code
I have this simple program, where I am implementing a menu structure on an OLED display and a rotary encoder.
The code works functionally as intended, however when I add more menu items, then I get some artefacts on the display, in the lower right corner (see screenshots).
The code that I am referring to is inside the block comment in initMenu().
When I uncomment that block, the artefacts start appearing, every other time I turn the knob on the encoder. Sometimes it temporarily disappears, or slightly changes its shape.

As I said, other than that, the code behaves as expected.
Could anyone maybe shed some light on why this happens?
#define DEBUG 1

// Display
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display;

// Rotary encoder
#include "RotaryEncoder.h"
#include "YetAnotherPcInt.h"
#define RTRY_ENC_SW A1
#define RTRY_ENC_CLK A2
#define RTRY_ENC_DT A3
RotaryEncoder encoder(RTRY_ENC_CLK, RTRY_ENC_DT);
void onSwitch();
void onRotate();

typedef struct MenuItem {
  String name;
  byte id = 0;
  boolean active = false;
  MenuItem* prevSibling;
  MenuItem* nextSibling;
  MenuItem* currentChild;
};

MenuItem autoModes;
MenuItem manualModes;
MenuItem settings;
MenuItem peakAverage;
MenuItem peakToPeak;
MenuItem rms;

MenuItem* currentItem;
MenuItem* activeMode;

void setup() {
#ifdef DEBUG
  Serial.begin(115200);
#endif
  initEncoder();
  initMenu();
  initDisplay();
}

boolean hasInputs = false;
boolean switchPressed = false;

void loop() {
  if (hasInputs == true) {
    hasInputs = false;
    handleButtonInputs();
  }
}

void initEncoder() {
  pinMode(RTRY_ENC_SW, INPUT_PULLUP);
  PcInt::attachInterrupt(RTRY_ENC_SW, onSwitch, FALLING);
  PcInt::attachInterrupt(RTRY_ENC_CLK, onRotate, CHANGE);
  PcInt::attachInterrupt(RTRY_ENC_DT, onRotate, CHANGE);
}

void initMenu() {
  autoModes.name = "Auto";
  autoModes.id = 1;
  autoModes.active = true;
  autoModes.prevSibling = &settings;
  autoModes.nextSibling = &manualModes;
  autoModes.currentChild = &peakAverage;

  manualModes.name = "Manual";
  manualModes.id = 2;
  manualModes.prevSibling = &autoModes;
  manualModes.nextSibling = &settings;

  settings.name = "Config";
  settings.id = 3;
  settings.prevSibling = &manualModes;
  settings.nextSibling = &autoModes;
/*
  peakAverage.name = "PAvg";
  peakAverage.id = 4;
  peakAverage.active = true;
  peakAverage.prevSibling = &rms;
  peakAverage.nextSibling = &peakToPeak;

  peakToPeak.name = "P2P";
  peakToPeak.id = 5;
  peakToPeak.prevSibling = &peakAverage;
  peakToPeak.nextSibling = &rms;

  rms.name = "RMS";
  rms.id = 6;
  rms.prevSibling = &peakToPeak;
  rms.nextSibling = &peakAverage;

  activeMode = &peakAverage;
*/
  currentItem = &autoModes;
}

void initDisplay() {
  display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setCursor(36, 24);
  display.setTextSize(2);
  display.setTextColor(1);
  display.print("Hello");
  display.display();
}

void handleButtonInputs() {
  if (switchPressed) {
    switchPressed = false;
    if (currentItem->id <= 3) {
      currentItem = currentItem->currentChild;
      printMenu();
    } else if (4 <= currentItem->id && currentItem->id <= 6) {
      if (activeMode->id != currentItem->id) {
        activeMode->active = false;
        currentItem->active = true;
        activeMode = currentItem;
      }
      currentItem = &autoModes;
      printMenu();
    }
  }

  RotaryEncoder::Direction direction = encoder.getDirection();
  if (direction == RotaryEncoder::Direction::CLOCKWISE) {
#ifdef DEBUG
    Serial.println("clockwise");
#endif
    currentItem = currentItem->nextSibling;
    printMenu();
  } else if (direction == RotaryEncoder::Direction::COUNTERCLOCKWISE) {
#ifdef DEBUG
    Serial.println("counterclockwise");
#endif
    currentItem = currentItem->prevSibling;
    printMenu();
  } else if (direction == RotaryEncoder::Direction::NOROTATION ) {
#ifdef DEBUG
    Serial.println("no rotation");
#endif
    // ?
  }
}

void printMenu() {
#ifdef DEBUG
  Serial.println(currentItem->prevSibling->name);
#endif
  display.clearDisplay();
  display.setTextSize(2);
  Serial.println(currentItem->prevSibling->name);
  int x1 = 64 - currentItem->prevSibling->name.length() * 6;
  if (currentItem->prevSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x1 - 2, 0, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x1, 0);
  display.print(currentItem->prevSibling->name);
#ifdef DEBUG
  Serial.println(currentItem->name);
#endif
  int x2 = 64 - currentItem->name.length() * 6;
  int width = currentItem->name.length() * 12 + 10;
  if (currentItem->active) {
    display.setTextColor(0, 1);
    display.fillRect(x2 - 6, 19, width, 24, 1);
  } else {
    display.setTextColor(1, 0);
    display.drawRect(x2 - 6, 19, width, 24, 1);
  }
  display.setCursor(x2, 23);
  display.print(currentItem->name);
#ifdef DEBUG
  Serial.println(currentItem->nextSibling->name);
#endif
  int x3 = 64 - currentItem->nextSibling->name.length() * 6;
  if (currentItem->nextSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x3 - 2, 47, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x3, 47);
  display.print(currentItem->nextSibling->name);
  display.display();
}

void onSwitch() {
  hasInputs = true;
  switchPressed = true;
}

void onRotate() {
  hasInputs = true;
  encoder.tick();
}

This is the output of the compilation process regarding program size:
Sketch uses 18198 bytes (59%) of program storage space. Maximum is 30720 bytes.
Global variables use 827 bytes (40%) of dynamic memory, leaving 1221 bytes for local variables. Maximum is 2048 bytes.

(4 <= currentItem->id <= 6) is parsed as ((4 <= currentItem->id) <= 6) which is always true since comparisons evaluate to 0 or 1. You need to split it up ((4 <= currentItem->id) && (currentItem->id <= 6)).

How much free RAM do you have?

Looks like your stack is ramming into your heap.

@EdgarBonet I updated my question regarding size. Would it help to split printMenu into smaller chunks? Put all constant Strings to PROGMEM?

Thanks for the comments about memory usage, I was able to solve this specific problem.
I have updated my program, and optimized it by splitting up the menu rendering, using smaller variable sizes where possible, and putting all Strings to PROGMEM using the F() macro.
I also had a look at this page https://learn.adafruit.com/memories-of-an-arduino/measuring-free-memory and copied freeMemory() from there:
#define DEBUG 1
#define DEBUG_MEMORY 1

// Display
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#define OLED_RESET -1
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display;

// Rotary encoder
#include "RotaryEncoder.h"
#include "YetAnotherPcInt.h"
#define RTRY_ENC_SW A1
#define RTRY_ENC_CLK A2
#define RTRY_ENC_DT A3
RotaryEncoder encoder(RTRY_ENC_CLK, RTRY_ENC_DT);
void onSwitch();
void onRotate();

typedef struct MenuItem {
  String name;
  byte id = 0;
  boolean active = false;
  MenuItem* prevSibling;
  MenuItem* nextSibling;
  MenuItem* currentChild;
};

MenuItem autoModes;
MenuItem manualModes;
MenuItem settings;
MenuItem peakAverage;
MenuItem peakToPeak;
MenuItem rms;

MenuItem* currentItem;
MenuItem* activeMode;

#ifdef DEBUG_MEMORY
#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__

int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}
#endif

void setup() {
#ifdef DEBUG
  Serial.begin(115200);
#endif
  initEncoder();
  initMenu();
  initDisplay();
}

boolean hasInputs = false;
boolean switchPressed = false;

void loop() {
  if (hasInputs == true) {
    hasInputs = false;
    handleButtonInputs();
  }
}

void initEncoder() {
  pinMode(RTRY_ENC_SW, INPUT_PULLUP);
  PcInt::attachInterrupt(RTRY_ENC_SW, onSwitch, FALLING);
  PcInt::attachInterrupt(RTRY_ENC_CLK, onRotate, CHANGE);
  PcInt::attachInterrupt(RTRY_ENC_DT, onRotate, CHANGE);
}

void initMenu() {
  autoModes.name = F("Auto");
  autoModes.id = 1;
  autoModes.active = true;
  autoModes.prevSibling = &settings;
  autoModes.nextSibling = &manualModes;
  autoModes.currentChild = &peakAverage;

  manualModes.name = F("Manual");
  manualModes.id = 2;
  manualModes.prevSibling = &autoModes;
  manualModes.nextSibling = &settings;

  settings.name = F("Config");
  settings.id = 3;
  settings.prevSibling = &manualModes;
  settings.nextSibling = &autoModes;

  peakAverage.name = F("PAvg");
  peakAverage.id = 4;
  peakAverage.active = true;
  peakAverage.prevSibling = &rms;
  peakAverage.nextSibling = &peakToPeak;

  peakToPeak.name = F("P2P");
  peakToPeak.id = 5;
  peakToPeak.prevSibling = &peakAverage;
  peakToPeak.nextSibling = &rms;

  rms.name = F("RMS");
  rms.id = 6;
  rms.prevSibling = &peakToPeak;
  rms.nextSibling = &peakAverage;

  activeMode = &peakAverage;
  currentItem = &autoModes;
}

void initDisplay() {
  display = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setCursor(36, 24);
  display.setTextSize(2);
  display.setTextColor(1);
  display.print(F("Hello"));
  display.display();
}

void handleButtonInputs() {
  if (switchPressed) {
    switchPressed = false;
    if (currentItem->id <= 3) {
      currentItem = currentItem->currentChild;
      renderMenu();
    } else if (4 <= currentItem->id && currentItem->id <= 6) {
      if (activeMode->id != currentItem->id) {
        activeMode->active = false;
        currentItem->active = true;
        activeMode = currentItem;
      }
      currentItem = &autoModes;
      renderMenu();
      #ifdef DEBUG_MEMORY
        Serial.println(freeMemory());
      #endif
    }
  }

  RotaryEncoder::Direction direction = encoder.getDirection();
  if (direction == RotaryEncoder::Direction::CLOCKWISE) {
#ifdef DEBUG
    Serial.println(F("cw"));
#endif
    currentItem = currentItem->nextSibling;
    renderMenu();
  } else if (direction == RotaryEncoder::Direction::COUNTERCLOCKWISE) {
#ifdef DEBUG
    Serial.println(F("ccw"));
#endif
    currentItem = currentItem->prevSibling;
    renderMenu();
  } else if (direction == RotaryEncoder::Direction::NOROTATION ) {
#ifdef DEBUG
    Serial.println(F("nr"));
#endif
    // ?
  }
}

void renderMenu() {
  display.clearDisplay();
  printPrevSibling();
  printCurrentItem();
  printNextSibling();
#ifdef DEBUG_MEMORY
  Serial.println(freeMemory());
#endif
  display.display();
}

void printPrevSibling() {
#ifdef DEBUG
  Serial.println(currentItem->prevSibling->name);
#endif
  display.setTextSize(2);
  Serial.println(currentItem->prevSibling->name);
  byte x1 = 64 - currentItem->prevSibling->name.length() * 6;
  if (currentItem->prevSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x1 - 2, 0, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x1, 0);
  display.print(currentItem->prevSibling->name);
}

void printCurrentItem() {
#ifdef DEBUG
  Serial.println(currentItem->name);
#endif
  byte x2 = 64 - currentItem->name.length() * 6;
  byte width = currentItem->name.length() * 12 + 10;
  if (currentItem->active) {
    display.setTextColor(0, 1);
    display.fillRect(x2 - 6, 19, width, 24, 1);
  } else {
    display.setTextColor(1, 0);
    display.drawRect(x2 - 6, 19, width, 24, 1);
  }
  display.setCursor(x2, 23);
  display.print(currentItem->name);
}

void printNextSibling() {
#ifdef DEBUG
  Serial.println(currentItem->nextSibling->name);
#endif
  byte x3 = 64 - currentItem->nextSibling->name.length() * 6;
  if (currentItem->nextSibling->active) {
    display.setTextColor(0, 1);
    display.fillRect(x3 - 2, 47, 2, 16, 1);
  } else {
    display.setTextColor(1, 0);
  }
  display.setCursor(x3, 47);
  display.print(currentItem->nextSibling->name);
}

void onSwitch() {
  hasInputs = true;
  switchPressed = true;
}

void onRotate() {
  hasInputs = true;
  encoder.tick();
}

Now the size is like this:
Sketch uses 18588 bytes (60%) of program storage space. Maximum is 30720 bytes.
Global variables use 761 bytes (37%) of dynamic memory, leaving 1287 bytes for local variables. Maximum is 2048 bytes.

However the improvement is not that great, and I am still left wondering, when the next problem will arise. I am still thankful for further insights besides using a bigger controller, because I am not quite done yet on this one.
If anyone has more ways for me to improve this program without sacrificing performance, as I will be adding a radio, and a microphone, I will accept that as an answer over this one.

Does repeatedly printing the free memory show something suspicious? You have quite a bit of RAM left and you don't seem to have an recursive code, so I wonder where the memory would overflow. I also see no dynamic memory allocations.

@PMF: the Adafruit SSD1306 library mallocs 1k of RAM in this configuration for a screen buffer. Makes it very convenient but barely usable on a Uno. There are probably better libraries if all that is needed is printing some text.

@PMF Yes, as @Mat pointed out, instantiating the display object eats a lot of RAM at once. I eventually resorted to using lower SCREEN_WIDTH and SCREEN_HEIGHT...


text:
AW9523B I2C on Arduino Nano
I'm testing the AW9523B IO expander with an Arduino Nano. I can't get the device to be recognized.
Using I2C scanner to find all attached I2C devices.
I've connected AW9523B to the correct pins to the SDA/SCL pints of the Arduino, with 5K pullups. INTN is connected to GND.
An EEPROM is also connected on the bus. The EEPROM is recognized on the bus. I swapped the SDA/SCL pins just to make sure, and still AW9523B was not found on bus.
I've tried changing the AD0 and AD1 pins to no avail.
I have a 22uf capacitor on the VCC.
Changing the AD0 pin does change the default state of a connected LED, so I'm fairly confident the chip is not dead.
I've also tried the two example sketches from:

https://github.com/mrmx/AW9523B

Curious if anyone has gotten their AW9523B to work.

Updated Working Schematic

It sounds like you got to many resistors connected maybe where they should not. The chip works fine if installed properly. Post a schematic of how you have it wired, including links to the technical information on the parts you are using. I looked up the part and is is straightforward, Look at the data sheet, Typical Application 1: Drive 16 function LED, including 6 ports feasible for LED backlight your circuit should look like that. Examine that application.

Tried removing all the resistors other than the I2C pullups, no help. Updated with schematic.

How did they connect the LED on the data sheet?

The device can be either open-drain or push-pull, depending on configuration register, and/or the AD1 and AD0 settings. Either way, it shouldn't impact if the device is found on the I2S bus.

Connect RSTN to +5V with a 10K pullup resistor.

Thanks @Majenko I had not read the datasheet carefully enough! I saw it had a pull down resistor, figured that would be default non-reset state. Upon further reading, yes, low = reset. Why they put it in a default reset state is strange to me, but I'm not engineer.  None of the datasheet schematics have that pin pulled or set high...

Transcribing and adding to the answer from the comments.
The AW9523B has a reset (RSTN) pin 23 which is internally pulled low by a 100K ohm resistor (i.e., default = reset). @Majenko suggests attaching a pull-up 10K ohm resistor to +5V (i.e., not reset) to enable the chip.
The data sheet schematics and section describing the reset function (pg14) seem to anticipate the RSTN pin being connected to an MCU GPO pin used to dynamically control the reset function.


text:
CH340K - Unknown USB Device (Device Descriptor Request failed)
I have a Arduino Nano clone working fine with the CH340 drivers. It has a CH340C on it.
I made a custom PCB. CH340 chips are hard to come by these days, so I opted for the CH340K, From the datasheet, seems like it should work similar to the CH340C and CH340G that are quite common.
My PCB has a footprint for both the CH340K and CH340C/CH340G (Yes, I'm aware I'm missing the load capacitors for the CH340G). CH340C/N/K/E and CH340B have built-in clocks without external crystal oscillator. So no need for a crystal.
After soldering on the CH340K and USB port, I plugged the device in, and I'm getting an error in Windows 10 Device Manager:

Unknown USB Device (Device Descriptor Request failed)
Windows has stopped this device because it has reported problems.
(Code 43)
The USB set address request failed.

I've uninstalled and reinstalled the CH340 drivers several times. Tried to force the driver onto the device in device manager, and it didn't let me.
There's no short to ground or vcc.
Any help to get this recognized would be great! thanks!
CH340K Pinout

PCB

i think that i remember that the driver has inf and ini  files associated with it ... they are text files ... some editing may be required ... google CH340K inf

What is "the CH340 drivers"? When I google this, I get 967000 results.

Schematic? PCB design? Without those we can't help you

A failure to read the device descriptor generally means that there is a hardware fault. It's not getting as far as even knowing that there is a real USB device attached, let alone working out which driver might fit the bill. You either have a fault in your design, a fault in your PCB layout or a fault in your soldering.

Common problems include: * Accidentally swapping D+ and D-, * Shorting one of the data lines somewhere, * Incorrect crystal, * Incorrect crystal load capacitors, * Incorrect crystal layout (all three latter ones causing the wrong clock speed to be generated)

Thanks all. I added some details to the post. Finding issues with CH340 K is impossible with all the other pages about the more ubiquitous C and G cluttering up search results.

That all looks ok to me except one thing: you have no decoupling capacitor on the V3 pin. The datasheet stipulates this as needing 100nF on it.

Also, the DP trace is very close to the edge of your board. Have you confirmed continuity of that trace? You should leave at least 0.5mm gutter around the edge of your board to allow for tearing during routing or v-grooving.

If I remember correctly, the official Windows driver does not support the latest revisions of the CH340. Can you tell us the error code that is shown in the device manager?

I checked the board, the traces are fine. Just updated post with the Windows error specifics. Maybe I should contact the manufacturer and see if there's an updated driver? I'm not expecting much support from them as the cheap manufacturer they are.

Majenko, was the 100nf capacitor for the win! Thought I didn't need it since I wasn't going to be using the LDO output for anything else on the board. Want to make the official answer?

I’m experiencing the same issue, did you fixed it with the decoupling capacitor?
I tried to install it but no luck so far…

Needed a 100nf capacitor on the v3 pin, per Majenko's suggestion, and per datasheet.
I thought this was only needed if you were going to use the 3.3v output for other purposes. I was wrong!
Same requirement for the CH340C!

on you Pcb the Footprint is not correct!
UD+ is on GND, UD- is on UD+ and GND is on UD- . The CH340K has a differnt Footprint.

did you read the other answer by OP?

Pin 0 is the exposed pad.


text:
working with ultrasonic sensors
I have a little problem dealing with ultrasonic sensor
I want a simple thing , when the sensor read High pulse then after it low pulse , turns on the led
so I try to make it with a 5cm distance and a flag , but it's dose not work
help me please!
    #define echoPin 5
    #define trigPin 7
    int GREEN = 2;
    int YELLOW = 3;
    int RED = 4;
    int pos = 0;
    int flag = 0 ;
    long duration;
    int distance;
    void setup() {

  // put your setup code here, to run once:
    pinMode(GREEN, OUTPUT);
    pinMode(YELLOW, OUTPUT);
    pinMode(RED, OUTPUT);
    pinMode(trigPin, OUTPUT); // Sets the trigPin as an OUTPUT
    pinMode(echoPin, INPUT); // Sets the echoPin as an INPUT
     }

    void loop() {

    ultra();

    if ( distance <= 5 && flag == 0)
    {//H
      flag = 1 ;}
    } //high pulse (When the distance <=5)

    if ( distance >5 && flag == 1)
    {//L
      red_light(); }

    }//the led should turned on when low pulse appears (When the distance >5)

    void red_light()
    { digitalWrite(GREEN, LOW);
    digitalWrite(YELLOW, LOW);
    digitalWrite(RED, HIGH); }

    void ultra()
    { digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, HIGH);
    distance = duration*0.034/2; }

//this is my code

I don't quite understand, what you are trying to do here. So the red LED should light up, when the distance gets lower than 5cm. But what should then happen? Should it stay on forever? Should it go off, when the distance gets higher than 5cm?

no , the red led should light up when( distance gets lower than 5cm and then after that gets greater than 5cm ) , I try to turned in the led after I get ( a HIGH signal then LOW)

and yes I want it turned on forever . can u understand me now ?

why do you have two closing braces for the first if loop in the  void() function?

Yes, now that is clear. Can you please give a detailed description, what actually happens (instead of the "it doesn't work) with your code? Or do you get an error during compilation? If yes, please provide the full error message. PS: You use the terms HIGH signal and LOW signal in a wrong way, which is a bit confusing. HIGH and LOW are about the digital signal on the pin, not about the measured pulse length. So you want to trigger your code, when the pulse length walks around the mark for 5cm. You don't want to trigger it after a LOW signal.

what actually happens with this code  is  when I put something near the sensor <= 5 , the led is on without i removed the thing , but i want the led on ehen i put then removr the thing , how i should do this ?

@goodarduinocode it's a syntax error, but it's not the problem hear

what actually happens with this code is when I put something near the sensor <= 5 , the led is on without i removed the thing , but I want the led on when I put then remove the thing

Here is my theory on what happens here. You can confirm it by using one of the solutions, that I will explain below.
Currently your code is measuring the distance as fast as it can. The measurement is what takes the longest time in one iteration of the loop() function. Thus you get many many measurements per second. But such distance measurements are always noisy, meaning that the values change randomly in a specific range. When you put the object in front of the sensor, you expect the values to just go down, but actually they are sometimes rising again for 1 or 2 values because of the noise. So the measured values might look something like this (only imagined for making the point; not real values):
5.4 --> 5.2 --> 4.99 --> 5.001 --> 4.89 --> 4.90 --> 4.5

Overall the values go down, but you are comparing always the current value with the fixed threshold of 5cm. When the noise just raises the value again, while you pass 5cm, you will get a false "put and removed again" outcome. At the probability  of the noise doing that is really high, since you measure that often and ultrasonic sensors are not accurate down to millimeters. You could even have the distance pass 5cm multiple times due to the noise.
There are some possibilities to reduce noise or to handle it.

Hysteresis: The first, that I would implement here is hysteresis. That means, that you set the "put" distance different than the "remove" distance. For example you could use 5cm as the distance to register, that the object is put in front of the sensor, but then you wait for the distance to go above 7cm to actually treat the object as "removed". You need to choose the difference between the distances larger than the noise (you can find that out via experimenting). This principle is also used directly with noisy digital signals on the Arduinos input pins. An Arduino Uno will treat voltages above about 2.6V as digital 1 (HIGH signal), and a value below 2.1V as digital 0 (LOW signal) (taken from the datasheet of the Atmega328P, which is the microcontroller on an Arduino Uno, while assuming the controller running on 5V like in an Arduino Uno). In electrical terms this is called a Schmitt-Trigger.
For implementing this, you can just change the threshold values in your if statements.

You can reduce the noise by always measuring multiple times in a row and then calculating the mean value from it. Since a part of the noise is random, you can smoothe out this part a bit through taking the mean. That also reduces your time resolution, but in such a simple use case that mostly doesn't matter that much.

If the reaction time doesn't matter that much, you could reduce the frequency of measurements, so that subsequent distance measurements are already to far away from each other for the noise to create false triggers. This is worse than the other solutions, since it also depends on how fast you put the object in front of the sensor, but it is really easy to implement (just a simple delay() call, or better using millis() like in the BlinkWithoutDelay example for non-blocking code)

I would first implement the hysteresis. Then, if the difference in distances, that you need for it to work good, is too big for you, you can take the mean of multiple value to reduce the noise.

And just for protocol, as it already was said in the comments: Your first if statement has an extra closing bracket } which should not be there.


text:
Best way to add external power supply when main PSU is a solar charge controller?
I have a 12V 20A Solar Charge Controller (which is part of my existing Solar Panel System Setup connected to a 12V Sealed Lead Acid Battery) that I will use to power up some pumps with the help of relays and some sensors. And because its a solar charge controller, the output varies depending on the sun, from 12.1v to 13.8v (I set the Load Reconnect, Load Disconnect, Float Charge etc which technically 12V to 13.8V)
How do I power my Arduino Mega safely in this case?
I am planning on using a separate buck converter that will give my Arduino a fixed 9V from the Solar Charge Controller.
Should I power the Arduino with the buck converter parallel to the same PSU (the 12V 20A Solar Charge Controller) I'm using for the pumps and is it safe that way?
or
Should I use a 9V battery to separately power the Arduino Mega?  and what is the explanation behind the concept of using an external PSU for the Arduino Mega when the total Amperes all in all is not exceeding the limit 20A at all?

I'm no expert in this, but isn't a buck converter holding the set voltage independent of the input, as long as it is high enough (giving it some headroom for working correctly). Then a varying voltage from 12 to 13V should not cause problems.

You didn't mention that you had a 12 volt nominal battery.  Maybe because there's a reason why you don't want to use it. I bring this up because typical solar charge controllers of the kind that would normally have something like an 12 VDC nominal lead acid battery bank (perhaps just one battery) attached to them, have their internal electronics powered from the battery bank itself.  In other words, most solar charge controllers cannot be used just as live voltage regulator powering a load without also a battery. I just want to make sure you have considered this.

20A is the redline on the charge controller.  It doesn't output 20A unless the solar panels are delivering >=20A.

@timemage, yes i edited my question. thanks for the information.

@Harper-ReinstateMonica may load total is lower than 20A, and the pumps and sensors will not turn on at the same time, thats why i want to integrate Arduino in my set up. I used fuses and relays just in case so that my set up will be safe

@chrisl thats what i thought too but then my arduino's ground is connected to the positve of the scc when i check for continuity and i find it strange, im not an expert in electronics and im scared i might fry m arduino

"arduino's ground is connected to the positve of the scc" Did you mean "negative" instead?  Because this makes no sense to me generally, nor in connection with chrisl's original comment.

@timemage not negative,i really meant positive which i know is not right and im weirded out, i thought  its because of i paralled the Arduino the the SCC Vout with the pumps

Should I power the Arduino with the buck converter parallel to the same PSU (the 12V 20A Solar Charge Controller) I'm using for the pumps

Yes. However I wouldn't use a 9V buck regulator, but a 5V one and feed it to the 5V pin. That way you bypass the wasteful LDO on the Arduino, and when running from solar every bit of power saving you can muster helps.

and is it safe that way?

Yes, it's safe. As long as the buck regulator you are using is rated for the voltages in question.

An Arduino is no load for a solar panel that can provide 20A. So I wouldn't bother the complexity and just use a 12V battery and the on-board converter.

@PMF is not about the load. It's about the heat with such a massive voltage drop.

I see, but wouldn't you have that anyway, even if you use some external DC/DC converter? Or are those more efficient than the onboard one?

@PMF They are massively more efficient. The LDO converts the voltage difference into heat. A DC/DC converter chops it up to change the average power throughput.

If possible, I would feed the 5V via the USB connector rather than 5V pin, so you can take advantage of the Arduino Mega's PTC fuse.

@Majenko i'll definitely do that  thank you so much

Ok first, you need a battery for all this to work.  The solar charge controller won't drive into nothin', that is not what they are designed to do.
Its full name is "solar battery charge controller".   Size the battery any way you like, just make sure the charge controller knows what kind it is, so it sets the proper charge curves and doesn't overcharge it/boil it dry/make it catch fire (lithium).
Once you have a battery in the system, paralleling in another battery charger is not a problem, be it wind, AC mains, or another solar CC.

Now, you will need to manage the case where the Arduino calls for the pump to turn on, but the solar panel is not making enough power to successfully power the pump.  This will not magically sort itself out.

If you did not have a battery, it'll "crow bar".  The pump would effectively pull the solar voltage to near zero, which would cause the Arduino to shut down, turning off the pump and causing solar voltage to recover.  The Arduino would reboot, try again, and fail again.  Repeating.  So a crow-bar condition.

If you do have a battery, then the Arduino will successfully spin up the pump, but, the solar won't be enough and this will be depleting the battery.  If your usage runs the battery flat, see crow-bar above.

If you have a battery and the Arduino monitors battery voltage, it can defer operation until the Arduino knows the battery is sufficiently charged for the work needed.  At this point you don't need to care if the solar is up, the battery will carry the "buffer".    Make sure to shut the load off before the battery is depleted enough to create a crow-bar condition.

Note that if the battery is lead-acid, it should be managed to stay within 60-100% state of charge.  Depleting a lead-acid below 60% of max will rapidly age the battery.  It probably will be, since they are a happy intersection of "cheap" and "well-supported by every charge controller ever made".
Power to the Arduino itself should be taken as close as possible to the energy source (e.g. battery) — even if that means a long, redundant cable, especially in that case actually.  Do not share a supply cable with motors or pumps or other heavy loads!!!  I have seen many installations where the startup current of the motor causes enough voltage drop down the shared supply cable to cause the Arduino to lose power and reboot.   That is quickly cured by running a redundant V+ and V- power cable just for the Arduino.

Thanks for that detailed explanation, im sorry that my scc info was unclear and so i edited my question.. im using thick wires at short distance to prevent voltage drop. i used cable terminals to easily manage the wires of the system. Should i use the same breaker for the main Output of my SCC and parallel my arduino power right there with the pumps(but a different wire for the arduino)? or can i just use the terminals? thanks


text:
Sim800L does not send SMS messages in a row
I created a project with sim800l that comes and stores 5 phone numbers in eeprom memory and then when a sensor is triggered, it sms all the numbers and then calls the first one.
But the module does not send an SMS to everyone and only sends an SMS to the first number and then nothing else and then calls. The problem is not that the numbers are not read correctly, because when sending the text message, I said, show the number in the monitor series and it will show correctly. It is not a problem not to send a text message request because I also connected a usb to ttl module to the tx rx module and saw that it comes for all numbers and at sends the at command correctly.

#include <EEPROM.h>
#include <SoftwareSerial.h>

#define SIM800RX 7 //D7 - SIM800L RX PIN
#define SIM800TX 8 //D8 - SIM800L TX PIN

#define SENSOR1SMSTEXT "Fire error" //Sensor 1 SMS Text
#define SENSOR2SMSTEXT "Theft error" //Sensor 2 SMS Text

SoftwareSerial SIM800(SIM800RX, SIM800TX);

String readSerial(String txt) {
  SIM800.flush();
  if (SIM800.readString() != "") {
    while (SIM800.readString() != "") {}
  }
  String text = "";
  if (txt != "") {
    SIM800.println(txt);
    int timeout = 0;
    while  (!SIM800.available() && timeout < 12000) {
      delay(1);
      timeout++;
    }
    if (SIM800.available()) {
      text = SIM800.readString();
    }
  }
  return text;
}

void readSerialOK(String txt) {
  while (readSerial(txt).indexOf("OK") == -1) {
    delay(700);
  }
}

void configSim800L() {
  readSerialOK("AT");
  delay(200);
  readSerialOK("AT+CMGF=1");
  delay(200);
  readSerialOK("AT+CNMI=1,2,0,0,0");
  delay(200);
  readSerialOK("AT+CMGDA=\"DEL ALL\"");
  delay(200);
  readSerialOK("AT+CSMP=17,167,0,0");
  delay(200);
}

void SendTextSMS(String num, String sms) {
  SIM800.print("AT+CMGS=\"");
  SIM800.print(num);
  SIM800.println("\"");
  delay(150);
  SIM800.print(sms);
  SIM800.write(26);
  delay(700);
  Serial.println("");
  Serial.print("Send SMS to:");
  Serial.print(num);
  Serial.print(":");
  Serial.println(sms);
}

bool checkPhone(String phone) {
  if (phone.substring(0, 2) == "09" && phone.length() == 11) {
    return true;
  } else {
    return false;
  }
}

void WriteEEPROM(byte part, String val) {
  int start_addw = part * 16;
  int w_len = val.length();
  EEPROM.write(start_addw, w_len + 1);
  int end_w = start_addw + w_len;
  byte len = 0;
  for (int i = start_addw + 1; i < end_w + 1; i++) {
    EEPROM.write(i, int(val[len]));
    len++;
  }
  len = 0;
  EEPROM.commit();
}

String ReadEEPROM(byte part) {
  int start_addr = part * 16;
  String str;
  int ch;
  int r_len = EEPROM.read(start_addr);
  int end_r = start_addr + r_len;
  for (int i = start_addr + 1; i < end_r; i++) {
    ch = EEPROM.read(i);
    str += char(ch);
  }
  if (checkPhone(str) == false) {
    str = "";
  }
  return str;
}

void ClearEEPROM(byte part) {
  int start_addw = part * 16;
  int w_len = 11;
  EEPROM.write(start_addw, 0);
  int end_w = start_addw + w_len;
  byte len = 0;
  for (int i = start_addw + 1; i < end_w + 1; i++) {
    EEPROM.write(i, 0);
    len++;
  }
  len = 0;
  EEPROM.commit();
}

void SendSMS(String sms) {
  String num1 = ReadEEPROM(1);
  String num2 = ReadEEPROM(2);
  String num3 = ReadEEPROM(3);
  String num4 = ReadEEPROM(4);
  String num5 = ReadEEPROM(5);
  if (num1 != "") {
    SendTextSMS(num1, sms);
  }
  if (num2 != "") {
    SendTextSMS(num2, sms);
  }
  if (num3 != "") {
    SendTextSMS(num3, sms);
  }
  if (num4 != "") {
    SendTextSMS(num4, sms);
  }
  if (num5 != "") {
    SendTextSMS(num5, sms);
  }
}

void Call() {
  String call = "";
  String num1 = ReadEEPROM(1);
  String num2 = ReadEEPROM(2);
  String num3 = ReadEEPROM(3);
  String num4 = ReadEEPROM(4);
  String num5 = ReadEEPROM(5);
  if (num1 != "") {
    call = num1;
  } else if (num2 != "") {
    call = num2;
  } else if (num3 != "") {
    call = num3;
  } else if (num4 != "") {
    call = num4;
  } else if (num5 != "") {
    call = num5;
  }
  Serial.println("");
  Serial.print("Call to:");
  Serial.print(call);
  if (call != "") {
    readSerialOK("ATD"+call+";");
    delay(300);
  }
}

void trigSensor1() {
  SendSMS(SENSOR1SMSTEXT);
  Call();
}

void trigSensor2() {
  SendSMS(SENSOR2SMSTEXT);
  Call();
}

void setup() {
  SIM800.begin(9600);
  Serial.begin(9600);
  EEPROM.begin(512);
  pinMode(IN1, INPUT_PULLUP);
  pinMode(IN2, INPUT);
  pinMode(SSS, OUTPUT);
  digitalWrite(SSS, LOW);
  while (readSerial("AT+COPS?").indexOf("+COPS: 0,0,\"") == -1) {
    delay(700);
  }
  configSim800L();
  digitalWrite(SSS, HIGH);
}

void loop() {
  if (digitalRead(IN1) == LOW) {
      trigSensor1();
  }
  if (digitalRead(IN2) == HIGH) {
      trigSensor2();
  }
}

Thanks if friends have experience in this area tell me.
Thanks in advance.

this exact problem and solution is repeated many times on the internet

I find error:
void SendTextSMS(String num, String sms) {
  SIM800.print("AT+CMGS=\"");
  SIM800.print(num);
  SIM800.println("\"");
  delay(150);
  SIM800.print(sms);
  SIM800.write(26);
  delay(3000);
  Serial.println("");
  Serial.print("Send SMS to:");
  Serial.print(num);
  Serial.print(":");
  Serial.println(sms);
}

i replaced delay with 3000ms the error solved.


text:
ATMega328 functions, but will not output to any pins
Problem:
ATMega328 Refuses to digitalWrite() to any pins, I can upload and run sketches using the board UNO from the ide on the 328 and can confirm it is working using the serial monitor (see code).
I am using this FTDI module.
Board Manager -- UNO works, but ATMega328 Doesn't

By using the UNO board under board manager, I am capable of writing sketches and communicating with the 328 just fine.
But when I use the ATMega328 at 5.5V,16Mhz I receive the following error.
         Using Port                    : COM3

         Using Programmer              : arduino

         Overriding Baud Rate          : 57600

avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xe0

avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xe0

avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xe0

avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xe0

avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x00

avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xe0

avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xe0

avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00

avrdude done.  Thank you.

Code & Serial Monitor "Proving" it works
I have tried every usable PWM and other pins to attempt to output using LED's, buzzers and even other Arduino's to read inputs but none of the pins will output high when requested.
I believe that Arduino IDE is attempting to compile my code for the UNO and those pins do not work on the ATMega328 but this could be completely incorrect and someone please correct me if this is a wrong assumption.
Lastly, I have been able to use the SCL and SCA pins to communicate with an I2C LED shield.
Does anyone know why I cannot write sketch to the ATMega328 using the FTDI and my configuration.
Posted Below are images and very rough Fritzing schematics of how I am setup.
void setup() {
  Serial.begin(9600);
  pinMode(5,OUTPUT);
}

void loop() {
  Serial.println("TICK");
  digitalWrite(5,HIGH);
  delay(1000);
  digitalWrite(5,LOW);
  }

My Breadboard

Fritzing Schematic

the top bus of your breadboard is not powered ... why do you say that you can upload a sketch and then present an error listing that shows an upload failure?

pin 5 is low only a few milliseconds

The top part of my breadboard IS powered, I have two cables to the right, as shown in the second fritzing but just out of frame on the camera. If you read the text in the question I explain "By using the UNO board under board manager, I am capable of writing sketches and communicating with the 328 just fine. But when I use the ATMega328 at 5.5V,16Mhz I receive the following error."

What do you mean by when I use the ATMega328 at 5.5V,16Mhz. Do you mean that you're using the Board Manager with that setting (as opposed to the selecting the Uno)? What Board Manager did you install for that (MiniCore?). Did you (re)flash the bootloader with the ATMega328 selected in Board Manager?

The error message you get means it can find the Arduino to be programmed. So your sketch isn't being uploaded, and thus you pins won't change. Not sure why you'd still get the serial output. My guess would be that that's an old sketch.

@StarCat https://imgur.com/8GR4GOs this is a link to what settings I am talking about, Arduino IDE gives you the option to select what chip, frequency and voltage your board is operating at. Using these settings I have been unable to write sketches to my board. The bootloader is a PU, I have not attempted to reflash the bootloader on my chip.

You've selected the Arduino Pro in Board Manager and the "AVRISP MkII" programmer. You can't simply choose a different board manager and programmer and expect to keep using the same bootloader you've used for an Arduino Uno (although they have the same processor). You need to program the Arduino Pro bootloader into your ATMega328 or just keep using the Arduino Uno from Board Manager and the ArduinoISP programmer. Please add the image you linked to, to your question.

In combination with Nick Gammon's answer above, I was not aware that the physical pin numbers are different from the digital pin numbers used in the sketch. I resolved my issue by referring to this digital pin map.

This may not be your only problem, but you need a second delay.
void loop() {
  Serial.println("TICK");
  digitalWrite(5,HIGH);
  delay(1000);
  digitalWrite(5,LOW);
  delay(1000);    // LOW for a second as well
  }

Otherwise you will not be able to see the LOW part, because it will be really quick.

I believe that Arduino IDE is attempting to compile my code for the UNO and those pins do not work on the ATMega328

The Uno has an Atmega328 on it, and I usually compile for the Uno when uploading to a custom board, so this is not the issue.

How old is your chip, or the bootloader on it? Most chips sold (with bootloaders preloaded) - and bootloaders available to upload - for the last several years at least, have uploaded at 115200 baud.