text:
240*320 transparent OLED display with Arduino
A long time ago I ordered this transparent OLED display (from a chinese supplier on alibaba) planning on interfacing it with an Arduino but didn't really have the skills to get the project going.
I have the datasheet (linked below) for the driver and it seems to come with a schematic on it which takes the output from the OLED and gives me 8-bit wiring. My plan is to use the adafruit GFX library with it and probably steal the code from this adafruit TFT.
Please, someone tell me if this has no hope of working but my plan as it stands is:
1) draw up the datasheets schematic into Kicad, and get it printed onto a PCB (I am worried that if I breadboard/protoboard it, ill have all kinds of issues coming from my poor perfboarding skills and I want to be able to narrow down my problems. I know it's bad practise to print a PCB before doing any breadboarding but I don't think ill successfully manage it)
2) wire up the output pins from the new PCB in the same way that the adafruit board and try and use the same code.
3) Here are where the problems come I think as I am proficient at simple code (I'm probably being ignorant to the fact that 'simple' code is still way above my level) e.g functions/loops etc... but writing code like adafruits example for displays is way above my level. I hope that I can just edit some of Adafruits existing example code and it will just work.
A few years ago I asked a similar question on the Arduino forum but then I was much worse at programming and had less of an idea where to start.
If any of you can provide insight into if this will work or any better ideas then I am all ears.
Thanks
Documents containing datasheets and example code - https://drive.google.com/drive/folders/1ZTmipJKRKWNMudYVQ5ATxixbQtKD4hQm?usp=sharing

edit:
there is also a file called example_code.txt which contains a lot of (I dont know what I'm talking about really) hex commands.
edit 2: - ILI9341 Mock Example
/***************************************************
  This is our GFX example for the Adafruit ILI9341 Breakout and Shield
  ----> http://www.adafruit.com/products/1651

  Check out the links above for our tutorials and wiring diagrams
  These displays use SPI to communicate, 4 or 5 pins are required to
  interface (RST is optional)
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
 ****************************************************/

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

// For the Adafruit shield, these are the default.
#define TFT_DC 9
#define TFT_CS 10

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
// If using the breakout, change pins as desired
//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {
  Serial.begin(9600);
  Serial.println("ILI9341 Test!");

  tft.begin();

  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);

  Serial.println(F("Benchmark                Time (microseconds)"));
  delay(10);
  Serial.print(F("Screen fill              "));
  Serial.println(testFillScreen());
  delay(500);

  Serial.print(F("Text                     "));
  Serial.println(testText());
  delay(3000);

  Serial.print(F("Lines                    "));
  Serial.println(testLines(ILI9341_CYAN));
  delay(500);

  Serial.print(F("Horiz/Vert Lines         "));
  Serial.println(testFastLines(ILI9341_RED, ILI9341_BLUE));
  delay(500);

  Serial.print(F("Rectangles (outline)     "));
  Serial.println(testRects(ILI9341_GREEN));
  delay(500);

  Serial.print(F("Rectangles (filled)      "));
  Serial.println(testFilledRects(ILI9341_YELLOW, ILI9341_MAGENTA));
  delay(500);

  Serial.print(F("Circles (filled)         "));
  Serial.println(testFilledCircles(10, ILI9341_MAGENTA));

  Serial.print(F("Circles (outline)        "));
  Serial.println(testCircles(10, ILI9341_WHITE));
  delay(500);

  Serial.print(F("Triangles (outline)      "));
  Serial.println(testTriangles());
  delay(500);

  Serial.print(F("Triangles (filled)       "));
  Serial.println(testFilledTriangles());
  delay(500);

  Serial.print(F("Rounded rects (outline)  "));
  Serial.println(testRoundRects());
  delay(500);

  Serial.print(F("Rounded rects (filled)   "));
  Serial.println(testFilledRoundRects());
  delay(500);

  Serial.println(F("Done!"));

}

void loop(void) {
  for(uint8_t rotation=0; rotation<4; rotation++) {
    tft.setRotation(rotation);
    testText();
    delay(1000);
  }
}

unsigned long testFillScreen() {
  unsigned long start = micros();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  tft.fillScreen(ILI9341_RED);
  yield();
  tft.fillScreen(ILI9341_GREEN);
  yield();
  tft.fillScreen(ILI9341_BLUE);
  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();
  return micros() - start;
}

unsigned long testText() {
  tft.fillScreen(ILI9341_BLACK);
  unsigned long start = micros();
  tft.setCursor(0, 0);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ILI9341_YELLOW); tft.setTextSize(2);
  tft.println(1234.56);
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println(0xDEADBEEF, HEX);
  tft.println();
  tft.setTextColor(ILI9341_GREEN);
  tft.setTextSize(5);
  tft.println("Groop");
  tft.setTextSize(2);
  tft.println("I implore thee,");
  tft.setTextSize(1);
  tft.println("my foonting turlingdromes.");
  tft.println("And hooptiously drangle me");
  tft.println("with crinkly bindlewurdles,");
  tft.println("Or I will rend thee");
  tft.println("in the gobberwarts");
  tft.println("with my blurglecruncheon,");
  tft.println("see if I don't!");
  return micros() - start;
}

unsigned long testLines(uint16_t color) {
  unsigned long start, t;
  int           x1, y1, x2, y2,
                w = tft.width(),
                h = tft.height();

  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1 = y1 = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t     = micros() - start; // fillScreen doesn't count against timing

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = w - 1;
  y1    = 0;
  y2    = h - 1;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = 0;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = w - 1;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
  t    += micros() - start;

  yield();
  tft.fillScreen(ILI9341_BLACK);
  yield();

  x1    = w - 1;
  y1    = h - 1;
  y2    = 0;
  start = micros();
  for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
  x2    = 0;
  for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);

  yield();
  return micros() - start;
}

unsigned long testFastLines(uint16_t color1, uint16_t color2) {
  unsigned long start;
  int           x, y, w = tft.width(), h = tft.height();

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
  for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);

  return micros() - start;
}

unsigned long testRects(uint16_t color) {
  unsigned long start;
  int           n, i, i2,
                cx = tft.width()  / 2,
                cy = tft.height() / 2;

  tft.fillScreen(ILI9341_BLACK);
  n     = min(tft.width(), tft.height());
  start = micros();
  for(i=2; i<n; i+=6) {
    i2 = i / 2;
    tft.drawRect(cx-i2, cy-i2, i, i, color);
  }

  return micros() - start;
}

unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
  unsigned long start, t = 0;
  int           n, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  n = min(tft.width(), tft.height());
  for(i=n; i>0; i-=6) {
    i2    = i / 2;
    start = micros();
    tft.fillRect(cx-i2, cy-i2, i, i, color1);
    t    += micros() - start;
    // Outlines are not included in timing results
    tft.drawRect(cx-i2, cy-i2, i, i, color2);
    yield();
  }

  return t;
}

unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(x=radius; x<w; x+=r2) {
    for(y=radius; y<h; y+=r2) {
      tft.fillCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testCircles(uint8_t radius, uint16_t color) {
  unsigned long start;
  int           x, y, r2 = radius * 2,
                w = tft.width()  + radius,
                h = tft.height() + radius;

  // Screen is not cleared for this one -- this is
  // intentional and does not affect the reported time.
  start = micros();
  for(x=0; x<w; x+=r2) {
    for(y=0; y<h; y+=r2) {
      tft.drawCircle(x, y, radius, color);
    }
  }

  return micros() - start;
}

unsigned long testTriangles() {
  unsigned long start;
  int           n, i, cx = tft.width()  / 2 - 1,
                      cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  n     = min(cx, cy);
  start = micros();
  for(i=0; i<n; i+=5) {
    tft.drawTriangle(
      cx    , cy - i, // peak
      cx - i, cy + i, // bottom left
      cx + i, cy + i, // bottom right
      tft.color565(i, i, i));
  }

  return micros() - start;
}

unsigned long testFilledTriangles() {
  unsigned long start, t = 0;
  int           i, cx = tft.width()  / 2 - 1,
                   cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(cx,cy); i>10; i-=5) {
    start = micros();
    tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(0, i*10, i*10));
    t += micros() - start;
    tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
      tft.color565(i*10, i*10, 0));
    yield();
  }

  return t;
}

unsigned long testRoundRects() {
  unsigned long start;
  int           w, i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  w     = min(tft.width(), tft.height());
  start = micros();
  for(i=0; i<w; i+=6) {
    i2 = i / 2;
    tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
  }

  return micros() - start;
}

unsigned long testFilledRoundRects() {
  unsigned long start;
  int           i, i2,
                cx = tft.width()  / 2 - 1,
                cy = tft.height() / 2 - 1;

  tft.fillScreen(ILI9341_BLACK);
  start = micros();
  for(i=min(tft.width(), tft.height()); i>20; i-=6) {
    i2 = i / 2;
    tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
    yield();
  }

  return micros() - start;
}

edit 3: - ili9341 header file
/*!
 * @file Adafruit_ILI9341.h
 *
 * This is the documentation for Adafruit's ILI9341 driver for the
 * Arduino platform.
 *
 * This library works with the Adafruit 2.8" Touch Shield V2 (SPI)
 *    http://www.adafruit.com/products/1651
 * Adafruit 2.4" TFT LCD with Touchscreen Breakout w/MicroSD Socket - ILI9341
 *    https://www.adafruit.com/product/2478
 * 2.8" TFT LCD with Touchscreen Breakout Board w/MicroSD Socket - ILI9341
 *    https://www.adafruit.com/product/1770
 * 2.2" 18-bit color TFT LCD display with microSD card breakout - ILI9340
 *    https://www.adafruit.com/product/1770
 * TFT FeatherWing - 2.4" 320x240 Touchscreen For All Feathers
 *    https://www.adafruit.com/product/3315
 *
 * These displays use SPI to communicate, 4 or 5 pins are required
 * to interface (RST is optional).
 *
 * Adafruit invests time and resources providing this open source code,
 * please support Adafruit and open-source hardware by purchasing
 * products from Adafruit!
 *
 *
 * This library depends on
 * Adafruit_GFX being present on your system. Please make sure you have
 * installed the latest version before using this library.
 *
 * Written by Limor "ladyada" Fried for Adafruit Industries.
 *
 * BSD license, all text here must be included in any redistribution.
 *
 */

