message:
How to print/display next menu item with menubackend.h?

I'm trying to make a navigational menu with sub menus to display on an OLED.  Have managed this OK, however I would like to display the next item on the same level, to encourage scrolling, but I am unable to figure this out.

I want to have it so that the current menu item is displayed, along with the next item one would reach if you scrolled downwards.  I know you can display the previous and current items easily with

      Serial.print(fromFlash(changed.from.getName()));

and

      Serial.println(fromFlash(changed.to.getName()));

respectively - but I would like to display the current and the next (below but on same level) item.  How can I do this?  I played around for most of today on this but am pretty stumped.

I've simplified the example given which is below.  Below that, I've included `menubackend.h`

Running on an ATMEGA328P chip.

    #include "MenuBackend.h"

    /*
        This is the structure of the modelled menu

        Settings
            Pin
            Debug
        Options
            Delay (D)
                100 ms
                200 ms
                300 ms
                400 ms
     */

    #define TEST_FROMFLASH
    #undef TEST_GETITEMNAMEFROMFLASH

    const char itemNameSettings[] PROGMEM = "Settings";
    const char itemNamePin[] PROGMEM      = "Pin";
    const char itemNameDebug[] PROGMEM    = "Debug";
    const char itemNameOptions[] PROGMEM  = "Options";
    const char itemNameDelay[] PROGMEM    = "Delay";
    const char itemName100ms[] PROGMEM    = "100 ms";
    const char itemName200ms[] PROGMEM    = "200 ms";
    const char itemName300ms[] PROGMEM    = "300 ms";
    const char itemName400ms[] PROGMEM    = "400 ms";
    const char itemNameshutdown[] PROGMEM = "shutdown";

    static void menuChangeEvent(MenuChangeEvent changed);
    static void menuUseEvent(MenuUseEvent used);
    //this controls the menu backend and the event generation
    MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
    //beneath is list of menu items needed to build the menu
    MenuItem settings = MenuItem(itemNameSettings);
    MenuItem pin = MenuItem(itemNamePin);
    MenuItem debug = MenuItem(itemNameDebug);
    MenuItem options = MenuItem(itemNameOptions);
    MenuItem setDelay = MenuItem(itemNameDelay,'D');
    MenuItem d100 = MenuItem(itemName100ms);
    MenuItem d200 = MenuItem(itemName200ms);
    MenuItem d300 = MenuItem(itemName300ms);
    MenuItem d400 = MenuItem(itemName400ms);
    MenuItem shutdown1 = MenuItem(itemNameshutdown);

    //this function builds the menu and connects the correct items together
    void menuSetup()
    {
        Serial.println(F("Setting up menu..."));
        //add the file menu to the menu root
        menu.getRoot().add(settings);
        //setup the settings menu item
        settings.addRight(pin);
        //we want looping both up and down
           pin.addBefore(debug);
           pin.addAfter(debug);
           debug.addAfter(pin);
        //we want a left movement to pint to settings from anywhere
           debug.addLeft(shutdown1);
           pin.addLeft(settings);
        settings.addAfter(options);
        shutdown1.addAfter(settings);
        options.addAfter(shutdown1);
          options.addRight(setDelay);
          setDelay.addLeft(options);
          setDelay.addRight(d100);
          d100.addBefore(d100); //loop to d400
          d100.addAfter(d200);
          d200.addAfter(d300);
          d300.addAfter(d400);
          d400.addAfter(d100); //loop back to d100
          //we want left to always be bak to delay
          d100.addLeft(setDelay);
          d200.addLeft(setDelay);
          d300.addLeft(setDelay);
          d400.addLeft(setDelay);

    }

    #ifdef TEST_FROMFLASH

    inline const __FlashStringHelper * fromFlash(const char * pStr)
    {
        return reinterpret_cast<const __FlashStringHelper *>(pStr);
    }

    #endif

    #ifdef TEST_GETITEMNAMEFROMFLASH

    inline char * getItemNameFromFlash(const MenuItem & item, char * copyToBuffer, size_t bufferSize)
    {
        strncpy_P(copyToBuffer, item.getName(), bufferSize);
        copyToBuffer[bufferSize - 1] = '\0'; // Make sure the buffer is null-terminated.

        return copyToBuffer;
    }

    #endif

    /*
        This is an important function
        Here all use events are handled

        This is where you define a behaviour for a menu item
     */
    void menuUseEvent(MenuUseEvent used)
    {
        Serial.print(F("Menu use "));

    #ifdef TEST_FROMFLASH
        Serial.println(fromFlash(used.item.getName()));
    #endif

    #ifdef TEST_GETITEMNAMEFROMFLASH
        char itemNameBuffer[31]; // 30 chars + '\0';
        Serial.println(getItemNameFromFlash(used.item, itemNameBuffer, sizeof(itemNameBuffer)));
    #endif

        if (used.item == setDelay) //comparison against a known item
        {
            Serial.println(F("menuUseEvent found Delay (D)"));
        }
    }

    /*
        This is an important function
        Here we get a notification whenever the user changes the menu
        That is, when the menu is navigated
     */
    void menuChangeEvent(MenuChangeEvent changed)
    {
        Serial.print("Menu change ");

    #ifdef TEST_FROMFLASH
        Serial.println(fromFlash(changed.to.getName()));

    #endif

    #ifdef TEST_GETITEMNAMEFROMFLASH
        char itemNameBuffer[31]; // 30 chars + '\0';
        Serial.print(getItemNameFromFlash(changed.from, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.print(" char is ");
        Serial.println(getItemNameFromFlash(changed.to, itemNameBuffer, sizeof(itemNameBuffer)));
    #endif
    }

    void setup()
    {
        Serial.begin(9600);

        Serial.println(F("Revision 1.0."));

        menuSetup();
        Serial.println(F("Starting navigation:\r\n   Down: s   Left: a   Right: d   Use: e"));
    }

    void showAllNames()
    {
    #ifdef TEST_FROMFLASH
        Serial.println(fromFlash(settings.getName()));
        Serial.println(fromFlash(pin.getName()));
        Serial.println(fromFlash(debug.getName()));
        Serial.println(fromFlash(options.getName()));
        Serial.println(fromFlash(setDelay.getName()));
        Serial.println(fromFlash(d100.getName()));
        Serial.println(fromFlash(d200.getName()));
        Serial.println(fromFlash(d300.getName()));
        Serial.println(fromFlash(d400.getName()));
    #endif

    #ifdef TEST_GETITEMNAMEFROMFLASH
        char itemNameBuffer[31]; // 30 chars + '\0';

        Serial.println(getItemNameFromFlash(settings, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(pin, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(debug, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(options, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(setDelay, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(d100, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(d200, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(d300, itemNameBuffer, sizeof(itemNameBuffer)));
        Serial.println(getItemNameFromFlash(d400, itemNameBuffer, sizeof(itemNameBuffer)));
    #endif
    }

    void loop()
    {
        if (Serial.available()) {
            byte read = Serial.read();
            switch (read) {
            case 's':
                menu.moveDown();
                break;
            case 'd':
                menu.moveRight();
                break;
            case 'a':
                menu.moveLeft();
                break;
            case 'e':
                menu.use();
                break;
            case 'z':
                showAllNames();
                break;
            }
        }
    }

MenuBackend.h

    /*
    ||
    || @file    MenuBackend.h
    || @version 1.4
    || @author  Alexander Brevig
    || @contact alexanderbrevig@gmail.com
    || @contribution Adrian Brzezinski adrb@wp.pl, http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?action=viewprofile;username=vzhang
    ||
    || @description
    || | Provide an easy way of making menus
    || #
    ||
    || @license
    || | This library is free software; you can redistribute it and/or
    || | modify it under the terms of the GNU Lesser General Public
    || | License as published by the Free Software Foundation; version
    || | 2.1 of the License.
    || |
    || | This library is distributed in the hope that it will be useful,
    || | but WITHOUT ANY WARRANTY; without even the implied warranty of
    || | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    || | Lesser General Public License for more details.
    || |
    || | You should have received a copy of the GNU Lesser General Public
    || | License along with this library; if not, write to the Free Software
    || | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    || #
    ||
    */

    #ifndef MenuBackend_h
    #define MenuBackend_h

    #include <avr/pgmspace.h>

    /*
        A menu item will be a container for an item that is a part of a menu
        Each such item has a logical position in the hierarchy as well as a text and maybe a mnemonic shortkey
    */
    class MenuItem {
    public:
        MenuItem(const char * itemName, char shortKey='\0' ) : name(itemName), shortkey(shortKey) {
            before = right = after = left = 0;
        }

        //void use(){} //update some internal data / statistics
        inline const char * getName() const { return name; }
        inline const char getShortkey() const { return shortkey; }
        inline const bool hasShortkey() const { return (shortkey!='\0'); }
        inline void setBack(MenuItem *b) { back = b; }
        inline MenuItem* getBack() const { return back; }
        inline MenuItem* getBefore() const { return before; }
        inline MenuItem* getRight() const { return right; }
        inline MenuItem* getAfter() const { return after; }
        inline MenuItem* getLeft() const { return left; }

        MenuItem *moveBack() { return back; }

        MenuItem *moveUp() {
            if (before) { before->back = this; }
            return before;
        }

        MenuItem *moveDown() {
            if (after) { after->back = this; }
            return after;
        }

        MenuItem *moveLeft() {
            if (left) { left->back = this; }
            return left;
        }

        MenuItem *moveRight() {
            if (right) { right->back = this; }
            return right;
        }

        //default vertical menu
        MenuItem &add(MenuItem &mi) { return addAfter(mi); }

        MenuItem &addBefore(MenuItem &mi) {
            mi.after = this;
            before = &mi;
            if ( !mi.back ) mi.back = back;
            return mi;
        }
        MenuItem &addRight(MenuItem &mi) {
            mi.left = this;
            right = &mi;
            if ( !mi.back ) mi.back = back;
            return mi;
        }
        MenuItem &addAfter(MenuItem &mi) {
            mi.before = this;
            after = &mi;
            if ( !mi.back ) mi.back = back;
            return mi;
        }
        MenuItem &addLeft(MenuItem &mi) {
            mi.right = this;
            left = &mi;
            if ( !mi.back ) mi.back = back;
            return mi;
        }
    protected:

        const char * name;
        const char shortkey;

        MenuItem *before;
        MenuItem *right;
        MenuItem *after;
        MenuItem *left;
        MenuItem *back;
    };

    //no dependant inclusion of string or cstring
    bool menuTestStrings1(const char *a, const char *b) { // a is in flash, b is in SRAM.
        for (uint8_t da = pgm_read_byte_near(a); da; da = pgm_read_byte_near(++a), b++)
        {
            if (da != *b)
                return false;
        }
        return (*b == '\0'); // We reached the end of a.  Strings are equal only if we reached the end of b too.
    }
    bool menuTestStrings2(const char *a, const char *b) { // a and b are both in flash.
        uint8_t da = pgm_read_byte_near(a); // Dereferenced a.
        uint8_t db = pgm_read_byte_near(b); // Dereferenced b.

        for ( ; da; da = pgm_read_byte_near(++a), db = pgm_read_byte_near(++b))
        {
            if (da != db)
                return false;
        }

        return (db == '\0'); // We reached the end of a.  Strings are equal only if we reached the end of b too.
    }
    bool operator==(MenuItem &lhs, char* test) {
        return menuTestStrings1(lhs.getName(),test);
    }
    bool operator==(const MenuItem &lhs, char* test) {
        return menuTestStrings1(lhs.getName(),test);
    }
    bool operator==(MenuItem &lhs, MenuItem &rhs) {
        return menuTestStrings2(lhs.getName(),rhs.getName());
    }
    bool operator==(const MenuItem &lhs, MenuItem &rhs) {
        return menuTestStrings2(lhs.getName(),rhs.getName());
    }

    struct MenuChangeEvent {
        const MenuItem &from;
        const MenuItem &to;
    };

    struct MenuUseEvent {
        const MenuItem &item;
    };

    typedef void (*cb_change)(MenuChangeEvent);
    typedef void (*cb_use)(MenuUseEvent);

    const char itemNameMenuRoot[] PROGMEM = "MenuRoot";

    class MenuBackend {
    public:

        MenuBackend(cb_use menuUse, cb_change menuChange = 0) : root(itemNameMenuRoot) {
            current = &root;
            cb_menuChange = menuChange;
            cb_menuUse = menuUse;
        }

        MenuItem &getRoot() {
            return root;
        }
        MenuItem &getCurrent() {
            return *current;
        }

        void moveBack() {
            setCurrent(current->getBack());
        }

        void moveUp() {
            setCurrent(current->moveUp());
        }

        void moveDown() {
            setCurrent(current->moveDown());
        }

        void moveLeft() {
            setCurrent(current->moveLeft());
        }

        void moveRight() {
            setCurrent(current->moveRight());
        }

        void use(char shortkey)
        {
            recursiveSearch(shortkey,&root);
            use();
        }

        void use() {
            //current->use();
            if (cb_menuUse) {
                MenuUseEvent mue = { *current };
                cb_menuUse(mue);
            }
        }

    private:
        void setCurrent( MenuItem *next ) {
            if (next) {
                if (cb_menuChange) {
                    MenuChangeEvent mce = { *current, *next };
                    (*cb_menuChange)(mce);
                }
                current = next;
            }
        }
        void foundShortkeyItem(MenuItem *mi) {
            mi->setBack(current);
            current = mi;
        }
        char canSearch(const char shortkey, MenuItem *m) {
            if (m==0) { return 0; }
            else  {
                if (m->getShortkey()==shortkey) {
                    foundShortkeyItem(m);
                    return 1;
                }
                return -1;
            }
        }
        void rSAfter(const char shortkey, MenuItem *m) {
            if (canSearch(shortkey,m)!=1) {
                rSAfter(shortkey, m->getAfter());
                rSRight(shortkey, m->getRight());
                rSLeft(shortkey, m->getLeft());
            }
        }
        void rSRight(const char shortkey, MenuItem *m) {
            if (canSearch(shortkey,m)!=1) {
                rSAfter(shortkey, m->getAfter());
                rSRight(shortkey, m->getRight());
                rSBefore(shortkey, m->getBefore());
            }
        }
        void rSLeft(const char shortkey, MenuItem *m) {
            if (canSearch(shortkey,m)!=1) {
                rSAfter(shortkey, m->getAfter());
                rSLeft(shortkey, m->getLeft());
                rSBefore(shortkey, m->getBefore());
            }
        }
        void rSBefore(const char shortkey, MenuItem *m) {
            if (canSearch(shortkey,m)!=1) {
                rSRight(shortkey, m->getRight());
                rSLeft(shortkey, m->getLeft());
                rSBefore(shortkey, m->getBefore());
            }
        }
        void recursiveSearch(const char shortkey, MenuItem *m) {
            if (canSearch(shortkey,m)!=1) {
                rSAfter(shortkey, m->getAfter());
                rSRight(shortkey, m->getRight());
                rSLeft(shortkey, m->getLeft());
                rSBefore(shortkey, m->getBefore());
            }
        }

        MenuItem root;
        MenuItem *current;

        cb_change cb_menuChange;
        cb_use cb_menuUse;
    };

    #endif

body:
You have a global variable `menu`, which is of type `MenuBackend`, which contains the structure of your menu system. One of the member functions of `MenuBackend` is `MenuItem getCurrent()`, which returns a reference to the currently active menu.

If you look at the class definition of `MenuItem`, you can see that among the public member functions, you have:

    inline MenuItem* getBack() const { return back; }
    inline MenuItem* getBefore() const { return before; }
    inline MenuItem* getRight() const { return right; }
    inline MenuItem* getAfter() const { return after; }
    inline MenuItem* getLeft() const { return left; }

Since `menu` is a global, anywhere in your program, you ought to be able to use:

    menu.getCurrent().getAfter();

to access the `MenuItem` after the current one. Likewise with just `menu.getCurrent()`.

----------
**EDIT:**

I add the following lines to your `showAllNames()` function, just to check:

    Serial.println(fromFlash(menu.getCurrent().getName()));
    Serial.println(fromFlash(menu.getCurrent().getAfter()->getName()));

And it seemed to work fine.


sender: user

message:
How to share/Reassign analog pin for two Adafruit libraries for two adafruit hardware

I'm attempting to use the Adafruit BMP180 and Adafruit 16x2 RGB LCD Display together on the same Arduino Uno R1. Both the pieces of hardware and their libraries use Analog Pin 4 and 5. Is there any way to reassign the pins for one of the libraries so I can use both of the parts together?

Here are the libraries I am using:

Adafruit BMP180/BMP085:
[https://github.com/adafruit/Adafruit_BMP085_Unified][1] and [https://github.com/adafruit/Adafruit-BMP085-Library][2]

Adafruit 16x2 RGB LCD Display:
[https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library][3]

  [1]: https://github.com/adafruit/Adafruit_BMP085_Unified
  [2]: https://github.com/adafruit/Adafruit-BMP085-Library
  [3]: https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library

sender: assistant

body: If they are using I2C (which i think they are), then it doesn't matter, because I2C is just a transfer protocol. In theory, you could have hundreds of devices using those pins, and have everything working fine. Just try using both, and tell me if anything doesn't work.


message:
Typedef not accepted as a data type in a function?

I know I'm in a C++ compiler, but I typically create a typedef from structures, probably a holdover from earlier C programming. So this has my head spinning. I create a Typedef from a structure. After that, I have no trouble declaring a global or local version of that structure anywhere in a function, or outside of all functions (global). But when I try to create a function with this typedef as an arg, or even a function arg with a pointer the such a typedef, the compiler complains (and the complaint doesn't seem to make sense). Example...

    typedef struct ss_tag {
      uint16_t settingsSavedCount;
      uint16_t codeID;

    // a few more vars

      uint8_t powerDownSaveFlag; // lets me know why we're being reset.
      uint8_t future[10];
    } Sunstates;

So now, this typedef seems as good as any other. Either of these statements compile fine...

    Sunstates sunStates;
    Sunstates * pSS = &sunStates;

But if I now try to create a function, with either an instance of this data type or a pointer to it, like so...

    void systemDataVerify(Sunstates *pST) {  }

The Arduino compiler offers this confusing error message...

> Arduino: 1.8.3 (Windows XP), Board: "Arduino Nano, ATmega328"
>
> SolarControler_21a:393: error: variable or field 'systemDataVerify'
> declared void
>
>   void systemDataVerify(Sunstates *pSS) { }
>
>                        ^
>
> SolarControler_21a:393: error: 'Sunstates' was not declared in this
> scope
>
> SolarControler_21a:393: error: 'pSS' was not declared in this scope
>
>   void systemDataVerify(Sunstates *pSS) { }
>
> exit status 1 variable or field 'systemDataVerify' declared void

The fact that it doesn't like me declaring a function void is odd, but not as troubling as it calling my function a 'variable or field' and definitely not as strange as it saying my datatype (Sunstates) was NOT "declared in this scope." The data type was defined immediately before the function... and the fact I could declare both instances of the type AND pointers to it kind of proves it exists within the scope. Can someone help me understand why the compiler is complaining?

Edit... I was asked to include a short sketch that shows the problem...

```c
uint8_t somefunction() {
  return;
}

// define structure to hold/save setup and mode info

typedef struct ss_tag {
  uint16_t settingsSavedCount;
  uint8_t powerDownSaveFlag; // lets me know why we're being reset.
} Sunstates;

Sunstates sunStates; // create an instance

// create a function to accept a pointer to
// type Sunstates as an arg

void systemDataVerify(Sunstates *p) {
  return;
}

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}
```

Now... I have discovered that if I remove the 'somefunction()' definition before the Structure definition, the problem goes away. And I'm using Arduino 1.8.3 to compile this.

body:
I do not get this error in Arduino IDE 1.8.5 with snippet you provided, but I get it in Sloeber Eclipse plugin. The later attached sketch fails to compile in Arduino IDE 1.8.5 too.

The error is in Arduino build chain ino to cpp conversion for the C++ compilation. Put the typedef declaration into .h file and include it in ino.

EDIT: Details are in my newer [answer to a similar problem](https://arduino.stackexchange.com/questions/66530/class-enum-was-not-declared-in-this-scope/66536#66536).


body:
Here I am 5 years after the OP with the same issue. I'm on Arduino IDE Version: 2.2.1 Date: 2023-08-31T14:35:44.802Z. And I'm using the Adafruit ATSAMD21 M0.

Note that my offending typedef is already in a .h file placing it after everything it needs and before any use so that fix doesn't work for me.

I've discovered what does work around this issue:

Changing this:
int storeXXX( framBlock *fb ) {

To this:
int storeXXX( struct _framBlock *fb ) {

That is, use the 'real' type for function arguments.
The typedef appears to be Ok everywhere else, locals, globals, before and after the point of the error report, etc. Just not as a function argument.

Note that the OP found a similar solution in using void * as the type of his typedef'd pointer. I saw no mention of using the 'real' type which is a more straight forward fix.

Looks like a compiler bug to me. Perhaps that should be passed along to the compiler people.


body:
It's **not** a compiler bug, @alm.

If I take the [Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) provided by the OP, and compile it, and then look at the intermediate file produced by the IDE (not the compiler) you can see what is happening:

<!-- language: c++ -->

    #include <Arduino.h>
    #line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
    #line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
    #line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
    uint8_t somefunction();
    #line 18 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
    void systemDataVerify(Sunstates *p);
    #line 22 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
    void setup();
    #line 26 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
    void loop();
    #line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
    uint8_t somefunction() {
      return;
    }

    // define structure to hold/save setup and mode info

    typedef struct ss_tag {
      uint16_t settingsSavedCount;
      uint8_t powerDownSaveFlag; // lets me know why we're being reset.
    } Sunstates;

    Sunstates sunStates; // create an instance

    // create a function to accept a pointer to
    // type Sunstates as an arg

    void systemDataVerify(Sunstates *p) {
      return;
    }

    void setup() {
      // put your setup code here, to run once:
    }

    void loop() {
      // put your main code here, to run repeatedly:
    }

You will notice that the IDE "helpfully" produces function prototypes for your functions, and that the order in which it does that means that it puts the prototype for `void systemDataVerify(Sunstates *p);` **before** the typedef for the structure, leading to the error message.

The solution is simple. Put your own function prototype into your source, thus telling the IDE to not bother, like this:

<!-- language: c++ -->

    uint8_t somefunction() {
      return;
    }

    // define structure to hold/save setup and mode info

    typedef struct ss_tag {
      uint16_t settingsSavedCount;
      uint8_t powerDownSaveFlag; // lets me know why we're being reset.
    } Sunstates;

    void systemDataVerify(Sunstates *p);  // <<<<<< ---- function prototype

    Sunstates sunStates; // create an instance

    // create a function to accept a pointer to
    // type Sunstates as an arg

    void systemDataVerify(Sunstates *p) {
      return;
    }

    void setup() {
      // put your setup code here, to run once:
    }

    void loop() {
      // put your main code here, to run repeatedly:
    }

---

> Looks like a compiler bug to me. Perhaps that should be passed along to the compiler people.

It's not a bug in the compiler, arguably it is an idiosyncrasy of how the IDE works. No point in submitting bug reports to the compiler-writers. You could conceivably raise an issue on [Github for the IDE](https://github.com/arduino/arduino-ide) complaining about the way they generate function prototypes.

---

For more information see [my answer here](https://arduino.stackexchange.com/a/13182/10794). In it I mention:

> The function prototype generation however can lead to obscure error messages if you are not careful.


message:
Arduino Serial Writing Array Problem

I am trying to communicate Pc - Arduino Uno.

My Arduino code is here: (It is working as below)

    int ndx = 0;
    char pack[12];
    void setup() {
    Serial.begin(9600);
    while(!Serial){;}
    }

      void loop() {

       while(Serial.available() ){
        char rb = Serial.read();
        pack[ndx] = rb;
        ndx++;
        Serial.write(rb);
        if(ndx == 12){
            ndx=0;
          }
        }
        }

If I try in

    Serial.write(rb);
Like that:

    Serial.write(pack[ndx]);

Program is acting weird, I mean sending weird bytes. I do not know what is the reason. Can you help me, please? What is going on in code?
My python code:
https://github.com/mucahitkayadan/Python

body:
you replace `Serial.write(rb);` to `Serial.write(pack[ndx]);` and get?:

    char rb = Serial.read();
    pack[ndx] = rb;
    ndx++;
    Serial.write(pack[ndx]);

then you read an uninitialized array item on the next index


body:
The sequence:

    pack[ndx] = rb;
    ndx++;
    Serial.write(rb);

modifies ndx before printing. So in your first case - printing 'rb' - you'll print the value you just stored in the array; in the second case printing 'pack[ndx]' - you'll print whatever happens to be in the _following_ member of the array. Swapping the second and third statements in my excerpt will fix it.


message:
How we can implement the interrupt?

I want to implement the Interrupt on the Adafruit_RGBLCDShield Select button to start/stop the data logging?

body:
There is no interrupt for the select button.

The buttons, and the LCD itself, are connected to an I2C IO expander. Reading the state of the buttons is a *polling* operation - the library sends a request to the IO expander to get the current state, and then returns that to you as a bitmap.

While it is true the IO expander can be configured to generate an interrupt signal on one of its IO pins when an input changes state, that pin is not connected to anything on the PCB, so you would need to physically modify the shield to connect it to an interrupt pin on the Arduino. And on top of that, the library doesn't implement the settings needed to enable the interrupt - so you'd have to resort to configuring it all manually.

If you really want to do that kind of thing, then you will have to examine the [datasheet for the IO expander](http://ww1.microchip.com/downloads/en/DeviceDoc/20001952C.pdf) and learn how it works.


message:
Using external reset to trigger radio receipt

I am designing a low-power RF application using an ATTiny (Adafruit Trinket).

When the system receives a radio signal, it needs to read some sensors, and transmit with that data. Because I am short on pins, I am trying to think of creative (low-pin count) ways to design this system.

My current idea is:

* Put the AVR to sleep.
* Connect the radio's Rx Interrupt pin to the AVR Reset pin
* When the AVR is reset, check the radio buffer
  * _(if there's nothing in the buffer, assume this is a real power-on reset and go back to sleep)_
* Otherwise, read sensors, transmit
* Go back to sleep

My aim here is that the AVR will use very little power while sleeping (furthermore, it will only need to wake up a few times per day).

Is it reasonable to use the AVR reset pin in this manner? Any gotchas to be aware of?

body:
No gotchas I can think of, except for the fact that the ATtiny's memory
will be re-initialized every time you reset it. But I assume you are
aware of that.

Note that, if you want some data to be preserved across a reset, it is
possible using either the on-chip EEPROM or the [.noinit
section][noinit] of the RAM.

[noinit]: https://www.nongnu.org/avr-libc/user-manual/mem_sections.html#sec_dot_noinit


message:
Arduino controlled by USB gamepad

I want to control my Arduino with USB gamepad. I know that exists library for USB keyboard for Arduino but I don't know any library for usb gamepad. I have PS3 styled gamepad. I dont want to use shield.

Any solution or help?

body:
A USB host shield or mini board depending on your Arduino board should work.

https://github.com/felis/USB_Host_Shield_2.0

https://www.circuitsathome.com/usb-host-shield-hardware-manual/


message:
Can you help me trim my code?

First of all I want to be clear, I'm not very skilled in programming methods, all the C I learned was for various Arduino projects.

That being said, I just finished a project that reads some data from ELM327 via a HC-05 Bluetooth module and prints it to a 3.5 inch screen. All is working as intended, but apparently I have capped my Arduino UNO's memory because the sketch utilizes 99% of it. At the moment this is not very troublesome, but if sometime in the future I want to add more data to be read, I won't be able to do it.

With this in mind, I was looking for some advice on how I could rewrite my code in order to occupy less memory. I tried some stuff, but had little effect. As I said, I'm not familiar with advanced programming techniques.

LE: So I used all of your advice, I got rid of all the fonts, modified the MCUFRIEND library to only work with my display and got rid of some repeating code, and now the sketch got 35% smaller. Thanks to all.

> Sketch uses 21216 bytes (65%) of program storage space. Maximum is 32256 bytes.
Global variables use 642 bytes (31%) of dynamic memory, leaving 1406 bytes for local variables. Maximum is 2048 bytes.

Here's the (old) code:

    #include <SoftwareSerial.h>
    #include <Adafruit_GFX.h>
    #include <MCUFRIEND_kbv.h>
    #include <Fonts/FreeMonoBold9pt7b.h>
    #include <Fonts/FreeMonoBold12pt7b.h>
    #include <Fonts/FreeMonoBold18pt7b.h>
    #include <Fonts/FreeMonoBold24pt7b.h>

    SoftwareSerial BTSerial(10, 11);
    MCUFRIEND_kbv tft;

    #define BLACK   0x0000
    #define WHITE   0xFFFF
    #define GREY    0x8410

    byte inData;
    char inChar;
    String constructor="";
    String deconstructor="";
    int A;
    int B;
    bool busy = false;

    void setup()
    {
        Retry:
        Serial.begin(9600);
        BTSerial.begin(38400);
        delay(1000);

        BTSerial.println("0100");
        while(BTSerial.available()>0)
        {
          inData=0;
          inChar=0;
          inData = BTSerial.read();
          inChar=char(inData);
          constructor = constructor + inChar;
          delay(20);
       }
        if (constructor.length()>0)
        {
          Serial.println("Conectat");
        }
        else {
          goto Retry;
          Serial.println("retry");
        }
        delay(5000);
        ReadData();
        basicConditions();

        tft.reset();
        uint16_t identifier = tft.readID();
        if (identifier == 0xEFEF) identifier = 0x9486;
        tft.begin(identifier);

        tft.fillScreen(BLACK);
        tft.setRotation(1);
        tft.setTextColor(WHITE);

        tft.fillRect(10, 40, 70, 40, GREY);
        tft.fillRect(10, 140, 70, 40, GREY);
        tft.fillRect(10, 240, 70, 40, GREY);
        tft.fillRect(140, 70, 200, 100, GREY);
        tft.fillRect(150, 220, 180, 60, GREY);
        tft.fillRect(370, 40, 70, 40, GREY);
        tft.fillRect(370, 140, 70, 40, GREY);
        tft.fillRect(370, 240, 70, 40, GREY);

        tft.setCursor(170,10);
        tft.setFont(&FreeMonoBold12pt7b);
        tft.print("Dacia 4X4");

        tft.setCursor(30,35);
        tft.setFont(&FreeMonoBold9pt7b);
        tft.print("Cuplu");
        tft.setCursor(80,70);
        tft.setFont(&FreeMonoBold18pt7b);
        tft.print("%");

        tft.setCursor(15,120);
        tft.setFont(&FreeMonoBold9pt7b);
        tft.print("Presiune");
        tft.setCursor(15,135);
        tft.print("motorina");
        tft.setCursor(82,170);
        tft.setFont(&FreeMonoBold12pt7b);
        tft.print("bar");

        tft.setCursor(15,220);
        tft.setFont(&FreeMonoBold9pt7b);
        tft.print("Presiune");
        tft.setCursor(20,235);
        tft.print("admisie");
        tft.setCursor(82,270);
        tft.setFont(&FreeMonoBold12pt7b);
        tft.print("bar");

        tft.setCursor(395,20);
        tft.setFont(&FreeMonoBold9pt7b);
        tft.print("Temp.");
        tft.setCursor(382,35);
        tft.print("Antigel");
        tft.setCursor(450,70);
        tft.setFont(&FreeMonoBold12pt7b);
        tft.print("C");

        tft.setCursor(395,120);
        tft.setFont(&FreeMonoBold9pt7b);
        tft.print("Temp.");
        tft.setCursor(382,135);
        tft.print("Admisie");
        tft.setCursor(450,170);
        tft.setFont(&FreeMonoBold12pt7b);
        tft.print("C");

        tft.setFont(&FreeMonoBold9pt7b);
        tft.setCursor(370,235);
        tft.print("Debit Aer");
        tft.setCursor(445,270);
        tft.setFont(&FreeMonoBold9pt7b);
        tft.print("g/s");

        tft.setFont(&FreeMonoBold12pt7b);
        tft.setCursor(150, 62);
        tft.print("Turatie (RPM)");

        tft.setFont(&FreeMonoBold12pt7b);
        tft.setCursor(152, 212);
        tft.print("Viteza (KM/H)");

    }

    void loop()
    {
      cuplu();
      PresMot();
      PresAdm();
      TempAntig();
      TempAdm();
      MAF();
      RPM();
      viteza();
    }
    void basicConditions(){
        if(constructor.indexOf(">")>0)  {
        busy=false;
        constructor="";
      }
    }
    void ReadData()
    {
      if (BTSerial.available()>0)
        busy = true;
      while(busy = true && constructor.indexOf(">")<0)
      {
        if (BTSerial.available()>0){
        inData=0;
        inChar=0;
        inData = BTSerial.read();
        inChar=char(inData);
        constructor = constructor + inChar;
        //Serial.println(constructor);
        //Serial.println(busy);
      }
      }
      //Serial.println("done");

      if (constructor.indexOf(">")>0){
       deconstructor=constructor.substring(11,13);
       A = strtol(deconstructor.c_str(),NULL,16);
       if (constructor.length()>15) {
        deconstructor = constructor.substring(14,16);
       B = strtol(deconstructor.c_str(),NULL,16);
       }
       else B = 0;
      }
    }
    void cuplu() {
      if (busy == false){
        BTSerial.println("01041");
       ReadData();
        tft.setTextSize(1);
        tft.setFont(&FreeMonoBold18pt7b);
        tft.setCursor(10, 70);
        tft.fillRect(10, 40, 70, 40, GREY);
        tft.print(A/2.55, 0);
      }
      basicConditions();
    }
    void PresMot() {
      if (busy == false){
       BTSerial.println("010A1");
       ReadData();
       tft.setTextSize(1);
       tft.setFont(&FreeMonoBold18pt7b);
       tft.setCursor(10, 170);
        tft.fillRect(10, 140, 70, 40, GREY);
        tft.print((3*A)/100.0, 1);
      }
      basicConditions();
    }
    void PresAdm() {
      if (busy == false){
       BTSerial.println("010B1");
       ReadData();
       tft.setTextSize(1);
       tft.setFont(&FreeMonoBold18pt7b);
       tft.setCursor(10, 270);
        tft.fillRect(10, 240, 70, 40, GREY);
        tft.print((A/100.0), 1);
      }
      basicConditions();
    }
    void TempAntig() {
     if (busy == false){
       BTSerial.println("01051");
       ReadData();
       tft.setTextSize(1);
       tft.setFont(&FreeMonoBold18pt7b);
       tft.fillRect(370, 40, 70, 40, GREY);
        tft.setCursor(370, 70);
        tft.print(A-40);
     }
      basicConditions();
    }
    void TempAdm() {
     if (busy == false){
       BTSerial.println("010F1");
       ReadData();
       tft.setTextSize(1);
       tft.setFont(&FreeMonoBold18pt7b);
       tft.fillRect(370, 140, 70, 40, GREY);
        tft.setCursor(370, 170);
        tft.print(A-40);
     }
      basicConditions();
    }
    void MAF() {
      if (busy == false){
       BTSerial.println("01101");
       ReadData();
       tft.setTextSize(1);
       tft.setFont(&FreeMonoBold18pt7b);
       tft.fillRect(370, 240, 70, 40, GREY);
        tft.setCursor(370, 270);
        tft.print(((256*A)+B)/4.0, 0);
      }
      basicConditions();
    }
    void RPM() {
      if (busy == false){
       BTSerial.println("010C1");
       ReadData();
       tft.setFont(&FreeMonoBold18pt7b);
        tft.setTextSize(2);
        tft.fillRect(140, 70, 200, 100, GREY);
        tft.setCursor(150, 140);
        tft.print(A/4.0, 0);
      }
      basicConditions();
    }
    void viteza() {
      if (busy == false){
       BTSerial.println("010D1");
       ReadData();
       tft.setFont(&FreeMonoBold18pt7b);
        tft.setTextSize(2);
       tft.fillRect(150, 220, 180, 60, GREY);
        tft.setCursor(180, 270);
        tft.print(A);
      }
      basicConditions();
    }

body:
The documentation for the [MCUFRIEND_kbv project][1] has a file [describing how to use][2].

This document has the statement:

    Most of these controllers are #define SUPPORT_xxxx by default.
    You can save Flash memory on a Uno by commenting out the macro(s) in MCUFRIEND_kbv.cpp

So you open MCUFRIEND_kbv.cpp and comment out support for the controllers you **aren't** using.

You can also reduce the number of different fonts you use to save Flash space.

  [1]: https://github.com/prenticedavid/MCUFRIEND_kbv
  [2]: https://github.com/prenticedavid/MCUFRIEND_kbv/blob/master/extras/mcufriend_how_to.txt


body:
Strings get allocated, reallocated, and deallocated as you use them, which can leave the heap - the bottom end of RAM memory - fragmented and the fragments essentially unusable. The memory report from the compiler can't show this; it happens at runtime.

If instead, you pre-allocate character arrays of a sufficient size for the eventual maximum text you want to put in them, they will stay in one place, neither growing nor shrinking, but also won't create those unused but unusable "holes" in the RAM.

Update:

Instead of:

    String xyz;
    xyz = "Hello";
    xyz = xyz + ',';
    xyz = xyz + "World!\n";

, you'd write:

    #define XYZ_MAX  25    // or whatever size you need

    char xyz[XYZ_MAX+1];
    strcpy(xyz, "Hello";      // overwrites whatever is there
    strcat(xyz, ", World!\n"; // appends whatever is there

You can further optimize RAM by directing the compiler to store the string literal (`"Hello"`, etc.) in Flash. That's another topic, but here is a l[ink to an article][1] about it in the Arduino Playground, to get you started.

  [1]: https://playground.arduino.cc/Main/PROGMEM


body:
you are repeating the same code in the 8 functions at the end of your sketch (note: the code is badly indented and the command sequence is inconsistent between functions)

similar thing is occurring at the middle of your sketch

here is the data that repeats

you could use one function and a lookup table (array)

this is the repeating data

    +---------------+-------+-------------------------------+---------------+-----------------------+
    |  println     setTextSize        fillRect                 setCursor          print             |
    +---------------+-------+-------------------------------+---------------+-----------------------+
    |   "01041"     |   1   |    10,  40,  70,  40, GREY    |    10,  70    |   A/2.55         , 0  |
    |   "010A1"     |   1   |    10, 140,  70,  40, GREY    |    10, 170    |   (3*A)/100.0    , 1  |
    |   "010B1"     |   1   |    10, 240,  70,  40, GREY    |    10, 270    |   (A/100.0)      , 1  |
    |   "01051"     |   1   |   370,  40,  70,  40, GREY    |   370,  70    |   A-40                |
    |   "010F1"     |   1   |   370, 140,  70,  40, GREY    |   370, 170    |   A-40                |
    |   "01101"     |   1   |   370, 240,  70,  40, GREY    |   370, 270    |   ((256*A)+B)/4.0, 0  |
    |   "010C1"     |   2   |   140,  70, 200, 100, GREY    |   150, 140    |   A/4.0          , 0  |
    |   "010D1"     |   2   |   150, 220, 180,  60, GREY    |   180, 270    |   A                   |
    +---------------+-------+-------------------------------+---------------+-----------------------+

you could also calculate some of the values in the first 6 functions


body:
I assume you mean that are running short of _flash_ memory, rather than
_RAM_. I base this assumption on the fact that you say that it's 99%
full, and that this “is not very troublesome”. Filling 99% of the RAM
with statically allocated data would certainly be troublesome. But
please note that it as always better to make your question clear and
explicit, rather than expect the respondents to make guesses.

Now, look at your font files. Each one of them ends with a comment
similar to this:

    // Approx. 1672 bytes

Just adding those numbers we get:

    FreeMonoBold9pt7b   1672 bytes
    FreeMonoBold12pt7b  2402 bytes
    FreeMonoBold18pt7b  4485 bytes
    FreeMonoBold24pt7b  7469 bytes
    ------------------------------
    TOTAL              16028 bytes

That's about 49% of your Arduino's flash. So that's the first place you
should be looking to if you want to save flash. Do you _really_ need
these four different font sizes? And more specifically, do you _really_
need the (very flash hungry) largest sizes? Getting rid of some of them
is the easiest way to save flash.

If you really want to keep them all, your next option is to trim the
fonts in order to have only the characters you are actually using. This
can be a lot of work, but it should be a very effective way of
significantly reducing their flash footprint.

If you decide to take this path, the first step is to take note of what
characters you need at each font size. From a cursory look at your
source, it seems to me that the 18 pt font is only used for
printing “%”, “.”, the ten digits, and possibly “-”. That's a lot less
than the full ASCII repertoire the font supports. And I can't see where
you are using the 24 pt font. Look into an ASCII table and take
note of the smallest continuous range that contains all the characters
you use at one font size. Then trim the `Glyphs` array of the font to
keep only that range, and fix the `first` and `last` fields of the
`GFXfont` struct accordingly.

Next step is what will take most of the work. For each character you
actually need, take note of the `bitmapOffset` field of its glyph _and
the next one_. This way you know the range of offsets that are used by
that character. Then remove from the font's `Bitmaps` array all the
bytes that are at offsets you don't need. While doing this, you will be
changing the offsets of the bytes you keep, so you should update the
`bitmapOffset` fields on the `Glyphs` array accordingly.

Yes, that's quite some work, but you should end up with custom fonts
that are a lot lighter than the original ones, and yet capable of
displaying everything you are displaying now. Maybe you could write a
program to automate all this. Maybe someone already did that and you can
find it through a Web search...


message:
Need help with a program for a button to change the display on an OLED display

So I am programming an **OLED** display from my **Arduino Uno**. I am trying to have a button that switches the different words on the display. (The words are just placeholders for programs as of now.) My program has a button that changes a counter, and an if test to see what the counter is so it can display the appropriate word. The problem is, whenever I press the button, the display turns black and doesn't do anything anymore. When I start/reset the Arduino, it displays **TEMPERATURE**, but it should say **TIME**.

    #include <OLED_I2C.h>

    OLED  myOLED(SDA, SCL, 8);

    extern uint8_t SmallFont[];
    extern uint8_t MediumNumbers[];
    extern uint8_t BigNumbers[];

    //constants:
    const int buttonPin = 2;

    //variables:
    byte oldButtonState = HIGH;
    int screenNumber = 0;
    byte buttonState = 0;

    void setup()
    {
      myOLED.begin();
      myOLED.setFont(SmallFont);
      pinMode(buttonPin, INPUT_PULLUP);
    }

    void loop() { //myOLED.print formats with (string, text_placement,     pixel_location)
      // read the pushbutton input pin:
      buttonState = digitalRead(buttonPin);

      // Test if the button is being pressed
      if (buttonState == HIGH) {
        myOLED.clrScr();
        myOLED.update();
        oldButtonState = buttonState;
        if (screenNumber != 2) {
          ++screenNumber;
        }
        else {
          screenNumber = 0;
        }
        //delay a little to avoid bouncing
        delay(200);
        }

      //Test for the screenNumber variable and change to the
      //according screen
      if (screenNumber == 0) {
        myOLED.print("TIME", CENTER, 16);
        myOLED.update();
      }
      else if (screenNumber == 1) {
        myOLED.print("TEMPERATURE", CENTER, 16);
        myOLED.update();
      }
      else if (screenNumber == 2) {
        myOLED.print("DIRECTION", CENTER, 16);
        myOLED.update();
      }
      else {
        myOLED.print("ERROR", CENTER, 16);
        myOLED.update();
      }
    }

body:
You have `pinMode(buttonPin, INPUT_PULLUP);` so I assume, you connected the button between pin and ground. With pull-up the pin will read HIGH if it is not grounded. If the button is pushed, grounding the button pulls it LOW. So you should test if the button is pressed with comparing to LOW.

We have this misleading idea in our heads that active is HIGH and not active is LOW. But you can see it this way:

 - button pushed down (low) is LOW
 - button not pushed is up (high) reading HIGH


body:
I fixed the problem. It turned out that the value being returned by the button was **1** when it was not being pressed and **0** when it was being pressed. My new code is:

    #include <OLED_I2C.h>

    OLED  myOLED(SDA, SCL, 8);

    extern uint8_t SmallFont[];
    extern uint8_t MediumNumbers[];
    extern uint8_t BigNumbers[];

    //constants:
    const int buttonPin = 2;
    const int debug = 0;

    //variables:
    int screenNumber = 0;
    byte buttonState = 0;

    void setup()
    {
      myOLED.begin();
      myOLED.setFont(SmallFont);
      pinMode(buttonPin, INPUT);
      myOLED.clrScr();
      myOLED.print("TIME", CENTER, 16);
      myOLED.update();
      Serial.begin(9600);
    }

    void loop() { //myOLED.print() formats with (string, text_placement, pixel_location)
      // read the pushbutton input pin:
      buttonState = digitalRead(buttonPin);
      Serial.println(buttonState);
      if (debug == 1) {
        myOLED.clrScr();
        myOLED.print("Start", CENTER, 16);
        myOLED.update();
        delay(debugDelay);
      }
      // compare the buttonState to its previous state
      if (buttonState == 0) {
        if (screenNumber < 2) {
          screenNumber = screenNumber + 1;
        }
        else {
          screenNumber = 0;
          }
        //delay a little to avoid bouncing
        delay(100);
        }

      //Test for the screenNumber variable and change to the
      //according screen

      if (screenNumber == 0) {
        myOLED.clrScr();
        myOLED.print("TIME", CENTER, 16);
        myOLED.update();
      }
      else if (screenNumber == 1) {
        myOLED.clrScr();
        myOLED.print("TEMPERATURE", CENTER, 16);
        myOLED.update();
      }
      else if (screenNumber == 2) {
        myOLED.clrScr();
        myOLED.print("DIRECTION", CENTER, 16);
        myOLED.update();
      }
      else {
        myOLED.clrScr();
        myOLED.print("ERROR", CENTER, 16);
        myOLED.update();
      }
    }


message:
Second SD not writing

simple problem I can't see the reason behind, the sd card writes the first file fine, but the second doesn't write at all. Can any one see why?

        #include <SPI.h>
        #include <SD.h>
        const int chipSelect = BUILTIN_SDCARD;
        File datafile;
        void setup()
        {
          Serial.begin(38400);
          analogReadResolution(13);
          //Initialize SPI pins to avoid errors
          //USB host SS pin
          pinMode(9, OUTPUT);
          delay(200);
          digitalWrite(9, HIGH);
          delay(200);
          pinMode(chipSelect, OUTPUT);
          delay(200);
          digitalWrite(chipSelect, HIGH);
          delay(200);

          Serial.print("Initializing SD card...");

          // see if the card is present and can be initialized:
          if (!SD.begin(chipSelect)) {
           Serial.println("Card failed, or not present");
      }
      Serial.println("card initialized.");
      File dFile = SD.open("datalog.txt", FILE_WRITE);
      dFile.println("BORK");
      dFile.close();
      char filename[] = "LOGGER00.CSV";
      for (uint8_t i = 0; i < 100; i++) {
        filename[6] = i / 10 + '0';
        filename[7] = i % 10 + '0';
        if (! SD.exists(filename)) {
          datafile = SD.open(filename, FILE_WRITE);
          break;  // leave the loop!
        }
      }
      Serial.println(filename);
      datafile.print("A0,");
      datafile.println("A1");
      if (!datafile){
        Serial.println("oopsydaisy");
      }
    }

    void loop()
    {
      Serial.print("analog 0 is: ");
      Serial.println(analogRead(0));
      Serial.print("analog 1 is: ");
      Serial.println(analogRead(1));

      datafile.print(String(analogRead(0)));
      datafile.print(",");
      datafile.print(String(analogRead(1)));
      datafile.println();
      delay(1000);
    }

body:
You should cut your code down to the bare minimum.  You need to work out if:

* It's the fact that it's the second file you're opening that causes it to fail, or
* It's the way you're building up the filename in your loop, or
* It's the way you're handling the file once it's been opened.

You should add extra debugging to your program so you know how your loop is operating. Is it checking for the existence of the files correctly? Is it looping too far? Not at all? Is the filename being created properly?

You haven't properly described your symptoms. Does the file actually get created? If so, is it just that it is empty? (I suspect so).

Why do I suspect that?  Simple:

The SD library uses a certain amount of crude caching. Nothing gets written to the SD card itself until either a whole block of data (512 bytes) has been written, or you close the file. Or manually `flush` the data to the card.

When doing periodic writing to a file like that it is better to open the file as `(O_READ | O_WRITE | O_APPEND)` before each block of writes, then close it afterwards. This ensures that the file is in a good state between each sampling period and all the data is written and the FAT updated properly.

So your method should be:

1. Find your unused filename.
2. Open the file `FILE_WRITE` (or `(O_READ | O_WRITE | O_CREAT)` - different versions of the library define it slightly differently) to make the file.
3. Close the file.

Then on each loop iteration where you want to write:

1. Open the file again as `(O_READ | O_WRITE | O_APPEND)`
2. Write your data.
3. Close the file.


body:
You do not close the second file.

The examples show that you should close the file after every write and open it again before next write. Opening the file with SD library using FILE_WRITE flags, opens it for append if the file exists.

In [my project][1] I have a MCU with enough RAM (Mega, esp8266 or M0) so I cache the rows into 2000 bytes buffer and write them to file if the memory cache is full.

  [1]: https://github.com/jandrassy/Regulator/blob/master/Regulator/CsvLog.ino


message:
sending and recieving data from esp8266

We're trying to make an network of connected cars in which the status of one car is continuously updated to the nearby cars (for example, speed, gear, brakes, etc.).

Can I continuously send out sensor data via ESP8266 and and any nearby ESP8266 can pick it up? Is it possible? Or if there's any other method?

body:
Yes, you can - if all the "cars" are on the same WiFi network.

If that is the case, then I'd recommend using UDP as your transport layer, and either *broadcast* or *multicast* the packets.

I use UDP and Multicast to send sensor data from multiple sensors to multiple receivers on my network. All nodes subscribe to the same multicast address, and the sensors include their own ID in the packet to identify them. A sensor sends out one packet, and all the other nodes can receive it.

However, if there is no active WiFi network already established between the "cars" then no, there's not a lot you can do with an ESP8266. It communicates using IP, and that relies on there being an established layer 2 network (WiFi / Ethernet, etc) already in existence. You should instead investigate more peer-to-peer communication technologies, or communication technologies that don't rely on establishing a connection to a network of any form.  Maybe the nRF24L01+ would be a better fit?


message:
How can I prepare for a short circuit between 5V and GND pins?

My Arduino Uno controls a couple of LEDs in a watertight enclosure. I'm running wires from ground, a data pin, and the 5 V pin into the enclosure. The Arduino is powered through the DC jack.

What measures can I take to handle failure of the watertight enclosure, which would short-circuit the wires? Can I protect the Arduino, or at least prevent a fire?

body:
Shoutout to @k.Cyborg who gave a very nice pointer in the comments to a YouTube video on the effects of water on electronics!

One of the things you can do to handle failure of the watertight enclosure better is to use nail polish clear coat and apply that over your board - it will form a protective layer. I use this technique on protoboards with solder bridges on the bottom - adding a layer of clear coat seals them and prevents any shorts due to placing the bottom of the board on a conductive surface, or from fingers touching and shorting things. This would work with water too, to prevent any electrolytic reaction and corrosion, which the video talks about. The video also briefly shows a nail polish clear coat (but doesn't elaborate and says it's a topic for another video).

Another point to consider when talking about shorts. In my case, I was powering my Arduino Pro Mini through the Vin , connected to a 9v battery. I fried the LDO on it by briefly reversing the polarity by switching the terminals by mistake (nice puff of magic smoke!). I added a reverse polarity protection diode in series with the + to prevent a repeat on my next Pro Mini. Since you are powering your Uno through the DC jack (which has a reverse polarity protection diode), it is not an issue for you, but thought I'd mention it if you plan to move to Vin.


message:
Problem with html code in ESP8266 WebServer

Here I have a small problem:

I have an **ESP8266**, to which I have connected a matrix of LEDs to move text (the array of LEDs is made with the tape of LEDs addressable **ws2812**); when you turn on the computer you create an access point with a Captive Portal, which takes you to a small (though still ugly) web interface, where I can manage both the text I show and the speed, intensity and colors of it. All right, everything works ... I know I still have to change several things in the "code" html to work properly, but I hate CSS and right now it is functional.

[![Page example][1]][1]

The problem is the following:

I have several html forms that collect the values of the variables mentioned above (text to be displayed, color, brightness and speed with which the text is displayed), but every time I hit the "*Send*" button the **browser** (I have only tried the browser that comes with my phone (a Xiaomi Redmi Note 4, the application is called Browser itself) and the Google browser, on the same phone) takes me to a screen (I leave screenshot) where it shows me the html code of the page that resides within the esp8266 . And what bothers me is why !? Why does this happen!? (I leave a copy of the code too at the end!)

[![Browser][2]][2]
[![Google Browser][3]][3]

The only thing that occurs to me is that I am saving the page in a variable type **String** (*String object*, not an *array of characters*) ... will anyone know what is due?

Copy of the code:

    //++++++++++++++++++++++++++++++++++++++++++++++//
    //                LIBRERIAS                     //
    //++++++++++++++++++++++++++++++++++++++++++++++//
            /*WiFi*/
    #include <ESP8266WiFi.h>
    #include <DNSServer.h>
    #include <WiFiClient.h>
    #include <ESP8266WebServer.h>

            /*SSID and Password of your WiFi router*/
    const byte DNS_PORT = 53;
    IPAddress apIP(192, 168, 1, 1);
    DNSServer dnsServer;
    ESP8266WebServer server(80);
    const char* ssid = "asd";
    const char* password = "123456789";

    String responseHTML = ""
      "<!DOCTYPE html><title>CaptivePortal</title>"
      "
Hello World!

This is a captive portal example. All requests will "
      "be redirected here.
";

    //++++++++++++++++++++++++++++++++++++++++++++++//
    //                  MATRIZ                      //
    //++++++++++++++++++++++++++++++++++++++++++++++//
            /*LedStrip*/
    #include <FastLED.h>
    #include <LEDMatrix.h>
    #include <LEDText.h>
    #include <FontMatrise.h>

    #define LED_PIN        2
    #define COLOR_ORDER    GRB
    #define CHIPSET        WS2812B
    #define MATRIX_WIDTH   -8
    #define MATRIX_HEIGHT  7
    #define MATRIX_TYPE    HORIZONTAL_ZIGZAG_MATRIX

      /*Creando instancias de la matriz y el objeto*/
    cLEDMatrix<MATRIX_WIDTH, MATRIX_HEIGHT, MATRIX_TYPE> leds;
    cLEDText ScrollingMsg;

        /*Texto a mostrar y colores*/
    char buf[200] = "HOME";
    byte red = 255;
    byte green = 255;
    byte blue = 0;
    byte intensity = 25;
    byte intensity_old = 25;
    int fastness = 300;

    //++++++++++++++++++++++++++++++++++++++++++//
    //                 Index                    //
    //++++++++++++++++++++++++++++++++++++++++++//
    String getPage(){
      String page = "<!DOCTYPE HTML>";
      page += "";
      page += "";
      page += "<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0 maximum-scale = 1.0, user-scalable=0\">";
      page += "<title>Cartel Led</title>";
      page += "";
      page += "";
      page += "";
      page += "
Página de configuración del Cartel Led
";

      //Formulario para cartel
      page += "<FORM action=\"/\" method=\"post\">";
      page += "Introduzca texto a mostrar:
";
      page += "<input type=\"text\" name=\"texto\" id=\"texto\" value=\"Mickey\">";
      page += "
";
      page += "<input type=\"submit\" value=\"Enviar\">";
      page += "</form>";
      page += "
";
      page += "
";
      page += "
";

      page += "<FORM action=\"/\" method=\"post\">";
      page += "Elija el color:
";
      page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"red\" name=\"red\" value=\"";
      page += red;
      page +="\" class=\"slider\">
";
      page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"green\" name=\"green\" value=\"";
      page += green;
      page +="\" class=\"slider\">
";
      page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"blue\" name=\"blue\" value=\"";
      page += blue;
      page +="\" class=\"slider\">
";
      page += "<input type=\"submit\" value=\"Enviar\">";
      page += "</form>";
      page += "
";
      page += "
";
      page += "
";

      page += "<FORM action=\"/\" method=\"post\">";
      page += "Elija la intensidad :
";
      page += "<input type=\"range\" min=\"10\" max=\"255\" id=\"intensity\" name=\"intensity\" value=\"";
      page += intensity;
      page +="\" class=\"slider\">
";
      page += "<input type=\"submit\" value=\"Enviar\">";
      page += "
";
      page += "
";
      page += "
";

      page += "<FORM action=\"/\" method=\"post\">";
      page += "Elija la rapidez:
";
      page += "<input type=\"range\" min=\"50\" max=\"1000\" id=\"fastness\" name=\"fastness\" value=\"";
      page += fastness;
      page +="\" class=\"slider\">
";
      page += "<input type=\"submit\" value=\"Enviar\">";
      page += "
";
      page += "
";
      page += "
";

      page += "";
      page += "";
      return page;
      }

    //++++++++++++++++++++++++++++++++++++++++++//
    //          REDIRECCIONAMIENTO             //
    //++++++++++++++++++++++++++++++++++++++++++//
    void handleNotFound(){
      server.send(200, "text/html", getPage());
    }

    //++++++++++++++++++++++++++++++++++++++++++//
    //      handleSubmit                        //
    //++++++++++++++++++++++++++++++++++++++++++//
    void handleSubmit(){
      //Text to show
      if (server.hasArg("texto")){
          String texto_string = server.arg("texto");
          int texto_string_size = (texto_string.length()+1);
          texto_string.toCharArray(buf, texto_string_size);
          Serial.print("El texto a mostrar sera:");
          Serial.println(buf);
          }
      //Colors
      if (server.hasArg("red")){
          String red_h = server.arg("red");
          red = red_h.toInt();
          Serial.print("El color rojo cambio a:");
          Serial.println(red);
          }
       if (server.hasArg("green")){
          String green_h = server.arg("green");
          green = green_h.toInt();
          Serial.print("El color verde cambio a:");
          Serial.println(green);
          }
       if (server.hasArg("blue")){
          String blue_h = server.arg("blue");
          blue = blue_h.toInt();
          Serial.print("El color azul cambio a:");
          Serial.println(blue);
          }

      //Intensity
      if (server.hasArg("intensity")){
          String intensity_h = server.arg("intensity");
          intensity = intensity_h.toInt();
          Serial.print("La intensidad cambio a:");
          Serial.println(intensity);
          }

      //Fastness
      if (server.hasArg("fastness")){
          String fastness_h = server.arg("fastness");
          fastness = fastness_h.toInt();
          Serial.print("La intensidad cambio a:");
          Serial.println(fastness);
          }

      server.send(200, "text/plain", getPage());       //Response to the HTTP request
    }

    //++++++++++++++++++++++++++++++++++++++++++//
    //            handleRoot                    //
    //++++++++++++++++++++++++++++++++++++++++++//
    void handleRoot() {
      if (server.args() ) {
        handleSubmit();
        } else {
          server.send(200, "text/html", getPage());
          }
    }

    //++++++++++++++++++++++++++++++++++++++++++++++//
    //        Recoger del puerto serial             //
    //++++++++++++++++++++++++++++++++++++++++++++++//
    //int readline(int readch, char *buffer, int len) {
    //    static int pos = 0;
    //    int rpos;
    //
    //    if (readch > 0) {
    //        switch (readch) {
    //            case '\r': // Ignore CR
    //                break;
    //            case '\n': // Return on new-line
    //                rpos = pos;
    //                pos = 0;  // Reset position index ready for next time
    //                return rpos;
    //            default:
    //                if (pos < len-2) {
    //                    buffer[pos++] = readch;
    //                    buffer[pos] = 0;
    //                }
    //        }
    //    }
    //    return 0;
    //}

    //++++++++++++++++++++++++++++++++++++++++++++++//
    //            SETUP()                           //
    //++++++++++++++++++++++++++++++++++++++++++++++//
    void setup(){
      delay(1000);
      Serial.begin(115200);

      //WiFi initilization part
      Serial.print("Creating AP...");
      WiFi.mode(WIFI_AP);
      WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
      WiFi.softAP("DNSServer CaptivePortal example");

      // if DNSServer is started with "*" for domain name, it will reply with
      // provided IP to all DNS request
      dnsServer.start(DNS_PORT, "*", apIP);

      IPAddress myIP = WiFi.softAPIP();
      Serial.print("AP IP address: ");
      Serial.println(myIP);
      server.on("/", handleRoot);
      server.onNotFound(handleNotFound);

      // if DNSServer is started with "*" for domain name, it will reply with
      // provided IP to all DNS request
      dnsServer.start(DNS_PORT, "*", apIP);

      server.begin();

      //LedStrip initialization part
      FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds[0], leds.Size());
      FastLED.setBrightness(intensity_old);
      FastLED.clear(true);
      delay(500);

      FastLED.showColor(CRGB::White);
      delay(500);
      FastLED.show();

      //Se declara la fuente que se utiliza
      ScrollingMsg.SetFont(MatriseFontData);
      //Se inicializa la matriz
      ScrollingMsg.Init(&leds, leds.Width(), ScrollingMsg.FontHeight() + 1, 0, 0);
    //  ScrollingMsg.SetBackgroundMode(BACKGND_DIMMING, 50);
      //Se introduce el textoque se va a mostrar y su tamanho
    //  ScrollingMsg.SetText((unsigned char *)TxtDemo, sizeof(TxtDemo) - 1);
      //Se declara los colores/efectos con los que se van a mostrar los mensajes
      ScrollingMsg.SetTextColrOptions(COLR_RGB | COLR_SINGLE, red, green, blue);

      //Para organizar el sentido del mensaje como mas convenga
      //Setear la direccion del mensaje
    //  ScrollingMsg.SetScrollDirection(SCROLL_UP);
      //Setear la direccion de las letas
    //  ScrollingMsg.SetTextDirection(CHAR_DOWN);

    }

    //++++++++++++++++++++++++++++++++++++++++++++++//
    //              LOOP                            //
    //++++++++++++++++++++++++++++++++++++++++++++++//
    void loop(){
      dnsServer.processNextRequest();
      server.handleClient();         //Handling of incoming requests

      ScrollingMsg.SetTextColrOptions(COLR_RGB | COLR_SINGLE, red, green, blue);
      FastLED.setBrightness(intensity);

      if (ScrollingMsg.UpdateText() == -1) {
        ScrollingMsg.SetText((unsigned char *)buf, strlen(buf));}
      else {
        FastLED.show();
      delay(fastness);
            }

    //  if (readline(Serial.read(), buf, 200) > 0) {
    //        Serial.print("You entered: >");
    //        Serial.print(buf);
    //        Serial.println("<");
    //    }

      delay(50);
    }

  [1]: https://i.stack.imgur.com/d6GYM.png
  [2]: https://i.stack.imgur.com/piTYz.png
  [3]: https://i.stack.imgur.com/Ii6wr.png

body: You have content type "text/plain" in `handleSubmit()`. Use "text/html".


message:
Reading text from sd card is returning weird characters?

I have an ebook which is converted to a .txt file saved on an sd card which is connected to the arduino. I'm trying to display the words from the book on a 16x2 lcd display on word at a time. It works mostly except when it reads a word that has an apostrophe or a pipe symbol it does not display correctly to the lcd display or the serial output.

For example the word "author's" will be displayed as "authorâs" (edit: there is actually two boxes between the "â" and the s that is not displaying on this forum) on both the lcd display and serial output.

I've spent an entire day now with this one problem hopefully there is a mistake someone can pick up on :/

#include <LiquidCrystal.h>
#include <SPI.h>
#include <SD.h>

const int chipSelect = 53;

const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

char nextChar;
String wordBuffer = "";

void setup() {

  lcd.begin(16, 2);

  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt");

  if (dataFile) {
    while (dataFile.available()) {

      nextChar = dataFile.read();

      if (isWhitespace(nextChar)){

        lcd.print(wordBuffer);

        Serial.println(wordBuffer);

        lcd.display();

        delay(500);

        wordBuffer = "";
        lcd.clear();

      }
      else{

        wordBuffer = wordBuffer + nextChar;
        wordBuffer.trim();
      }

    }
    dataFile.close();
  }

  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
}

void loop() {
}

body:
The text file is not ASCII, it is UTF-8. You will either have to convert it to pure ASCII, or write (or obtain) a conversion routine to approximate the UTF-8 characters using ASCII on the Arduino.

Maybe [this](http://playground.arduino.cc/main/Utf8ascii) can help you.


message:
Two HC05 Bluetooth Bind problem

I succeeded in giving an AT command. My two BL MAC addresses are `21, 13, A03B` and `21, 13, A3E2`.

When I want to connect one to the other I use `AT+BIND=21,13,A3E2`. But then I see `Error(7)`. If I use another BL address from the Internet, it works.

So, why won't my 2 HC05 bind?

body:
The solution is

    AT+BIND=0021,13,00A03B

NB: Here I just added `00` left side and right side digits


message:
Potentiometer reading out letters

My potentiometer reads out t's or u's in my serial.
I believe that my potentiometer is wired correctly.
What am I missing?
Here is my code:

    #include <VarSpeedServo.h>

    VarSpeedServo servo;
    const byte buttonLeft = 2;
    const byte buttonRight = 3;
    const int led = 7;
    const int potentioPin = A0;
    int potentioVal = 0;

    void setup() {
      Serial.begin(9600);
      servo.attach(11);

      // PIN MODES
      pinMode(buttonLeft, INPUT);
      pinMode(buttonRight, INPUT);
      pinMode(led, OUTPUT);

      // INTERRUPT
      attachInterrupt(digitalPinToInterrupt(buttonLeft), turnServo, FALLING);
    }

    void loop() {
      int stateBtnLeft = digitalRead(buttonLeft);
      int stateBtnRight = digitalRead(buttonRight);

      if(stateBtnLeft == 0 && stateBtnRight == 0){
        digitalWrite(led, HIGH);
      } else {
        digitalWrite(led, LOW);
      }
    }

    void turnServo(){
      Serial.println("Button was pushed");
      potentioVal = analogRead(0);
      Serial.write("Servo moving with speed ");
      Serial.write(potentioVal);
      Serial.println("");
      //servo.write(180, potentioVal, true);
      //Serial.write("Reached position of motor");
      //lightLed();
    }

    void lightLed(){
      digitalWrite(led, HIGH);
      delay(2000);
      digitalWrite(led, LOW);
    }

body: You need to use Serial.print instead of Serial.write.


body:
`write()` is a function for binary data. I you want to print the number as text, use `print()` or `println()`.

`Serial.println(potentioVal);`


message:
Is it possible to insert your own routine into the Reset procedure

I'm working with  ATmega328 NANO boards, and I would like to know if it is possible to INSERT my own routine, to be included in the things done during reset, BEFORE any pre-C initialization is done, or any upload of new code occurs. If this is possible, I'd like to know how. I'd want to be able to "install" this routine during setup(). I also would not expect it to work after a power loss. I'm talking about a reset caused by pressing the reset button, uploading code, opening a serial port, or any reset that was NOT caused by a loss of power.

I'm including a simple example sketch illustrating what I would LIKE to do, but it obviously won't do what I want as written, because I do not know the "magic" answer I'm seeking,

I've defined and initialized a global static byte outside of any functions. The setup() simply reads a byte from EEPROM and displays it with Serial.print(), and then stores its value in that global 'number'.  Now notice I created a void(void) function called magic(). It simply increments the global number and stores it in EEPROM. I call it "magic() because what I need to do to call it is unknown. I want some way to "install" magic() during setup(), so that it runs only as part of the reset process, before anything within code or data space is affected. By install, I don't mean just call the function. It should not actually be called unless RESET occurs.   **Whatever "magic" has to be added to make this happen, the proof of the pudding will be that after loading the sketch. every time you press RESET, or even upload the sketch again, the printed number will be different, because it was incremented and saved when reset was pushed.** NOTE: (I just edited some stupid errors here)

    #include <EEPROM.h>

    static uint8_t number =0;

    void setup()
    {
      uint8_t n = EEPROM.read(0);
      Serial.begin(57600);
      Serial.print(n);
      number = n;

      // somehow, install "magic" routine here

    }

    void loop() { }

    void magic(void)
    {
     ++number;
     EEPROM.write(0, &number);
    }

body:
You can check the MCUSR register to see the cause of the reset. In your case you could use:

    if( bit_is_set(MCUSR, EXTRF) )// reset button was pressed
    {
        MCUSR = 0;// clear the reset-flag

        // "magic" routine here

    }


body:
Yes, it is possible. See the [documentation on memory
sections][sections], from the avr-libc manual. For example:

<!-- language-all: lang-c++ -->

    // Run this after initializing the stack pointer and zero_reg, but
    // before initializing the RAM.
    void __attribute__((naked, used, section(".init3"))) magic(void)
    {
        // Whatever...
    }

Note that this runs after both a warm reset and a cold boot. See
Gerben's answer if you want to tell the difference between these two
reset conditions.

Note also that, if you just want some data to be preserved through a
reset, you can put it in the .noinit section, no need to use the EEPROM.

[sections]: https://www.nongnu.org/avr-libc/user-manual/mem_sections.html

------------------------------------------------------------------------

**Edit 1**: In response to the OP's comment, here is a small program
demonstrating the technique. It just quickly blinks the LED three times
early in the program initialization, then three more times, more slowly,
during `setup()`:

    #include <util/delay.h>

    // Blink the LED three times, fast, early in the initialization.
    void __attribute__((naked, used, section(".init3"))) magic(void)
    {
        DDRB |= _BV(PB5);      // pin PB5 = digital 13 as output
        for (int i= 0; i < 6; i++) {
            PINB |= _BV(PB5);  // toggle PB5
            _delay_ms(100);
        }
    }

    // Blink the LED three times, slowly.
    void setup()
    {
        pinMode(13, OUTPUT);
        for (int i = 0; i < 6; i++) {
            delay(300);
            digitalWrite(13, !(i & 1));
        }
    }

    void loop(){}

I tested it on an Uno, and it works.

Note that `magic()` runs _before_ the Arduino core library has been
initialized. At this point, many core function, like `delay()`, do not
work. Any job that is done here should be done low-level, using only
direct port access and avr-libc calls.

**Edit 2**: In the previous version of this answer I forgot the `used`
attribute. It worked with the old Arduino setup I tested with, but not
with the newest IDE. Adding the `used` attribute fixes this.


body:
If you use the latest version (7.0, July 2018) of [Optiboot](https://github.com/Optiboot/optiboot/blob/862e9dd5e86f939cf63846372cfba3818e248f4c/optiboot/bootloaders/optiboot/optiboot.c#L169), you can use the MCUSR register to check the reset cause.

You need to use the latest version because previous versions of the bootloader cleared the MCUSR before starting the sketch (as recommended in §15.9.1 of the ATmega328P datasheet). This was changed in version 7.0 ([a50f47b](https://github.com/Optiboot/optiboot/commit/a50f47b8acf28ea51e72c08914d8811563dcb869#diff-aa6fbd4fbd422af50b97d38d37fe1e1eL482)).

    #include <EEPROM.h>

    static uint8_t ch = MCUSR;

    void setup() {
      MCUSR = 0;
      uint8_t n = EEPROM.read(0);
      Serial.begin(115200);
      Serial.print(n);
      if ((_BV(PORF) & ch) == 0) // not a power on reset
        magic(n);
    }

    void loop() { }

    void magic(uint8_t &number) {
       EEPROM.put(0, ++number);
    }


message:
Arduino SD card cannot write (writes crap files and then I get error)

I am developing a very simple project to measure some temperatures and store them in an SD card. I have a problem trying to write. No matter what I do the SD card always ends up with content like this:

[![enter image description here][1]][1]

And in read only mode. I have formatted it in FAT16, FAT32, in Windows an Ubuntu and always the same. I have changed between two different Arduino UNO boards, two different SD modules connected like this:

[![enter image description here][2]][2]

and extremly simple codes like [this example][3] and I always get the same.

**Detailed example of what I do and what I get**

I have wrote this simple code to test:

    #include <SD.h>
    #define CHIP_SELECT_PIN 10
    /* CIRCUITO ----------------
    * SD card attached to SPI bus as follows:
    * MOSI - pin 11
    * MISO - pin 12
    * CLK - pin 13
    * CS - pin 10. */
    File archivo;
    char cadena[20];
    char c;
    void setup(void) {
    Serial.begin(9600);
    while (!Serial) {;} // Esperar a que se inicialice la comunicacion serial
          while (Serial.read() >= 0) {;} // Limpiar el buffer
    // INICIALIZAR LA MEMORIA ----------------------------------------
    Serial.print("Initializing SD card... ");
    pinMode(CHIP_SELECT_PIN, OUTPUT);
    if (!SD.begin(CHIP_SELECT_PIN)) {
      Serial.println("Unable to initialize. Remove the card.");
      while (1);
    }
    Serial.println("OK!");
    // ABRIR UN ARCHIVO PARA ESCRIBIR --------------------------------
    if (SD.exists("ARCHIVO.TXT")) {
      Serial.println("Deleting existing file with the same name. ");
      SD.remove("ARCHIVO.TXT");
    }
    Serial.print("Creating new file... ");
    if (!(archivo = SD.open("ARCHIVO.TXT", FILE_WRITE))) {
      Serial.println("Unable to create the file. Remove the card.");
      while (1);
    }
    Serial.println("File successfully created. ");
    Serial.print("Send a string to store in the card... ");
    while (Serial.available() == 0); // Nos quedamos esperando a que nos manden el numero
    leerCadena('\n', cadena, 19);
    Serial.print("The following string was received: \" ");
    Serial.print(cadena);
    Serial.println("\"");
    archivo.print(cadena);
    archivo.close();
    Serial.println("The string was successfully stored in the card. ");
    // Lectura de los datos guardados en la memoria ------------
    Serial.print("Preparing to read data in card... ");
    if (!(archivo = SD.open("ARCHIVO.TXT", FILE_READ))) {
      Serial.println("Cannot open file to read. Remove the card. ");
      while(1);
    }
    Serial.print("The string stored in memory is: \"");
    while ((c = archivo.read()) >= 0) {
      Serial.print(c);
    }
    Serial.println("\"");
    archivo.close();
    Serial.println("Remove the card.");
    while(1);
    }
    void loop(void) {}
    void leerCadena (char corte, char* cadena, byte n_bytes) {
      byte n_leidos;
      n_leidos = Serial.readBytesUntil(corte, cadena, n_bytes);
      cadena[n_leidos] = '\0';
      delay(100);
      while (Serial.read() >= 0) {;}
    }

and what I am doing and getting is:

 1. First I format my SD card in FAT32 using Gparted (the same happens if I format it in FAT16 or 32 both in Ubuntu and Windows).
 2. I test the SD card in my computer. [![enter image description here][4]][4] It works perfectly. I can remove it and plug it again and the data is there. Everything OK.
 3. I put the card in the SD slot connected to Arduino and run the above program. What I get through the serial monitor is [![enter image description here][5]][5]
 4. Now I remove the card from Arduino and insert it into my computer. This is its content: [![enter image description here][6]][6] The file "readme.txt" contains the same text as before. The file "ARCHIVO.TXT" is empty. The binary files vary in size, e.g. the second one is 3 GB and fourth one is 774 MB.
 5. Now I try to modify the content in "readme.txt" and I get this: [![enter image description here][7]][7] I cannot delete files either.
 6. I remove the SD card from my computer and insert it again into Ardino. Reset the board and through the serial port I get: [![enter image description here][8]][8]
 7. Now the content of the card seen in the computer is different: [![enter image description here][9]][9] and the file "ARCHIVO.TXT" is not present.
 8. If I put the card again in Arduino and reset the board everything repeats from step number 3. I mean, it creates the file "ARCHIVO.TXT" among with the other strange files, in the next time I put it into Arduino it deletes the file "ARCHIVO.txt", and so on.

If after all this I format the SD card in my computer, we are back in step number 1.

I am about giving up with Arduino and the SD module and go to a Raspberry. But it is much more expensive for this extremly simple task I need to do...

  [1]: https://i.stack.imgur.com/R6LDj.png
  [2]: https://i.stack.imgur.com/WrKe8.png
  [3]: https://www.arduino.cc/en/Tutorial/Datalogger
  [4]: https://i.stack.imgur.com/M30oW.png
  [5]: https://i.stack.imgur.com/R7glr.png
  [6]: https://i.stack.imgur.com/IqSxi.png
  [7]: https://i.stack.imgur.com/3eRmv.png
  [8]: https://i.stack.imgur.com/bbbRA.png
  [9]: https://i.stack.imgur.com/R3eAT.png

body:
-Did you change the CS pin in the code to 10?
-It can be a problem with the SD card, try another and tell us.
-After the "dataFile.close();" put: "if(dataFile)Serial.println("not closed");" and watch the serial monitor window.


body: You have to guarantee that the file.txt is not opened before you shutdown the power or take the SD card off. I recomend you firstly, to do a "for" loop to stop in "X" iterations. If it works, you can put then a push-button in your project to stop any time.


body: The problem was magically solved. I think the cables were the causing this issue. I was using cables of about 15 cm, now changed them to 5 cm and is working perfectly.


body: I had the same problem (using a UNO with the MH-SD module directly connected to the arduino). The module apparently correctly initialised and I could list the files that were already there but when I attempted to create a single blank file ready for reading, a whole bunch of random named files were created many of which were enormous (according to my PC, although it said they all corrupted and couldn't open any of them). And then the card wasn't recognised when I tried using it again and had to be reformatted. I eventually found that one of the wires I was using, specifically the one to GND adjacent to MISO, was faulty. I suspect the length of the cables is irrelevant, I think that user171780 had a faulty cable in the same position.


body: I change voltage from 5V to 3.3V and move GND to the GND pin near the 3.3V. Now I can write and read a text file on a SD card.


body:
I think maybe the problem comes from the SD module you use. I have used the SD module just like you.And I can not write or read data successfully. More seriousely, my card broken and the damage is permanent.This connect is the new SD module I use, and I use successfully. You can dry by yourself.
https://www.qutaojiao.com/8515.html?fbclid=IwAR0T9dFoAOyJhTCSOHeDWQTE_Iuq8l5eGN9ByYth2uPmIyzC2bHLdt0_cKk


message:
Local char* - keeps its value

Sorry for novice question in Arduino, but I'm trying to figure out why `res` is keeping its value when `up_cmd0` is being called again.

for example - if `num=8` in first run and the result is :`up_cmd0_res: 8`, and second run `num=12`, the result is: `up_cmd0_res: 812`

    void up_cmd0(){
      char num[8];
      char *res = "up_cmd0_res:";
      itoa(counter2, num, 10);
      strcat(res ,num);
      client.publish(inTopic,res);

body:
Because you're changing a string literal. These literals are in static memory, so they persist between function calls.
On top of that, changing them results in undefined behaviour.

You're also writing out of the bounds of the string.

My recommendation:

    void up_cmd0(){
      const size_t int_max_digits = floor(log10(pow(2, 8 * sizeof(int) - 1))) + 1;
      char num[int_max_digits + 2]; // max digits + minus sign + null terminator
      const char *str = "up_cmd0_res:";
      char buffer[strlen(str) + sizeof(num)] = {};
      strcat(buffer, str);
      itoa(counter2, num, 10);
      strcat(buffer, num);
      // ...
    }

You shouldn't be using globals to get values from one function to the other (`counter2`), try to pass it as a parameter to the function.


body:
> `char *res = "up_cmd0_res:";`

In principle, `res` should be a `const char *`. Const because it is
pointing to a literal string, and you cannot (ar at least, you are not
supposed to) change a literal string. The compiler should warn you on
that... if you enable compiler warnings.

> `strcat(res ,num);`

This is very wrong. `strcat()` expects as its first argument an pointer
to a _modifyable_ array large enough for the resulting concatenation
(and the terminating `\0`). In other words, you have to allocate enough
room for the whole string, then fill the beginning of the allocated
array with the first substring, then only call `strcat()`:

<!-- language: lang-c++ -->

    char res[24];
    strcpy(res, "up_cmd0_res:");
    strcat(res, num);

What happened is that you initially had, in memory, something like this:

    <----- memory reserved for the string literal ---->
    'u' 'p' '_' 'c' 'm' 'd' '0' '_' 'r' 'e' 's' ':' NUL
     ^-- res

On the first call to `stracat()`, you overwrite the terminating NUL and
end up with

    <----- memory reserved for the string literal ---->
    'u' 'p' '_' 'c' 'm' 'd' '0' '_' 'r' 'e' 's' ':' '8' NUL
     ^-- res

Note that the new terminating NUL is now occupying a byte in memory that
hasn't been allocated for this purpose. You have likely overwritten some
global variable. Next time you call `strcat()`, you again replace the
terminating NUL and continue to overwrite whatever happens to be stored
in this part of the RAM. Expect a crash or program misbehavior.


body:
Only the pointer, `*res`, is a local variable. The string `"up_cmd0_res:"` itself is elsewhere in RAM, stored as a literal and not meant to be modified.

Your strcat() call overwrites (extends) the literal each time you call it - which, by the way means that the growing string will be overwriting something else - whatever was following the string literal in global memory!!

You need to provide a character buffer within your function, large enough to hold "up_cmd0_res:" plus the longest thing you might ever append to it, plus one more byte for the zero-terminator. That buffer should be re-initialized on every function entry, before you append anything to it. Then make the strcat call to append to it. (These two calls will each manage the terminator for you).

The fact that this program didn't crash (or did it?) is only just by happenstance. If you call this function as it is initially written, enough times, your string literal will grow until it overwrites something important and either produces incorrect results (by over-writing some other data, or crashes (by overwriting the stack, especially the current function's return-address).


body:
It is incorrect to `strcat` into a field pointing to a literal. The code below is shorter, easier to understand, and does not corrupt memory:

<!-- language: lang-c++ -->

     char res [20];
     sprintf (res, "up_cmd0_res:%i", counter2);
     client.publish(inTopic,res);

The field `res` needs to be long enough to hold the literal string (which is not modified doing it this way) plus the number you are adding to the end, and a terminating 0x00 byte.

---

> can you please explain what "literal" is?

OK. A literal is when you *literally* put a string into a variable. For example:

    char *res = "up_cmd0_res:";

So `res` isn't pointing to some variable, it is pointing to a **literal string in the code**. Now check this out:

<!-- language: lang-c++ -->

    void setup() {
      Serial.begin (115200);
      char * a = "foo";
      Serial.println (a);
      strcpy (a, "bar");
      Serial.println (a);
      char * b = "foo";
      Serial.println (b);
    }

    void loop()
    {
    }

Are you expecting this code to print:

    foo
    bar
    foo

It should, right?, because the variable `b` contains "foo".

However it actually prints:

    foo
    bar
    bar

This is because the `strcpy` has modified a literal string ("foo") to now contain "bar". The compiler is smart enough to think that every time it sees "foo" in the code it can place a **single** piece of memory with "foo" in it, because it is a literal (and literals don't change). But now you have modified that.

The compiler **does** give a warning:

    /tmp/arduino_modified_sketch_905830/sketch_aug19a.ino:7:12: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
     char * b = "foo";
                ^

Imagine if you were able to change the literal 5 so that every time you added 5 to something it actually added 42? That wouldn't be so great, right?

---

Your code was worse than that, because you didn't just replace a string with something the same length, you used `strcat` which replaces it with something longer.


message:
How can I power a NeoPixel ring and strip through Arduino MKR1000?

I currently have a MKR1000 which is connected to 1 ring with 8 neopixels, 1 strip with 20 neopixels, 1 microwave sensor, 1 speaker, 1 rotary encoder. I am running the NeoPixel positive and negatives through a 220 µF capacitor, and the data pins through 220 Ω resistor.

I am soldering these components onto a board, but currently, when I plug the MKR1000 into my USB it says it's drawing too much power, the Arduino also smokes and I can smell burning, so disconnected straight away.

What am I doing wrong?

body:
The on-board regulator of an Arduino can supply a maximum of 500 mA when connected to USB, and up to 1000 mA when connected to an external power supply (see [Maximum current from Arduino 5V power pins][1]).

If your components are drawing more current than that, then you will need to use an additional separate power supply for the NeoPixel ring - ensuring that the ground lines of the Arduino's supply and the NeoPixel's supply  are connected.

If the Arduino has been smoking then it may already be damaged. Did you see which part was smoking? If it was a capacitor as shown in [Is my Arduino dead?][2], then [this answer][3] may help.

  [1]: https://gr33nonline.wordpress.com/2018/08/16/maximum-current-from-arduino-5v-power-pins/
  [2]: https://arduino.stackexchange.com/questions/54006/is-my-arduino-dead
  [3]: https://arduino.stackexchange.com/questions/54006/is-my-arduino-dead/54010#54010


message:
Looking for light-weight Arduino OLED library that supports text and bitmaps

I'm trying to incorporate a screen into my Arduino code which is quite large already. The Adafruit SSD1306 library is overly large and has a lot of unnecessary things in it. I've found the SSD1306Ascii library which is great because it takes up barely any space, but I really would like to be able to display a bitmap logo on the screen. Does anyone know of a library that is light weight but still supports bitmaps?

Thanks.

body:
This is supposed to be a small implementation. https://github.com/nicoud/Oled

I have not used it, but it does look interesting. You can pick the bits that you need.

https://www.didel.com/OledLib.pdf


message:
esp8266 and arduino pro mini

I have few sensors. Temperature sensor (DHT22), flow rate sensor, rpm optical tachometer sensor and a rgb led.
I want to use adafruit IO to get values of these sensors and change the colour of the led.  Most of the tutorials online use a builtin WiFi module  but I want to do it separately. please guide me how to do it?
I am going to use esp8266 and  arduino nano.

body:
Use tutorial for the esp8266 module to connect to Adafruit IO (MQTT). Then code the exchange of the data between Nano and esp8266 using Serial communication.
(You can test the Serial communication by sending lines to esp8266 from Serial Monitor and of course by showing the prints from the Nano.)

Consider using only esp8266 dev board like Wemos D1 mini or NodeMCU.


message:
How should you predict the battery size required for a project?

I am using an Arduino nano along with an ESP8266.  The nano is connected to an OLED display and a keypad. The ESP8266 uploads the data entered from the keypad onto a server. I wish to make the device portable; i.e. add a battery to it so that it can last for at least 8 hours.

How can I calculate the rating for the LiPo battery to use? I understand that it is very important to know the current rating of the devices in use.

How can I make an approximate guess?

body:
Yes, you need to know the average current draw over the period of an hour (or over a period that you then extrapolate to an hour).  That is the *mAh* (milliamps per hour) that your circuit draws.

It can be hard to calculate the actual current, though, since it is always changing depending on what is actually happening in your system at the time.  So I would suggest picking up a cheap current monitoring USB dongle from eBay / Amazon / Wherever (one with an LCD screen that gives mAh, such as [this one](https://ebay.co.uk/itm/323367365036) and use that to get the total mAh of your system over an hour.

Multiply that mAh by 8 (the number of hours you want it to run for), and that will give you the minimum mAh for your battery. And then add some more as a safety margin, since the capacity of a battery is subject to many things (like temperature, age, etc), and the rated value is only a rough guide.

For instance, if you find your circuit uses on average 387mAh, then a battery of 3600mAh should be adequate.


body: Current consumption is measured in Amperes, battery capacity in specified in Amperes per hour.


message:
Repair Arduino with too much voltage exposure

I have used the 5V pin instead of the Vcc pin to operate some sensors on the Arduino MKR GSM 1400. Altough the operating voltage is 3.3V.Because of that it doesn't work properly anymore, some analog sensor values are clearly wrong and the GSM module works only occasionally. Is there any way to repair this myself or send is somewhere, or should I buy a new one?

body:
Feeding 5 volts into an input most likely cause the protection diode on that input to conduct the 5 volts onto the 3.3 volt supply. That in turn would exceed the voltage on all the 3.3 volt connected parts. Likely to cause more damage than just to the affected input.

The cost of shipping and labour to repair the board would exceed the cost of buying a new replacement board. A repair would require too many parts to be replace. And replacement would be required of even parts that might appear to work because the risk of failure would be high.

Buy a new board and be confident that it will work.