#ifndef _ADAFRUIT_ILI9341H_
#define _ADAFRUIT_ILI9341H_

#include "Adafruit_GFX.h"
#include "Arduino.h"
#include "Print.h"
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <SPI.h>

#define ILI9341_TFTWIDTH 240  ///< ILI9341 max TFT width
#define ILI9341_TFTHEIGHT 320 ///< ILI9341 max TFT height

#define ILI9341_NOP 0x00     ///< No-op register
#define ILI9341_SWRESET 0x01 ///< Software reset register
#define ILI9341_RDDID 0x04   ///< Read display identification information
#define ILI9341_RDDST 0x09   ///< Read Display Status

#define ILI9341_SLPIN 0x10  ///< Enter Sleep Mode
#define ILI9341_SLPOUT 0x11 ///< Sleep Out
#define ILI9341_PTLON 0x12  ///< Partial Mode ON
#define ILI9341_NORON 0x13  ///< Normal Display Mode ON

#define ILI9341_RDMODE 0x0A     ///< Read Display Power Mode
#define ILI9341_RDMADCTL 0x0B   ///< Read Display MADCTL
#define ILI9341_RDPIXFMT 0x0C   ///< Read Display Pixel Format
#define ILI9341_RDIMGFMT 0x0D   ///< Read Display Image Format
#define ILI9341_RDSELFDIAG 0x0F ///< Read Display Self-Diagnostic Result

#define ILI9341_INVOFF 0x20   ///< Display Inversion OFF
#define ILI9341_INVON 0x21    ///< Display Inversion ON
#define ILI9341_GAMMASET 0x26 ///< Gamma Set
#define ILI9341_DISPOFF 0x28  ///< Display OFF
#define ILI9341_DISPON 0x29   ///< Display ON

#define ILI9341_CASET 0x2A ///< Column Address Set
#define ILI9341_PASET 0x2B ///< Page Address Set
#define ILI9341_RAMWR 0x2C ///< Memory Write
#define ILI9341_RAMRD 0x2E ///< Memory Read

#define ILI9341_PTLAR 0x30    ///< Partial Area
#define ILI9341_VSCRDEF 0x33  ///< Vertical Scrolling Definition
#define ILI9341_MADCTL 0x36   ///< Memory Access Control
#define ILI9341_VSCRSADD 0x37 ///< Vertical Scrolling Start Address
#define ILI9341_PIXFMT 0x3A   ///< COLMOD: Pixel Format Set

#define ILI9341_FRMCTR1                                                        \
  0xB1 ///< Frame Rate Control (In Normal Mode/Full Colors)
#define ILI9341_FRMCTR2 0xB2 ///< Frame Rate Control (In Idle Mode/8 colors)
#define ILI9341_FRMCTR3                                                        \
  0xB3 ///< Frame Rate control (In Partial Mode/Full Colors)
#define ILI9341_INVCTR 0xB4  ///< Display Inversion Control
#define ILI9341_DFUNCTR 0xB6 ///< Display Function Control

#define ILI9341_PWCTR1 0xC0 ///< Power Control 1
#define ILI9341_PWCTR2 0xC1 ///< Power Control 2
#define ILI9341_PWCTR3 0xC2 ///< Power Control 3
#define ILI9341_PWCTR4 0xC3 ///< Power Control 4
#define ILI9341_PWCTR5 0xC4 ///< Power Control 5
#define ILI9341_VMCTR1 0xC5 ///< VCOM Control 1
#define ILI9341_VMCTR2 0xC7 ///< VCOM Control 2

#define ILI9341_RDID1 0xDA ///< Read ID 1
#define ILI9341_RDID2 0xDB ///< Read ID 2
#define ILI9341_RDID3 0xDC ///< Read ID 3
#define ILI9341_RDID4 0xDD ///< Read ID 4

#define ILI9341_GMCTRP1 0xE0 ///< Positive Gamma Correction
#define ILI9341_GMCTRN1 0xE1 ///< Negative Gamma Correction
//#define ILI9341_PWCTR6     0xFC

// Color definitions
#define ILI9341_BLACK 0x0000       ///<   0,   0,   0
#define ILI9341_NAVY 0x000F        ///<   0,   0, 123
#define ILI9341_DARKGREEN 0x03E0   ///<   0, 125,   0
#define ILI9341_DARKCYAN 0x03EF    ///<   0, 125, 123
#define ILI9341_MAROON 0x7800      ///< 123,   0,   0
#define ILI9341_PURPLE 0x780F      ///< 123,   0, 123
#define ILI9341_OLIVE 0x7BE0       ///< 123, 125,   0
#define ILI9341_LIGHTGREY 0xC618   ///< 198, 195, 198
#define ILI9341_DARKGREY 0x7BEF    ///< 123, 125, 123
#define ILI9341_BLUE 0x001F        ///<   0,   0, 255
#define ILI9341_GREEN 0x07E0       ///<   0, 255,   0
#define ILI9341_CYAN 0x07FF        ///<   0, 255, 255
#define ILI9341_RED 0xF800         ///< 255,   0,   0
#define ILI9341_MAGENTA 0xF81F     ///< 255,   0, 255
#define ILI9341_YELLOW 0xFFE0      ///< 255, 255,   0
#define ILI9341_WHITE 0xFFFF       ///< 255, 255, 255
#define ILI9341_ORANGE 0xFD20      ///< 255, 165,   0
#define ILI9341_GREENYELLOW 0xAFE5 ///< 173, 255,  41
#define ILI9341_PINK 0xFC18        ///< 255, 130, 198

/**************************************************************************/
/*!
@brief Class to manage hardware interface with ILI9341 chipset (also seems to
work with ILI9340)
*/
/**************************************************************************/

class Adafruit_ILI9341 : public Adafruit_SPITFT {
public:
  Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _MOSI, int8_t _SCLK,
                   int8_t _RST = -1, int8_t _MISO = -1);
  Adafruit_ILI9341(int8_t _CS, int8_t _DC, int8_t _RST = -1);
#if !defined(ESP8266)
  Adafruit_ILI9341(SPIClass *spiClass, int8_t dc, int8_t cs = -1,
                   int8_t rst = -1);
#endif // end !ESP8266
  Adafruit_ILI9341(tftBusWidth busWidth, int8_t d0, int8_t wr, int8_t dc,
                   int8_t cs = -1, int8_t rst = -1, int8_t rd = -1);

  void begin(uint32_t freq = 0);
  void setRotation(uint8_t r);
  void invertDisplay(bool i);
  void scrollTo(uint16_t y);
  void setScrollMargins(uint16_t top, uint16_t bottom);

  // Transaction API not used by GFX
  void setAddrWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h);

  uint8_t readcommand8(uint8_t reg, uint8_t index = 0);
};

#endif // _ADAFRUIT_ILI9341H_

The critical part, assuming your hardware works, is getting the software going. Not all OLEDs are the same, and different ones need different commands to get them working.
You can't just take a random OLED and use a random library - it needs a driver to make it work.
In this case it's the DA8620 that is the main chip that you want to worry about, and your chosen library has to implement the commands and methodologies for that specific chip.
Now, you have a file that contains those commands (all the "hex commands"), and if you can't find an existing library to work with the DA8620 then you will have to write or adapt one while referring to those commands.  You can find out more about what the commands all mean by referencing the datasheet, which lists all the commands and their parameters (from page 78 onwards), so you should be able to relate those to what an existing library needs and map things accordingly while keeping the right power-up sequences.

Thanks for the info. Unfortunately, the DA8620 seems to be niche and also discontinued so it's very tricky to find any information let alone an Arduino driver. If I decided to try and adapt an existing library, for example, the Adafruit GFX, would it be so easy as changing some commands in the library to match the commands written in the datasheet? I assume that is not how it works at all and I am probably way out of my depth here.
How would I go about changing a library? Thanks

@VosemMedia That is probably exactly how it works. Find what the library does, and then find the commands that do that job in the datasheet and match those to the examples in the file of commands you have.

Okay, thankyou. Do you have any reccomendations for libraries to start with? Do you think that one I linked earlier would be an okay starting point? Thanks

The Adafruit one is good because it is split into sections - one for the drawing primitives (the GFX library) and the other for the OLED driver.

Okay, I edited in an adafruit GFX example code for some irrelivent 2.4" tft. It references some functions like tft.setTextColor and tft.println. I need to edit those functions right? Or am I on the completely wrong line and should be looking somewhere else. If im not, would these magical commands be in Adafruit_GFX.h or Adafruit_ILI9341.h? Thanks

Adafruit_GFX,h is the parent class. It contains the high level stuff that you as a user interact with.  It neither knows nor cares what the OLED is.  Adafruit_ILI9341.h is the low level OLED / LCD interaction code and is what you should be editing.

Wow, this looks really promising. I edited in the Adafruit_ILI9341.h as well. The language on the datasheet is very similar to the language on the header file which looks good. Providing the hardware works and I manage to edit in all the commands correctly, should I be able to run the ILI9341 example .ino file and it all work smoothly? Cheers again for the help

That is what is to be hoped for, yes.

There is a 0x06 (RDRED Read Red Color) 0x07 (green) 0x08 (blue) in the datasheet but not in the header. Should I add it in?

There are also a number of ones that only exist in the header file (0x10, 0x11,0x12, 0x13)

The header should contain what you need. Remove anything that is specific to the old LCD and replace it with equivalents from the new OLED. If there are things about the OLED that the library doesn't want then just ignore them. If there are things that the old library does that aren't immediately obvious how to do in the new OLED then you have to get creative.  Any #defines are purely symbolic for your own programming use. If you want them then have them. If you don't want them then don't have them.

Is the SPI communication method feasible? I have found a chip at present, and it seems that the driver can be transplanted directly. You can look at this chip.
https://nl.mouser.com/ProductDetail/Newhaven-Display/NHD-169-BREAKOUT?qs=wnTfsH77Xs6v7mYjAGElxw%3D%3D

Your initial code.txt file is flawed.
The pdf file has the code in multiple columns on each page, and not all the columns are filled.
This is the code (i think it is correct)

Example of Initial Code

Command(0x11);
Data(0x00);

Delay_ms(255);   // Delay 255ms or more

Command(0xC5);
Data(0x01);

Command(0xC4);
Data(0x2F);

Command(0xC0);
Data(0x10);
Data(0x00);

Command(0x26);
Data(0x00);

Command(0x2A);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0xEF);

Command(0x2B);
Data(0x00);
Data(0x00);
Data(0x01);
Data(0x3F);

Command(0x36);
Data(0x08);

Command(0xC0);
Data(0x50);
Data(0x00);

Command(0x3A);
Data(0x65);    //Pixel Format 16bit data
//Data(0x67);  //Pixel Format 24bit data

Command(0xBB);
Data(0x4D);
Data(0x97);
Data(0x1C);

Command(0xC1);
Data(0x01);

Command(0xC6);
Data(0x6B);
Data(0x02);
Data(0x00);
Data(0x06);
Data(0x06);
Data(0x06);

Command(0xC9);
Data(0xF0);

Command(0xE0);
Data(0xC0);
Data(0x00);

Command(0xE2);
Data(0x00);

Command(0xE8);
Data(0x23);
Data(0x00);
Data(0x00);

Command(0xEB);
Data(0xC0);

Command(0xD9);
Data(0x40);
Data(0x00);

Command(0xD1);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xDF);
Data(0x35);
Data(0xAD);
Data(0x1C);
Data(0xE7);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x14);
Data(0xA5);
Data(0x18);
Data(0xC6);
Data(0x10);
Data(0x84);
Data(0x1C);
Data(0xE7);
Data(0x14);
Data(0xA5);
Data(0x10);
Data(0x84);
Data(0x1C);
Data(0xE7);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x10);
Data(0x84);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x10);
Data(0x84);
Data(0x14);
Data(0xA5);
Data(0x08);
Data(0x42);
Data(0x08);
Data(0x42);
Data(0x14);
Data(0xA5);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x14);
Data(0xA5);
Data(0x08);
Data(0x42);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);
Data(0x08);
Data(0x42);
Data(0x14);
Data(0xA5);
Data(0x14);
Data(0xA5);
Data(0x08);
Data(0x42);
Data(0x0C);
Data(0x63);

Command(0xD0);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x9F);
Data(0x19);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x0D);
Data(0x94);
Data(0x28);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x16);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x16);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x16);
Data(0x8F);
Data(0x35);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x20);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x20);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x20);
Data(0x8C);
Data(0x42);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x2A);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x2A);
Data(0xFF);
Data(0x00);
Data(0x04);
Data(0x2A);
Data(0x8A);
Data(0x50);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x33);
Data(0x88);
Data(0x64);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x46);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x46);
Data(0xFF);
Data(0x00);
Data(0x08);
Data(0x46);
Data(0x7C);
Data(0x67);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x44);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x44);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x44);
Data(0x6E);
Data(0x74);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x54);
Data(0x64);
Data(0x90);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5E);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5E);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5E);
Data(0x5A);
Data(0x92);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5F);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5F);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x5F);
Data(0x52);
Data(0x94);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x61);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x61);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x61);
Data(0x4C);
Data(0x95);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0x47);
Data(0x97);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x62);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x62);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x62);
Data(0x42);
Data(0x99);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x64);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x64);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x64);
Data(0x3E);
Data(0x9A);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x66);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x66);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x66);
Data(0x3A);
Data(0x9C);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x65);
Data(0x37);
Data(0x9D);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x68);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x68);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x68);
Data(0x34);
Data(0x9F);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6A);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6A);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6A);
Data(0x32);
Data(0xA0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6B);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6B);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x6B);
Data(0x2F);
Data(0xA2);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x70);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x70);
Data(0xFF);
Data(0x00);
Data(0x10);
Data(0x70);
Data(0x2D);
Data(0xA4);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x72);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x72);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x72);
Data(0x2B);
Data(0xA6);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x75);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x75);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x75);
Data(0x29);
Data(0xA7);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x76);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x76);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x76);
Data(0x28);
Data(0xA8);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x79);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x79);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x79);
Data(0x26);
Data(0xAA);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0x25);
Data(0xAC);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x81);
Data(0x23);
Data(0xAE);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x87);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x87);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x87);
Data(0x22);
Data(0xAF);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0x21);
Data(0xB1);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8D);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8D);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8D);
Data(0x20);
Data(0xB2);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x89);
Data(0x1F);
Data(0xB4);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8E);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8E);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x8E);
Data(0x1E);
Data(0xB6);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x93);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x93);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x93);
Data(0x1D);
Data(0xB8);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x98);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x98);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x98);
Data(0x1C);
Data(0xBA);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0x1B);
Data(0xBC);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x95);
Data(0x1B);
Data(0xBC);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x91);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x91);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x91);
Data(0x1A);
Data(0xBE);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x9A);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x9A);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0x9A);
Data(0x19);
Data(0xC0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA8);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA8);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA8);
Data(0x19);
Data(0xC0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA0);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA0);
Data(0xFF);
Data(0x00);
Data(0x0C);
Data(0xA0);
Data(0x17);
Data(0xC6);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x2C);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x2C);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x2C);
Data(0x16);
Data(0xC9);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x45);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x45);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x45);
Data(0x14);
Data(0xD0);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x7F);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x7F);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0x7F);
Data(0x11);
Data(0xDE);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0xF0);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0xF0);
Data(0xFF);
Data(0x00);
Data(0x02);
Data(0xF0);
Data(0x0F);
Data(0xEB);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0x00);
Data(0x03);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x03);
Data(0x54);
Data(0xFF);
Data(0x00);
Data(0x03);
Data(0x54);

Command(0xDD);
Data(0x0B);
Data(0x0B);
Data(0x0B);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xDE);
Data(0x1C);

Command(0xE4);
Data(0x7F);
Data(0x7F);
Data(0x7F);
Data(0xEF);
Data(0xEF);
Data(0xEF);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0xFF);
Data(0xFF);
Data(0xFF);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xED);
Data(0x0F);

Command(0xC7);
Data(0x00);

Command(0xC8);
Data(0xA4);

Command(0xD2);
Data(0xA7);

Command(0xE2);
Data(0x09);

Delay_ms(255);
Delay_ms(255);
Delay_ms(255);

Command(0xF0);
Data(0x7E);
Data(0x54);
Data(0x45);
Data(0x53);
Data(0x54);
Data(0x21);

Command(0x51);
Data(0x16);

Command(0x50);
Data(0x00);

Command(0xCE);
Data(0x80);
Data(0x00);
Data(0xE0);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xCD);
Data(0x06);
Data(0xC7);

Delay_ms(16);   //Delay 16ms or more

Command(0xCE);
Data(0x80);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);
Data(0x00);

Command(0xCD);
Data(0x06);
Data(0xC7);

Command(0xCD);
Data(0x00);
Data(0x00);

Command(0x35);
Data(0x00);

Command(0xE0);
Data(0xD0);
Data(0x00);

Command(0x29);
Data(0x00);

So is this an updates and corrected piece of example code?

look at the txt file you included and compare it to the code in the pdf file ... the txt file was created by copy and paste from the pdf file ... the problem is that the pdf file has the code arranged in four columns ... copy and paste of the four columns results in garbage data .... the code above matches the correct sequence in the pdf file

Ah okay I understand. Thankyou for correcting that.


text:
Understanding the variation of Arduino's current consumption with respect to the voltage supply
Even though this is already a well-debated topic, I couldn't find an extensive discussion about what really is drawing so much power in Arduino's board.
Here is the preamble: I have an Arduino Mega 2560, I measured its power consumption in a steady state with just a red LED turned on with a 560Ohm series resistor.
The power supply (Vcc) was given to Arduino from the Vin pin and the measurement were as follows (below the schematic set-up):

30mA @Vcc = 5.2V;
65mA @Vcc = 8.3V.

What I would like to understand is:

From a hardware perspective, I don't see what is drawing all of this current in Arduino's board;
Why the current drawn from the power supply changes so much with the power supply's value (i.e. what part of the board changes its consumption with the power supply value);
It also seems that turning on an LED through a digital output of Arduino draws a higher current with a higher power supply (Vcc). Why is that?

Note that, by looking at the datasheet of the ATmega2560, the uC mounted on my Arduino, I saw that the current Icc drawn from the power supply is max 14mA (I suppose when no output is sourcing current, I couldn't find the test conditions, unfortunately). I thought the microcontroller was the major cause of power consumption, but it doesn't seem to be so!
Another thing I considered is the onboard LDO, but the input voltage should change the power dissipated by the LDO, not the current drawn from its output.
It's even more strange if you think that regardless of the Vin, all the electronics after the LDO is working at the same voltage.
EDIT1
After Majenko pointed out a big flaw in my set-up with his answer, I re-measured with Vcc = 12.1V and I measured approximately the same Icc observed at Vcc = 8.1V.
I completely agree with Majenko's answer and I would just like to go a bit more in details about what happens while the board is working under voltage.
Here is my analysis:
The minimum operating condition when supplied from Vin is 7V, and that's the "knee" point in Majenko's answer.
However, the maximum quiescent current of the LDO is 10mA, and the Icc of the ATmega2560 is 15mA, so even if we suppose they don't draw any current at Vcc=5.2V, and then draw 25mA together at the minimum operating voltage at 7V, this doesn't add up to the actual increase of 40 or 50 mA that Majenko calculated I observed from 5.2 to 8.3 (which should be the same as from 5.2 to 7V).
And we're not even taking into account that at 5.2V the micro is perfectly able to turn on and keep on the LED, so it's somewhat working and already drawing some current.
Other things that we can take into account, but don't change the facts, are:

a second LDO (LP2985) to generate the 3V3, whose quiescent current should be around 100uA since the circuit is not drawing any current from the 3V3.
a second microcontroller related to the USB programming, whose Icc may be up to 20mA but this one is OFF when supplying from Vin.  -->  Edgar Bonet correctly pointed out that this is not true!
Some voltage dividers and comparators.

So what is the cause of this increase in current consumption from 5 to 7V?

There is one major flaw in your measurements: 5.2V is below the minimum input voltage for the board, so the regulator won't be regulating to 5V. Create more data points over the voltage range and draw yourself a graph. I'll bet it won't be a straight line.

It's not clear from your question how you are measuring the board's current. If you are measuring current draw at the Vin pin, that is still on the input or power-supply side of the LDO, not on the regulated side. If this is the case, increasing current draw (disspiation!) with increasing supply voltage is to be expected. A diagram of how you are measuring the board's current draw would help greatly.

There is a second MCU on the board, used as an USB–serial bridge, which draws its share of current.

Re “this [second microcontroller] is OFF when supplying from Vin”: No, it's ON. See the schematic.

Ah you're right! I checked the schematic but the UVCC pin tricked me :-)

There is a basic error in your methodology which leads to incorrect conclusions.
You cannot determine what is going on from just two data points. Instead you need far more.
Here is a voltage sweep from 5V to 12V with a 0.05V resolution (overkill, but the default setting for the script I use) connected to a Mega:

As you can see the current steadily climes in a pretty linear fashion up to a certain point, then it flattens out.
Everything up to the point where it flattens is below the minimum input voltage for the board. During this time the voltage regulator isn't getting enough voltage, so can't regulate its output voltage to 5V. So the board is running under voltage at this point.  Once it reaches that "knee" point the voltage regulator can regulate the voltage properly - so most of the components on the board start seeing a steady 5V and their current consumption flattens out.
There are a handful of components on the high-voltage side of the regulator - most notably the voltage divider for detecting the input voltage and feeding it to the comparator that drives the P-channel FET to turn the USB power on and off - which will consume slightly more current when the voltage increases, but that is only very small amounts.
So, in short, by comparing a voltage that is below the minimum input voltage for the board with one that is above the minimum input voltage, you are comparing an invalid result with a valid result and inferring that everything in between is valid.

You're right about the big flaw in my set-up! I updated the question with new results at Vcc=12.1V and also extended the question thanks to your considerations. I hope you can share your thoughts about my analysis because something is still not in the right place. Also, how did you calculate the current consumption? I didn't know about any "mathematical" model.

@Elia I didn't calculate anything. It's what my bench power supply reported as being consumed. It's all scripted through a USB connection to control the power supply.

@Elia As for the under voltage scenario, just think about Ohm's Law and what it means.

I thought it was a simulation, it's even better then! :-) I thought about it in terms of Ohm's law, also because the increase is quite linear, but if you consider 40mA at 5V and roughly 90mA at 7V, you get a differential resistance of roughly 40Ohm in that range, and I don't see anything that may show this resistance. Also, there are many semiconductors components that don't strictly follow ohm's law.

@Ella Think about the simplest thing: the power LED. You have an LED with a forward voltage that is fixed. You have a resistor in series with it with a resistance that is fixed. You increase the supply voltage - what happens to that bit of the circuit?

On the Mega R3, the Power LED is driven by 5V, so that will stay the same.  The 5V regulator will dissipate more power as heat; Power dissipated = (Vin - 5V) x current draw.  Vin is after the reverse polarity protection diode D1, which will also be dissipating some power as current flows thru it.

@CrossRoads Not when the input voltage is too low to regulate. That is the whole point here.

Yes, below around 6.7V the regulator is not doing much for you (did the chart above use Vin, or the barrel jack to power the board?)  I prefer in my designs to just power from a 5V wallwart and leave the 5V regulator off altogether.  Need a power supply no matter what - why not use 5V to start?

@CrossRoads the barrell jack, so yes, includes the diode drop.  Personally I use a TPS82130SILT when possible in my projects. Zero dropout and high efficiency.

source: Stack Exchange

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

sort: votes


text:
Multiple Buttons to control the same led for different on off times
I am just learning the Arduino, it is a learning curve that's for sure.
Using the onboard Led I want to use two buttons to make the Led blink for different times.
I am not sure what is missing from the code, as pressing BUTTON2 gives the same time as BUTTON.
Any help would be greatly appreciated.
 const byte BUTTON = 2;
const byte BUTTON2 = 3;
const byte LED = 13;

unsigned long buttonPushedMillis;
unsigned long ledTurnedOnAt;
unsigned long turnOnDelay = 500;
unsigned long turnOffDelay = 500;
unsigned long turnOnDelay2 = 1000;
unsigned long turnOffDelay2 = 1000;
bool ledReady = false;
bool ledState = false;

void setup() {
  pinMode(BUTTON, INPUT_PULLUP);
  pinMode(BUTTON2, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);
}

void loop() {
  unsigned long currentMillis = millis();
  if (digitalRead(BUTTON) == LOW) {
    delay(50);
    buttonPushedMillis = currentMillis;
    ledReady = true;
  }
  if (ledReady) {
    if ((unsigned long)(currentMillis - buttonPushedMillis) >= turnOnDelay) {
      digitalWrite(LED, HIGH);
      ledState = true;
      ledTurnedOnAt = currentMillis;
      ledReady = false;
    }
  }
  if (ledState) {
    if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) {
      ledState = false;
      digitalWrite(LED, LOW);
    }
  }
  {
    unsigned long currentMillis = millis();
    if (digitalRead(BUTTON2) == LOW) {
      delay(50);
      buttonPushedMillis = currentMillis;
      ledReady = true;
    }
    if (ledReady) {
      if ((unsigned long)(currentMillis - buttonPushedMillis) >= turnOnDelay2) {
        digitalWrite(LED, HIGH);
        ledState = true;
        ledTurnedOnAt = currentMillis;
        ledReady = false;
      }
    }
    if (ledState) {
      if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay2) {
        ledState = false;
        digitalWrite(LED, LOW);
      }
    }
  }
}

\\

Please format your code properly (indent it all 4 characters of start and end it with three back-ticks on a line of their own).

You're making your program too complex for its own good.
Instead of changing your blink code depending on which button is pressed, just make the button change the blink code's parameters, and stick to just one blink code.
That means having just one set of blink variables which your blink code uses, and your button code then just changes what values those variables contain.

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


text:
Tapered log potentiometer to linear formula
I have a tapered log 10K potentiometer. I would like some function which returns tapered log value to linear values.
The potentiometer is a slider. When connected to the Arduino the wiper displays the values ranging from 0 to 1023.  Currently if I set the slider to the half way position it displays the value 856 (approx), when I'd expect (or want) the value it to be more like 512 (as it's half way). The quarter way mark for example shows a value in the region of 570, where I'd expect the value to be 256. I hope that this makes sense.
This is about the extent of the code so far :))
  curpos1 = analogRead(potPin);

  Serial.println(curpos1);

You can search for gamma correction which probably helps you find a suitable formula.

If it's a log, you could convert in back to linear by using the exponent. A lot of these pots have just two linear sections in them which approximates a log, (or inverse log in your case). I'd just put a ruler next to the slider; move the slider in small even increments; put the values in excel, and create a plot. You can then see if it's an actual log pot, or just aproximated. You can then, in excel, play with some formulas to get back a linear value.

Or just use a lookup table...

what are you using the pot for?


text:
how to set up an ESP8266 as a webserver
I would like to set up an esp8266, connected arduino as a webserver, specifically, one that has its own IP, and is stand alone, not connected to other networks, and offers its sensor info as the contents of its internal webpage. what is this called?
I see numerous examples for connecting the esp8266 to another network, but that is not what I want to do. I want the esp8266 to read its sensors, and write a webpage, but have other devices connect to it.

https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/WiFiAccessPoint/WiFiAccessPoint.ino

The keyword to search for is "SOFTAP".

the ESP8266 has to act as a wifi access point .... https://duckduckgo.com/?q=esp8266+wifi+access+point&ia=web


text:
Stereo audio Arduino MKR Zero
I am doing a project in which I need to have a stereo audio output in Arduino MKR Zero. The quality of the audio is not important: 8 bit, 44 kHz would be enough. Is it possible to use two combined PWM outputs to do that, maybe with the library TMRpcm (is it supported by MKR?)? Or is it a better solution to interface it with a I2S stereo DAC?
Thank you
Alessandro


text:
Can you activate the whole pixel on LCD?
I'm working on a project where I'm trying to display the level of a filled tank through ultrasonic, then displaying it on a 16x2 LCD. I'm trying to do it through the whole LCD Pixels, such that when the tank level is full, the first 5 pixels are activated (as what happens when you connect the LCD initially without having any code for it, the whole pixels are turned on, giving 16x2 white rectangles, as shown in the picture below). Is there a way to activate an entire pixel on the LCD?

You can define your own characters to display. Is that what you want?

@Majenko Nope. My issue is not to display characters. However, I want to display the white rectangles, as shown in the picture. Is there a code to activate the entire rectangle pixel?

You can define your own characters. Make a character that has all the pixels you want set.

@Majenko Oh I see. I assumed there was an easier way, since it just activates the entire rectangular pixel. Thanks for your help!

Check the datasheet for your display. It should give you the predefined characters. One might be a solid block.

that picture shows all of the pixels in the first line activated ... there are no in-between pixels

The LCD is made up from 32 characters each is 5x7 pixels in size, with a 1 pixel gap between each character.
You can never put anything in the gap between the characters, as there is just nothing there.
But what you can do is define your own characters to fit within the 5x7 pixel rectangles.
Some variants of the HD44780 have character 255 as a solid block, but not all (it depends on what language the ROM is).  If you have one that has that character you can just print it with lcd.print("\xff") or lcd.write(255).  If it doesn't it will print ÿ instead. In that case you will have to define your own character.
One benefit of defining your own characters is that you could then do partial blocks to give you a higher resolution.  Here's an example:

You can find that example and the code that goes with it here.

The LCDs like the one you picture display characters. That is all they do. You can't address the pixels in the display.
And as a point of clarification, you are talking about the 5 pixel by 7 pixel character blocks on the display as if a character is a pixel. It's not. A character block consists of 5 x 7 pixels.
Some versions may have a pre-defined solid block character, as Majenko said in their answer. You could print as many of those solid blocks as you want.
You could also define a single custom character that displays a solid block and print as many of those as you want.
As a third option (again from Majenko's excellent answer) you could define 5 different custom characters, each with a different number of columns of pixels filled in. You could then write code that displayed solid blocks for all but the last character, and then one of the 5 partly filled custom characters, and get a finer resolution of simulated bar graph.
All that said, remember, the LCD display can only display 5x7 blocks with blank space between. The LCD is built without any pixels between the characters, so there will always be blank spaces.
There are other pixel displays you could use. (I've seen OLED displays where you can control every character individually.)


text:
trying to switch input on my speakers via infrared using web browser but i have issue getting it working
ived tested the IR code with
https://github.com/wemos/D1_mini_Examples/blob/master/examples/04.Shields/IR_Controller_Shield/IRsend/IRsend.ino
and it works that way, but when i try to code it together with the web server, i get nothing, can someone explain to me what's wrong in my code? the webserver works fine, its the IR part i dont fully understand why its not working
#include <i18n.h>
#include "ESP8266WiFi.h"
#include "ESP8266WebServer.h"
#include <IRremoteESP8266.h>
#include <IRsend.h>
ESP8266WebServer server(80);

void setup() {
  Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
  WiFi.begin("net", "pass");  //Connect to the WiFi network

  while (WiFi.status() != WL_CONNECTED) {  //Wait for connection

    delay(500);
    Serial.println("Waiting to connect…");

  }

  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());  //Print the local IP

  server.on("/on", []() {   //Define the handling function for the path

    server.send(200, "text / plain", "Switching to USB input");
    #define IR_LED D3
    IRsend irsend(IR_LED);  // Set the GPIO to be used to sending the message.
    uint16_t rawData[71] = {8992, 4494,  574, 558,  572, 558,  574, 558,  574, 558,  574, 558,  572, 558,  572, 556,  572, 1660,  572, 1658,  574, 1658,  574, 1658,  574, 1660,  574, 1660,  574, 1660,  574, 1658,  602, 528,  574, 558,  574, 1658,  576, 556,  574, 556,  574, 1660,  574, 556,  574, 554,  574, 554,  574, 1658,  574, 556,  574, 1656,  576, 1658,  576, 556,  574, 1658,  576, 1656,  576, 1658,  576, 39978,  8994, 2256,  578};
    irsend.begin();

  });

  server.on("/", handleRootPath);    //Associate the handler function to the path
  server.begin();                    //Start the server
  Serial.println("Server listening");

}

void loop() {

  server.handleClient();         //Handling of incoming requests

}

void handleRootPath() {            //Handler for the rooth path

  server.send(200, "text/plain", "NinjaLights");

}

Look at your code. You set up the sender, define the data and then never use it:
server.on("/on", []() {   //Define the handling function for the path
    server.send(200, "text / plain", "Switching to USB input");
    #define IR_LED D3
    IRsend irsend(IR_LED);  // Set the GPIO to be used to sending the message.
    uint16_t rawData[71] = {8992, 4494,  574, 558,  572, 558,  574, 558,  574, 558,  574, 558,  572, 558,  572, 556,  572, 1660,  572, 1658,  574, 1658,  574, 1658,  574, 1660,  574, 1660,  574, 1660,  574, 1658,  602, 528,  574, 558,  574, 1658,  576, 556,  574, 556,  574, 1660,  574, 556,  574, 554,  574, 554,  574, 1658,  574, 556,  574, 1656,  576, 1658,  576, 556,  574, 1658,  576, 1656,  576, 1658,  576, 39978,  8994, 2256,  578};
    irsend.begin();

  });

You need to add a call to irsend.SendRaw() to actually send the data - otherwise you didn't actually do anything.
So your code would look like:
server.on("/on", []() {   //Define the handling function for the path
    server.send(200, "text / plain", "Switching to USB input");
    #define IR_LED D3
    IRsend irsend(IR_LED);  // Set the GPIO to be used to sending the message.
    uint16_t rawData[71] = {8992, 4494,  574, 558,  572, 558,  574, 558,  574, 558,  574, 558,  572, 558,  572, 556,  572, 1660,  572, 1658,  574, 1658,  574, 1658,  574, 1660,  574, 1660,  574, 1660,  574, 1658,  602, 528,  574, 558,  574, 1658,  576, 556,  574, 556,  574, 1660,  574, 556,  574, 554,  574, 554,  574, 1658,  574, 556,  574, 1656,  576, 1658,  576, 556,  574, 1658,  576, 1656,  576, 1658,  576, 39978,  8994, 2256,  578};
    irsend.begin();

    irsend.sendRaw(rawData, 71, KHZ);
  });

You'll need to replace KHZ with the frequency the remote you're trying to replicate uses, otherwise it still won't work.

thanks you, i knew i was missing something


text:
Motor cutting out when using HC-05 Bluetooth module
I'm using an L293D motor driver chip along with an HC-05 Bluetooth module. The two work as expected separately - I can send a string via a Bluetooth terminal app on my phone to the HC-05 and I see it in the serial monitor just fine, and I can use the serial monitor to change the speed/direction of the DC motor without an issue. However, if I try to use the Bluetooth console on my phone to change the speed, the motor only spins for about a second before I lose connection with the HC-05 and it stops.
I think this is happening because the Arduino is tripping some breaker by drawing too much current to power both the HC-05 chip and the DC motor. Is this the case? Should I use an external battery pack to power the DC motor and L293D chip, and then keep the HC-05 connected to the 5V out line on the Arduino?
Thanks.

Either that or the motor is causing EMI that is disrupting your communication.

How are you powering everything currently?

@chrisl Previously I was powering everything off of the 5V line on the Arduino, but I just switched to using an external battery pack of 4 AAs and that seems to work fine.

Will you post a scheme of your device plase? It is Hard to ubderstand What is going on without it...
As I have understood, you May have a leak of power there.. Try to power your motors using an external way: to connect them In parallel with your arduino board.
Yor problem also May be caused by that your power source is not String enough, and it May be not enough it's power to keep motirs and hc05 working at the same time.
Also, if you are using a board with severak uart pins on it, you May check if you haven't connected you motors to thise Uart pins I hooe my answer wil help you

Previously I was powering everything off of the 5V line on the Arduino, but I just switched to using an external battery pack of 4 AAs and that seems to work fine.

That suggests, that your power source was not strong enough. You didn't say, how you are powering the Arduino, but I guess you are doing so via USB. The USB port of a PC can only give you 500mA of current (at least without any extra configuration to get more). Also the parts on the Arduino (for example the diode between USB power and the 5V pin) can only give you a limited amount of current. Especially when the motor is starting, the needed current is rather big. That might have caused a short voltage dip, deep enough to irritate the HC-05 module.
Using an extra battery as power source for the motor eliminates that problem. Though I think you should be able to connect all parts to the same power source, as long as it is powerfull enough to power all parts (plus some overhead). In that case be sure to connect the power for the L293D and Arduino in parallel, so that the motor current does not have to flow through the Arduino (which could kill the voltage regulator or the diode).
Depending on your motor, it also might generate a huge amount of EMI (Electromagnetic Interference) either though air transmission or through the power lines, which might irritate the HC-05 enough. In that case the easiest option would be to add a second power source. Though I think the problem is with the power source as described above.


text:
Error taking address of temporary array when passing compound literal array
I have an Arduino sketch that passes an array into a method as a compound literal, but for some reason I keep getting the following error:

void setup() { }
void printConcatLine(char chunks[][20]) { }

void loop() {
  printConcatLine((char[][20]){ "{", "255", "}" });
}

I've also tried passing the number of the pointers/length of the array, and explicitly terminating it:
void setup() { }
void printConcatLine(char *chunks[]) { }

void loop() {
  printConcatLine((char*[]){ "{", "255", "}", NULL });
}

...and
void setup() { }
void printConcatLine(char chunks[][20]) { }

void loop() {
  printConcatLine((char[][20]){ "{", "255", "}", "" });
}

But they both produce the same error.
What is the correct method of passing the compound literal array as a method parameter?

You can't. You have to assign it to something then pass that variable.

Either that or rewrite your function to use variadic arguments.

Is this limitation specific to Arduino? From what I understand you can do this in C.

I am not sure, but I suspect it's a consequence of the AVR being a Modified Harvard Architecture CPU.

https://stackoverflow.com/questions/32941846/c-error-taking-address-of-temporary-array

What are you actually trying to achieve with that function anyway?

I needed a method to print any number of strings/variables together in a single line, to get past the limitation of having to send one at a time to Serial.print. I wanted to achieve the same functionality of something similar to: Serial.println( "{" + var1 " - " + var2 + "}" );

Actually Arduino uses C++.

You can't with the Arduino. I am not quite sure why, but I think it may be because it's a Modified Harvard architecture machine.
You can better achieve what you want with variadic arguments, however:
void printConcatLine(int num, ...) {
    va_list ap;
    const char *s;

    va_start(ap, num);
    for (int i = 0; i < num; i++) {
        s = va_arg(ap, const char *);
        Serial.print(s);
    }
    va_end(ap);
    Serial.println();
}

void setup() {
    Serial.begin(115200);
    printConcatLine(3, "{", "255", "}");
}

void loop() {

}

The first argument is the number of arguments that follow, and all the rest are string constants.


text:
Stopping a motor after a given time period
I have a code to turn on a LED when IR Proximity sensor having a object less than 6cm in front of it,
and the LED goes down after it is removed.
Now, I want the LED to run for 3 seconds only, even if the object is not removed, how should I modify my code?
Many thanks in advance!
int LED = 13; // pin for the LED
int Sensor = 2;// pin for the IR Sensor

void setup(){

  pinMode (LED, OUTPUT);
  pinMode (Sensor, INPUT);
}

void loop(){

  if (digitalRead(2)){

      digitalWrite(LED , LOW);
  }

  else{

    digitalWrite ( LED, HIGH);
    // if the IR sensor detects an object, the LED turns on or else it should not turn on
}

what are you doing? ... you already asked this question, and it was answered, and you accepted the answer

int LED = 13;
int Sensor = 2;

void setup(){

  pinMode (LED, OUTPUT);
  pinMode (Sensor, INPUT);
}

void loop(){

 if (digitalRead(2)){

        digitalWrite(LED , LOW);
        delay(3);
  }

 else{

    digitalWrite ( LED, HIGH);``
 }

I do not see any relation to the question, sorry.


text:
Can I check if a message has been sent successfully using Radiohead_ASK?
I'm new to Arduino programming and I'm trying to get a simple 433 MHz transmitter and receiver module working on an Arduino Uno board. Unsurprisingly, it's not working as expected and I'm trying to debug the problem.
I'm using RadioHead and read in the documentation that the send() and waitPacketSent() methods return a boolean to indicate success. However, I disconnected the data wire and the send() method still returns true. As the module is no longer connected to the arduino I would have expected it to return false.
I understand that the messages are sent as unreliable datagrams, but I'm just trying to work out whether the transmitter has actually sent something. Is there some way I can do this?
The code I'm using is relatively short, so I've included it in full below, for what it's worth
#include <RH_ASK.h>
#include <RadioHead.h>

#ifdef RH_HAVE_HARDWARE_SPI
#include <SPI.h> // Not actually used but needed to compile
#endif

RH_ASK driver;

bool sent;

void setup()
{
#ifdef RH_HAVE_SERIAL
    Serial.begin(9600);    // Debugging only
#endif
    if (!driver.init())
#ifdef RH_HAVE_SERIAL
      Serial.println("init failed");
#else
  ;
#endif
  sent = false;
}

void loop()
{
    uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
    uint8_t buflen = sizeof(buf);

    const char *msg = "hello";
    bool sendSuccess;
    bool waitSuccess;

    if (!sent) {
      Serial.println("sending");
      sendSuccess = driver.send((uint8_t *)msg, strlen(msg));
      if (sendSuccess) {
        Serial.println("Send completed successfully");
      } else {
        Serial.println("Send Error");
      }
      Serial.println("Waiting");

      waitSuccess = driver.waitPacketSent();
      if (waitSuccess) {
        Serial.println("Wait Sent Success");
      } else {
        Serial.println("Wait Sent Error");
      }
      Serial.println("Done Sending");
      sent = true;
      delay(1000);
    }

    if (driver.recv(buf, &buflen)) // Non-blocking
    {
      Serial.println("driver.recv");

      // Message with a good checksum received, dump it.
      driver.printBuffer("Got:", buf, buflen);
    }
}

The output on the serial monitor is as follows

22:22:30.647 -> sending
22:22:30.647 -> Send completed successfully
22:22:30.684 -> Waiting
22:22:30.753 -> Wait Sent Success
22:22:30.753 -> Done Sending

Thanks in advance!

There is no concept of "did the packet arrive", only "did it get sent" - and by "sent" I mean the data squirted out of the data pin for the attached module to send.
These 433MHz modules are dumb. Very dumb. You toggle the transmitter's pin high and low and the receiver sees that toggling, if it is in range, and toggles its output pin to mirror the signal.
The only way you can know if the packet arrived is if the receiver also has a transmitter and the transmitter also has a receiver. When a message arrives at the receiving node it sends a message back to the transmitting node to say "I got it". That takes a lot of work to get right, though. Especially since the original message may have arrived fine, but the acknowledgement didn't, and all sorts of horrible things can happen if you don't handle packet sequencing right.
Better is to pick a better module that does all these things for you, such as the nRF24L01+ with Auto-ACK turned on.

Thanks for the quick reply Majenko! I know I don't have any way of checking if the packets arrived. I'm just debugging at the moment and trying to check if it was sent. I would have thought that because the data pin isn't connecting the Arduino to the transmitter module then send() should fail? Have I misunderstood this?

You have misunderstood that. The Arduino neither knows not cares what is connected. Is there is nothing there the data pin still gets toggled. If a tree falls over in the forest and there's no one there to hear it the tree still fell over and the air still vibrated.

Ah, Ok. Thanks for clearing that up. Thanks also for the recommendation. Will check out the module you mentioned above.

Get a 2nd Arduino and let it receive the data pin signal. Then you'll know the signal is being created.  You cannot send and receive with one Arduino, you need a 2nd.  I think there will be some data wrapped around the message that is sent; some sync bytes, some padding to ensure there are enough hi/low and low/hi transitions to ensure all data is recognizable on the receive end. The Radiohead web pages discuss it in more detail. It's basically Software Serial, but with radio modules stuck in the middle.

@CrossRoads Thanks. This was the problem. I had been trying to send and receive from the same board. When I got a second arduino to act as the receiver it worked as expected.


text:
Can I get around extremely long time to setup WIFI connection WPA2 Personal?
I'm using the Arduino Wifi Nina Library to connect an Arduino Uno Wifi Rev2 to wifi and then using the Arduino HTTP Client library to make HTTP post calls to the internet.
To connect the Arduino to my home Wifi Network (WPA2 Personal), I use the WiFi.begin() method. This method takes an excruciatingly long 4 seconds to connect to the Wifi. This seems to be a known issue. Since this methods is synchronous/blocking, my sketch is completely unresponsive during this time to any user input such as button-presses etc. I'm trying to create a proof-of-concept for a commercial-grade product. So having it go unresponsive to user-input for several seconds is unacceptable.
Is there any workaround to this? Is there a asynchronous library to achieve the same goal? Is there some other workaround? How do other people deal with this situation?

wow! four seconds is an excruciatingly long time? ... i think that maybe the problem that needs correcting is not with the arduino ... spend the four seconds looking out the window or at your better half

use WiFi.setTimeout()

I don't think WiFi.begin takes four seconds, does it? Sounds to me like you have a loop that is waiting around for WiFi.status==WL_CONNECTED which is taking four seconds. I just tested on my NodeMCU and WiFi.begin() typically completes in just 5 milliseconds.

@S.Imp, yes 5 ms because it is already connected as 'persistent connection'

@Juraj My WiFiInit function calls WiFi.persistent(false) as its first operation. WiFi.begin only takes about 5ms pretty much every single time I call it (on a NodeMCU) and returns WF_DISCONNECTED if the wifi is not connected. You should poll periodically to see if it has connected before attempting to use it. In any case, it will take about 4 seconds before it finally connects, but at least begin doesn't block the whole time.

@S.Imp, but that is on the esp8266 or esp32, not on the Uno WiFi Rev.2 with WiFiNINA library.

4 even 5 seconds is normal for connecting to WiFi. How long takes your phone or other devices to connect?
You can connect a little faster with static IP address.
EDIT: With WiFiNINA library for Uno WiFi Rev.2, you can change the connection timeout with WiFi.setTimeout(). The default is 5 seconds. WiFi.begin() can end with WL_CONNECT_FAILED but if you later check the status of the connection it will eventually be connected.

With esp8266 or esp32 you can make the connection persistent and it is build up immediately after boot and asynchronously. WiFiNINA library doesn't make this possible yet. Some future version will offer WiFi provisioning.

So if I switch from WifiNINA to esp8266, then I can connect to the wifi asynchronously?

@SaqibAli, yes. but usually setup() runs much faster then the connection is build-up so even then the sketch usually waits some seconds if having network at the end of setup() is needed.  you can connect a little faster with static IP address

For a proof-of-concept, use two Arduinos, one for WiFi and one for everything else.
The everything-else Arduino can keep your system responsive (minus the WiFi, of course, during connection time) and poll the WiFi Arduino periodically (without blocking) to find out when WiFi becomes available.

I think better solution is to use ESP8266 WiFi module and Connect if needed another Arduino through GPIO pins of ESP8266.
This video will be helpful,
https://www.youtube.com/watch?v=dWM4p_KaTHY

better then what?

Without using In Built Wifi Module.

so you say it is better to use an external esp8266 module then the on-board esp32? what is the difference?

Actually ESP 32 is a improvement o ESP 8266, but  I was able to use ESP 8266 with Arduino easily than ESP32 and ESP 8266 ha lot of  community threads.


text:
Formatting variables from a variadic function
I have a function that concatenates a print line, however I am having trouble getting some of the strings to format correctly.
Using Serial.print formats the output from keypad.getKey() correctly, however when I try to output the same format using printConcatLine() it does not give me the same output. I've tried casting it as both a char and an int...

void printConcatLine(const char* mask, ...) {
    va_list params;
    va_start(params, mask);

    while(*mask != '\0') {
      if (*mask == 'i') {
          Serial.print(va_arg(params, int));
      } else if(*mask == 'c') {
          Serial.print(va_arg(params, const char *));
      } else if (*mask == 'f' || *mask == 'd') {
          Serial.print(va_arg(params, double));
      }
      ++mask;
    }

    va_end(params);
    Serial.println();
}

char btnPressed = keypad.getKey();
  if (btnPressed) {
    Serial.print("BtnPressed: ");
    Serial.println(btnPressed);
    // Output: "BtnPressed: 1"

    printConcatLine("ci", "BtnPressed: ", btnPressed);
    // Output: "BtnPressed: 49"

    printConcatLine("cc", "BtnPressed: ", btnPressed);
    // Output: "BtnPressed: "
  }

I also tried changing:

va_arg(params, const char *)

to

va_arg(params, char)

which also did nothing.
How can I modify the call to va_arg() to properly output the same output as Serial.print()?

Incidentally, on chipKIT we provide the handy Serial.printf("...", ..., ..., ...) function which is ideal for this. The formatting is handled by this code, which itself was lifted directly from RetroBSD.

Since you’re using serial to print the string, why the need to concatenate it?  Just print it out in chunks.

Edgar beat me to it by a few seconds, but my answer is pretty much the same as his, so read that first.
I will however add a few extra notes and pointers:

It's better to assign the va_args to an actual variable. That makes it both easier to read and understand what's going on, and more certain for the overloading of the print function to know what is supposed to happen (at least from the reader's perspective) that mere casting.
Bytes and chars are promoted to integer when being passed to a variadic function, so you have to treat them as such
float and double happen to be the same on the AVR based Arduinos, so your code will be OK there, but the same can't be said for other chips. If you want your code to be portable then you should split float and double into separate handlers since they use different sizes.
It can be good to "pass through" unknown characters in the format string so that you can add extra formatting in there. See my example below.

Here's my variant of the same code. Note the colon and space in the format that is used to add more formatting to the output (this could be enhanced by adding a % before any format characters as printf does). I also like to use a separate pointer to iterate over the format string instead so that the original start pointer is still available if I should ever want it.
Also note the difference between c and i: use c to print a letter from a char, and i to print the number in a char instead.
void printConcatLine(const char *mask, ...) {
    va_list params;
    va_start(params, mask);

    char *ptr = (char *)mask;
    while (*ptr != '\0') {
        if (*ptr == 'c') {
            int c = va_arg(params, int);
            Serial.write(c);
        } else if (*ptr == 'i') {
            int i = va_arg(params, int);
            Serial.print(i);
        } else if (*ptr == 's') {
            const char *s = va_arg(params, const char *);
            Serial.print(s);
        } else if (*ptr == 'f' || *ptr == 'd') {
            // Be careful with this. It's not portable. On AVR float
            // and double are the same, but that's not the case on other
            // microcontrollers. It would be better to split them.
            double d = va_arg(params, double);
            Serial.print(d);
        } else {
            Serial.write(*ptr);
        }
        ptr++;
    }

    va_end(params);
    Serial.println();
}

void setup() {
    Serial.begin(115200);
    char btnPressed = 1;
    float flt = 3.141592653;

    if (btnPressed) {
        printConcatLine("c: sisd", 'Q', "BtnPressed: ", btnPressed, " done ", flt);
    }
}

void loop() {
}

how much flash space does this save compared to printf? in my test none.

@Juraj A lot. Take a look at the link in my comment above for a "light weight" printf formatter and you'll see how much is involved in it.

sorry. no. printf produces a little smaller code. I use my StreamLib for printf wrapper for Serial https://github.com/jandrassy/StreamLib/blob/3b2393284315de939105a0c11df50be1471f6cfe/src/FormattedPrint.cpp#L28

@Juraj Maybe on the Arduino, but then the Arduno printf lacks float support, which is included in the code here. If you take out the float support you will most likely find this code considerably smaller. Float support is massive.

I compiled both versions for the Uno with float support and, to my surprise, Juraj's is smaller (text: 4814, data: 68, bss: 166) than yours (text: 6226, data: 62, bss: 166).

@EdgarBonet That is a surprise it has to be said.

the printf float support with -Wl,-u,vfprintf -lprintf_flt is somehow unconditional. it makes even Blink large

With the format "ci", the argument is interpreted as an integer, and
the output is correct: 49 is the ASCII code of '1'.
With the format "cc", the argument is interpreted as a string (pointer to an
array of chars), which is incorrect.
One (bad) solution is to use the "cc" format and pass &btnPressed as
an argument. The problem with this approach is that the byte in memory
right after btnPressed may not be a zero, and the format expects a
NUL-terminated string.
A better approach would be to have one format for a char and a
different one for a string. I suggest "c" and "s" respectively. But
then you should be aware that there are special promotion rules
associated with variadic functions. When playing with your code, the
compiler reminded me of this one:

warning: ‘char’ is promoted to ‘int’ when passed
  through ‘...’

So the function should expect an int, and cast it to char in order
to call the correct overload of Serial.print():
void printConcatLine(const char* mask, ...) {
    va_list params;
    va_start(params, mask);

    while(*mask != '\0') {
      if (*mask == 'i') {
          Serial.print(va_arg(params, int));
      } else if(*mask == 's') {
          Serial.print(va_arg(params, const char *));
      } else if(*mask == 'c') {
          Serial.print((char) va_arg(params, int));
      } else if (*mask == 'f' || *mask == 'd') {
          Serial.print(va_arg(params, double));
      }
      ++mask;
    }

    va_end(params);
    Serial.println();
}

Used like this:
printConcatLine("sc", "BtnPressed: ", btnPressed);
// Output: "BtnPressed: 1"

I recommend to use printf if you don't need float support in printf. This code produces a little smaller compiled code then the one in Majenko's answer and has the full power of the printf except of float.
#include <StreamLib.h>

void setup() {
    Serial.begin(115200);
    char btnPressed = 1;
    float flt = 3.141592653;

    byte b;
    BufferedPrint bp(Serial, &b, 1);

    if (btnPressed) {
        bp.printf("%c: %s %i %s", 'Q', "BtnPressed: ", btnPressed, " done ");
        bp.println(flt, 4);
    }
}

void loop() {
}

With StreamLib you can of course print float with normal single print function for floats, the same as for Serial or network Client, with second parameter for the number of decimal places.
If you want to create a formatted C-string you can use the CStringBuilder of the StreamLib. It too builds the string with print functions and has 'printf' too.

Re “smaller program”: smaller compiled code?

@EdgarBonet, yes, smaller compiled code


text:
ESP32 runtime error in 2d array
I am trying to serial print the value of b[0][0].
Has to be zero but it dose not work!
Here is the code
void setup() {
  Serial.begin(115200);
  byte b[321][241];
  Serial.println(b[0][0]);
}

void loop() {

}

If the array is small like b[2][2] it dose work
In theory esp32 has ram of  520 KiB SRAM so can this be a problem?
Here is the error code
rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8

The code complies fine but the error gets when esp32 is running
esp32 version for arduino is 1.0.4

what about b[2][241] or b[321][2] ?

Stack size is usually much smaller than RAM, especially if it's running under RTOS, so I'd expect problems with it.

@jsotola for b[321][2] I get the value 165 as output shouldn't it be zero also for b[2][241] is 165

The ESP32 uses FreeRTOS to run everything, and that includes the Arduino API. Your code is running in a thread of its own ("loopTask"), and that task by default has 8192 bytes of stack allocated to it.
xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE);

You cannot create local variables and other stack data that totals more than 8192 bytes.
Instead you will either have to have the variable as a global variable (or static local) so it gets allocated in the global data segment, or use new or malloc to create it on the heap (and don't forget the corresponding delete or free call when you're done with it).

creating the variable as global seems to solve the problem.

This may be due to serial buffer size.
ESP32 may wrire new data before finshing previous transfer. Add a delay after print line and see.

nop that did not work


text:
Pulling the enable pin on Adafruit PowerBoost to low (It's connected to VBatt!)
I am working on an Tonuino (tonuino.voss.earth), and I am using a PowerBoost-module from Adafruit (https://www.adafruit.com/product/1944) for it. The powerboost-module needs the enable pin driven to LOW(GND) to turn the output 5V off. Currently I have a rocker switch which allows me to permananently connect EN to GND.
I would like to implement a auto-off functionality for this combination, i.e. the arduino can drive the enable pin LOW and in this manner kill its own power. In addition to the auto-off, I want the user to be able to turn on the device via a button press. I come from a software background and my last connection to electronics is from a time long, long ago, which is why I am struggeling.
This shows my initial thoughts:

The user presses the button to start the Tonuino. The switch disconnects EN from GND, EN goes to UBATT(HIGH) and 5V to the arduino is enabled. By enabling the arduino, a GPIO is set to high and thus EN is maintained high
To turn off, the arduino sets the GPIO to LOW, thus setting EN to LOW, 5V are disabled and so forth...

My problem: 5V from the Arduino GPIO will always be at 5V and thus higher than the reference voltage of EN (UBATT 3V - 3.7V). I really am afraid that this will damage my lipo. For me this means, I ideally should switch UBATT for EN (safely) and am failing to come up with a solution.
Any pointers are greatly welcome

The datasheet states that the EN pin can be up to 7V. But you could also, instead of setting the Arduino pin to OUTPUT HIGH, set the Arduino pin to INPUT. The pull-up (R13) on the PowerBoost will then provide Vbat to the EN pin. So it would never see 5V.

PS note that as soon and the Boost converter turn off, the power to the Arduino goes off, and the pin will no longer be LOW, turning the boost converter back on. Majenko's solution already fixes that.

Your biggest problem is that the module defaults to on. There is a 340kΩ resistor pulling the EN pin up to VBAT all the time, so to turn it off you have to actively override that pullup.
Ideally you would modify the module by removing that resistor (R13) and adding your own resistor between the ENABLE and GND pins. You can the override that with both a button and a P-channel FET in parallel to turn the module on.
For example:

simulate this circuit – Schematic created using CircuitLab
Now normally R1 pulls ENABLE to ground turning the module off.  You press SW1 and it pulls ENABLE up to VBAT and turns it on.  5V then gets supplied to the Arduino, at which point you need to set the GPIO to output and pull it HIGH.
This causes the gate of M2 to be pulled above its threshold voltage (make sure it has a threshold voltage between 0V and 3V) and it starts to conduct pulling the gate of M1 below its threshold voltage (must be between 0V and -2V) bypassing switch SW1 keeping the system enabled.
You can now let go of SW1 and it will all stay powered on until you either set the GPIO LOW or set it to an INPUT.
Note that resetting the Arduino (for programming, for example) would cause the boost module to shut down and require re-powering with SW1 (or through the GPIO if you have the Arduino powered through USB for programming of course).
However if you don't want to or can't modify the module then things get a little nastier.
To make it default to OFF R1 in the above schematic will have to be low enough value that the voltage presented at the ENABLE pin is below 20% of the battery voltage.  R1 and the existing 340kΩ pullup resistor form a voltage divider, so you need to calculate the size of resistor that will allow it to be below 20% VBAT.
Since a voltage divider just gives you a proportion of the input voltage whose ratio is the ratio of the "top" resistance in the divider to the total resistance we don't care what the voltage is, only the ratio.  And we don't really care about the exact value, only that the result is below 20%.  So we can pick a good common value.
However we don't want a value that is too low, because the voltage divider will be draining power from the battery all the time, so the higher the resistances the less the power drain will be.
For example if we pick the common value 47kΩ we see that:
    R2           47000
 ------- = --------------- = 0.11 (11%)
 R1 + R2    340000 + 47000

Which is below the 0.2 (20%) that we want, which is good.  Calculating the current at a typical battery voltage of 3.7V we get
     V          3.7
I = --- = -------------- = 0.000010 (10µA)
     R    340000 + 47000

10µA is not much, on the scale of things, but it's good to know about it when you're working from a battery since it will form part of your power budget calculations.

This is a fantastic answer! Thank you for enlightening me and the time to answer my question. I will see what  parts i can get quickly to realize this

Hi Majenko, so after a test build on the breadboard, I have to rescind my acceptance of the answer. Here is why: The arduino does turn the powerboost module off - BUT - the gate voltage remains at 2,25V. So a trickle current is running somwhere...

Which variant of the circuit are you using? Did you remove R13 or are you trying to work around it?

I removed R13 from the circuit

There may be some back flow through the Arduino gpio. Isolating it with an n channel MOSFET would cure that. I'll update the schematic shortly.

@JoeD Ok, I have modified the schematic to include a N-channel MOSFET used to isolate the GPIO. It has the effect of reversing the GPIO logic, so now HIGH is on and LOW or INPUT is off.


text:
How do you make a Class variable array bigger?
I am making an infrared macro-keyboard, I want to store Unicode for the Keyboard class in an array inside a class I made called Keybindand to allow the user to program as many outputs as they want, I want the storage to be mutable.  I currently use the String class and decode within the program but it's cpu intensive and not very practical.
I want to use an array or list, but I haven't found any way to expand the size of an array inside a class.  Casting a temporary array didn't work:
  int intArray[] = {0,1,2,3,4,5};
  int* temp[7];

  for(int x = 0; x<sizeof(intArray)/sizeof(intArray[0]); x++){
    temp[x] = intArray[x];
  }
  temp[6] = 6;
  intArray = temp;

IDE spits out "incompatible types in assignment of 'int* [7]' to 'int [6]'"

The error is because ìnt* temp[7] gives you an array of 7 pointers to ints, not an array of 7 ints. Remove the *. Though I don't see, what this has to do with making the array bigger. That could be done via dynamic memory allocation (just like the String class does in the background), though that is not a good idea on Arduinos, especially on the ones with low memory, like the ones based on the Atmega328p (Uno, Nano, ...)

Please explain clearer, what you are trying to do and how.

I want to [...] allow the user to program as many outputs as they want

This may be problematic. The microcontroller has a limited amount of
RAM: it will not be able to store arbitrarily long macros. You should
consider a way of telling the user “sorry, no more memory”. Or you can
be optimistic and assume the user will never try to record macros long
enough to exhaust the memory... and let the firmware crash if this
assumption turns out to be invalid.

I currently use the String class and decode within the program but
  it's cpu intensive and not very practical.

CPU intensive? You mean the allocation? Reading the contents of a String
object is not CPU intensive. And what do you find impractical in the
String class? At it's core, it's just a dynamically sized container for
character data, which seems to be exactly what you are looking for.

I haven't found any way to expand the size of an array inside a class.

A class is a data structure of fixed size. There is no way you can
expand its contents. If you need something of variable size, you will
have to use dynamic allocation. You will then only store a pointer to
the allocated memory in your class. This is exactly what String does.
The only other option is to store an array of fixed size within the
class, and make that size large enough so that you never need more.


text:
4 RFID with Arduino Uno / add or remove card with master card /
i am new in coding for arduino. I need some help with the project i'm working on. my project is a object tracking by using the rfid rc522 for inventory system. so i need to have multi reader in this project. i would like to have 4 reder that will work at the same time.
this is how i want my project to work:
1. there is going to be 3 or 4 reader rc522, 1 i2s lec and leds.
2. one rfid tag will be use as the master card. the master card have the ability to add or remove card.
3. when 1 tag is tapped on 1 reader, the card quantity at the reader that it tapped will increase. example when we tap the tag at reader1, reader1 will add 1 card into its memory.
https://github.com/TasmanianDevilYouTube/Arduino/blob/master/RFID_master_slave_cards/RFID_master_slave_cards.ino

And what exactly is your problem with that? You didn't ask a question

what do you need help with ... right now, your post is like I'm new to house building and I need some help with a project.  I'm building a house with 3 bedrooms and a basement suite.

i want to have this coding to work with 4 rfid reader connected to arduino uno.

my bad. so do u know how to interface 4 rfid rc522 reader with arduino uno with the code in the link?

Still it is not clear, what your problem is. You need to narrow down the problem more. You already have a big code, which uses the MFRC522 library to interface with the RFID reader. Is that working? If not: How exactly is it not working? What did you expect and what actually happens? Are the examples working, that normally come with such a library? Or is the problem, that you don't know how to extent the code?

my problem is i dont know how to modified this code so it will work on 4 rfid reader with exactly the same as the code is now. the code here is working fine with only 1 reader. i wanted to extend it to 4 reader. so how should i do the modification on the code?

are you able to interface 4 rfid readers with Arduino UNO? .... start with simple code that reads a card on any of the four readers .... if it is not possible to use 4 rfid readers with the UNO, then it is pointless to waste time trying to modify your code

yess im able to interface 4 rfid with arduino uno.

that why I m now trying to do it


text:
Trying to switch a 5v fan with a LiPo and can't figure our what's wrong at full duty cycle
I have a simple project where I want to turn a 5v fan on/off and both the MCU  and fan will powered by a LiPo battery.
I'm powering the ESP and fan directly from the battery in the attached circuit. For now I've decided not to boost the power to 5v for the fan because the fan runs fine at lower voltage. Also using a BJT transistor as a low side switch.
This all seems to work fine except at full duty cycle the voltage to the fan seems to completely collapse. At just below full (like if a do analogWrite(pin 1000) it's humming along fine but when I go to 1023 the voltage drops from around 4 to closer to 2 and the fan stops. Even at lower duty cycles like 50% the fan operates nice and slow.
I put a multimeter on the leads to the fan and observe the voltage drop at full duty.
I'm very new to all this and have done a lot of reading but I haven't been able to solve this. Also this is my first fritzing drawing so I hope it makes sense.
Edit: I made some changes to the circuit and it's working as expected. I have also updated the circuit diagram below.

The 3.3V pin needs to be provided with a regulated 3.3V. When the power input of the ESP gets too low, it will show weird behavior

Oh I need to update the schematic. I’m actually feeding the power from the LiPo to Vin on the MCU. Still unregulated, to your point, but it’s not going to 3v3, it’s going to Vin. Anyway, I can try boosting the LiPo output  to 5v and use that to directly power the MCU and the fan and see if that makes things stable at full duty.

According to specs I found online, the NodeMCU wants 7-12V on Vin. Most LiPo cells put out around 4 volts, which isn't enough. The battery voltage may drop and the MCU's voltage regulator probably fails to keep putting out 3.3V when the fan's average power draw exceeds some threshold.
It might also be that the fan itself is slowing when the duty cycle approaches 100% and the battery voltage drops.
Doesn't the NodeMCU run on 3.3V, not 5V? If you feed 5V into the 3V pin and that's supposed to have 3.3V, it will likely damage or destroy the board.

Looks like you’re right about Vin. I’m still trying to find the datasheet for my exact devkit board to confirm but I can easily put a regulated 7v into Vin and see if it fixes the voltage drop off problem at full cycle. And, sorry, but I don’t understand your last paragraph ... Vin is connected to a voltage regulator so it will regulate to 3.3v for the board which should be safe. Did I misunderstand your comment?

Sorry, that was a typo. I fixed it.

Yes, I would suggest measuring the voltage, both across the motor, and at the Vin to the board, when you're running it at 100% duty cycle. I'm suspecting a voltage drop.

It turns out that the nodemcu dekvit I'm using supports 5v on Vin. And I'm no longer going directly from the Lipo to the Vin but boosting the voltage from the battery to 5v then to Vin and I also changed the transistor to a 2N-2222A and things seem to be working as expected.I don't know enough about transistors to say what fixed it but I'm guessing the one I was using wasn't the right one for my application.


text:
Arduino expected ':' before '{' token
I wanted to compile a project yesterday which always worked until now. Probably since an adjustment of the libraries (update) I have not been able to do this anymore. I ask for help.
ERRORMESSAGE:
exit status 1
expected ':' before '{' token
Line from Error
#define MSG_PRINT(...) { MSG_PRINTER.print(__VA_ARGS__); }

With all those compile errors in here, we should consider renaming from Arduino to Does-Not-Compile. - Have you even tried to google how to define function-like macros and how to use them?

what is the value of MSG_PRINT(...) after the #define directive  is evaluated?

What comes in your code just before you use MSG_PRINT?

MSG_PRINT is a macro.  It gets replaced in your code verbatim before compilation.
The error message will give you more information. Specifically it will tell you where the error is. For example:
/tmp/untitled1/untitled1.ino: In function 'void loop()':
/tmp/untitled1/untitled1.ino:1:24: error: expected ':' before '{' token
/tmp/untitled1/untitled1.ino:12:13: note: in expansion of macro 'MSG_PRINT'

Here I have defined MSG_PRINT at line 1, which is where it "says" the error is. However that's only where the macro is. The actual error is at line 12, where the error says the macro is being expanded. That's the last line in the error message.
The little bit of code I used to trigger that error is actually a switch command where I deliberately omitted the : at the end of a case statement:
    switch (v) {
        case 3 // <---- missing colon here
            MSG_PRINT("foo");
            break;
    }

If we replace MSG_PRINT as the preprocessor would we end up with:
    switch (v) {
        case 3
            { Serial.println("foo"); }
            break;
    }

(I defined MSG_PRINT to just call Serial.println...) and now we can better see the context of the error.
With the expansion now in place it is obvious that there is indeed a : missing before a {, even though that { isn't immediately visible in your code.
Learning to interpret these sometimes cryptic error messages is key to working with C and C++.