# Question
Title: 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

```

# Answer
> 1 votes
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.

---
Tags: print
---


title: How we can implement the interrupt?

text:
# Question
Title: How we can implement the interrupt?
I want to implement the Interrupt on the Adafruit\_RGBLCDShield Select button to start/stop the data logging?

# Answer
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 and learn how it works.
> 3 votes

---
Tags: adafruit
---


# Question
Title: How close to 5 kHz can I set the PWM frequency on an UNO pin 11?
I'm rebuilding a laser CNC machine and using LaserWeb4 as the control interface and GRBL 1.1 as the low-level interface to the stepper motors, limit switches and the laser. I have all the motion sorted out and am working on the laser control.

*Figure 1. The GRBL 1.1 pinout. Pin 11 is used for spindle (cutter) speed on a milling machine or laser power control on a laser cutter.*

The machine is using a Synrad 48 Series laser module which requires a 5 kHz PWM frequency (page 45 - 46).

The GRBL 1.1 sketch can be configured for a variety of PWM frequencies. See cpu\_map.h.

```
  // Prescaled, 8-bit Fast PWM mode.
  #define SPINDLE_TCCRA_INIT_MASK   ((1<<WGM20) | (1<<WGM21))  // Configures fast PWM mode.
  // #define SPINDLE_TCCRB_INIT_MASK   (1<<CS20)               // Disable prescaler -> 62.5kHz
  // #define SPINDLE_TCCRB_INIT_MASK   (1<<CS21)               // 1/8 prescaler -> 7.8kHz (Used in v0.9)
  // #define SPINDLE_TCCRB_INIT_MASK   ((1<<CS21) | (1<<CS20)) // 1/32 prescaler -> 1.96kHz
  #define SPINDLE_TCCRB_INIT_MASK      (1<<CS22)               // 1/64 prescaler -> 0.98kHz (J-tech laser)

  // NOTE: On the 328p, these must be the same as the SPINDLE_ENABLE settings.
  #define SPINDLE_PWM_DDR     DDRB
  #define SPINDLE_PWM_PORT  PORTB
  #define SPINDLE_PWM_BIT     3    // Uno Digital Pin 11

```

It seems that my options are 62.5 kHz, 7.8 kHz, 1.96 kHz or 0.98 kHz.

Why does it matter? Two excerpts from the Synrad manual:

> Tickle frequencies \[a 'keep-awake' signal at zero power\] lower than 4.5 kHz may compromise laser performance, ..., and stress the RF \[radio frequency\] electronics thereby reducing long term reliability while tickle frequencies greater than 5 kHz may cause unintended lasing.
>
> Because laser output follows PWM input with a rise and fall time constant of ~100 µs, the laser cannot precisely follow Command signal frequencies over t kHz with duty cycles greater than 50%.

Can anyone see a workaround for this within the constraints of the GRBL configuration?

I can only think of a hardware solution to filter the PWM out and run it through another device to convert the analog signal to a 5 kHz PWM.

Many thanks.

# Answer
> 1 votes
No, you cannot have hardware PWM at 5 kHz on pin 11 of an Arduino Uno. The closest you can get is 3.92 kHz. You get that by setting the prescaler to 8 and configuring the timer for phase correct PWM, instead of the fast PWM mode usually used by GRBL. Your options for getting 5 kHz are to use either software PWM or change the pinout.

You can get a quite accurate 5 kHz PWM signal on pins 3, 9 and 10. You can do software PWM at 5 kHz on any pin, but this is prone to have significant jitter, which your laser may well not like.

# Answer
> 1 votes
The simple way, which may interfere with the timing of your other digital outputs: https://playground.arduino.cc/Code/PwmFrequency

Or, if you are willing to put the PWM output on pin 9/10 and manipulate the AVR registers directly:

Digital pins 9 (`OC1A`) and 10 (`OC1B`) are outputs of the AVR 16-bit timer (TIMER1) on 328p. With those you can get a PWM signal at 5.000 kHz, but if you need reliability then an Arduino with external crystal resonator may be needed. You will need to set the registers `TCCR1A`, `TCCR1B` and `OCR1A`,`OCR1B`,`ICR1`,`TIFR1` appropriately, details can be found in the AVR datasheet.

---
Tags: pwm
---


# Question
Title: 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?

# Answer
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 of the RAM.
> 1 votes

---
Tags: attiny, sleep, reset
---


title: Arduino controlled by USB gamepad

text:
# Question
Title: 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?

# Answer
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/
> 1 votes

---
Tags: usb, remote-control
---


title: sending and recieving data from esp8266

text:
# Question
Title: 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?

# Answer
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?
> 1 votes

---
Tags: esp8266
---


title: Second SD not writing

text:
# Question
Title: 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);
}

```

# Answer
> 0 votes
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.

# Answer
> 0 votes
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 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.

---
Tags: arduino-ide, sd-card
---


title: Can you help me trim my code?

text:
# Question
Title: 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();
}

```

# Answer
> 3 votes
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...

# Answer
> 4 votes
The documentation for the MCUFRIEND\_kbv project has a file describing how to use.

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.

# Answer
> 1 votes
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 link to an article about it in the Arduino Playground, to get you started.

# Answer
> 0 votes
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

---
Tags: arduino-uno, bluetooth, shields, hc-05, memory-usage
---


# Question
Title: 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.

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!)

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><html><head><title>CaptivePortal</title></head><body>"
  "<h1>Hello World!</h1><p>This is a captive portal example. All requests will "
  "be redirected here.</p></body></html>";

//++++++++++++++++++++++++++++++++++++++++++++++//
//                  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 += "<html>";
  page += "<head>";
  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 += "<style>";
  page += "\"body { background-color: #808080; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }\"";
  page += "</style>";
  page += "</head>";
  page += "<body>";
  page += "<h1>Página de configuración del Cartel Led </h1>";

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

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

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

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

  page += "</body>";
  page += "</html>";
  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);
}

```

# Answer
> 1 votes
You have content type "text/plain" in `handleSubmit()`. Use "text/html".

---
Tags: esp8266, web-server, http, ws2812
---


# Question
Title: 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, one 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 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 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();
  } else {
    // if the file isn't open, pop up an error:
    Serial.println("error opening datalog.txt");
  }
}

void loop() {
}

```

# Answer
> 3 votes
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 can help you.

---
Tags: lcd, sd-card, display
---


title: Potentiometer reading out letters

text:
# Question
Title: 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);
}

```

# Answer
You need to use Serial.print instead of Serial.write.
> 4 votes

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

`Serial.println(potentioVal);`
> 3 votes

---
Tags: serial, potentiometer
---


# Question
Title: 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();
  }
}

```

# Answer
> -1 votes
I didn't see a problem in the code - but maybe I overlooked something.

Maybe your code is not the problem but your hardware. Did you make sure the input is connected to GND if it the button is not pressed?

**Notes and Warnings**

**If the pin isn’t connected to anything, digitalRead() can return either HIGH or LOW (and this can change randomly).**

https://www.arduino.cc/reference/en/language/functions/digital-io/digitalread/

I suggest you use serial to show the value of buttonState after this line

```
buttonState = digitalRead(buttonPin);

```

Maybe it is not what you expect it to be.

# Answer
> 1 votes
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

# Answer
> 0 votes
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();
  }
}

```

---
Tags: arduino-uno, button, display, switch
---


# Question
Title: 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);
}

```

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

```
// 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.

---

**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.
> 2 votes

# Answer
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

}

```
> 1 votes

# Answer
If you use the latest version (7.0, July 2018) of Optiboot, 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).

```
#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);
}

```
> 0 votes

---
Tags: reset, vector
---


title: Local char* - keeps its value

text:
# Question
Title: 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);

```

# Answer
> 7 votes
> `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()`:

```
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.

# Answer
> 6 votes
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).

# Answer
> 4 votes
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:

```
 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:

```
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.

# Answer
> 2 votes
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.

---
Tags: string
---


# Question
Title: 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?

# Answer
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).

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?, then this answer may help.
> 1 votes

---
Tags: arduino-ide, arduino-nano, capacitors
---


title: rfid_default_keys check with RC522

text:
# Question
Title: rfid_default_keys check with RC522
I just received a RC522 board and since i am new to RFID, I tried out some examples from "Arduino RFID Library for MFRC522". Here's one of them **rfid\_default\_keys**

```
/*
 * ----------------------------------------------------------------------------
 * This is a MFRC522 library example; see https://github.com/miguelbalboa/rfid
 * for further details and other examples.
 *
 * NOTE: The library file MFRC522.h has a lot of useful info. Please read it.
 *
 * Released into the public domain.
 * ----------------------------------------------------------------------------
 * Example sketch/program which will try the most used default keys listed in
 * https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys to dump the
 * block 0 of a MIFARE RFID card using a RFID-RC522 reader.
 *
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno           Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 *
 */

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

// Number of known default keys (hard-coded)
// NOTE: Synchronize the NR_KNOWN_KEYS define with the defaultKeys[] array
#define NR_KNOWN_KEYS   8
// Known keys, see: https://code.google.com/p/mfcuk/wiki/MifareClassicDefaultKeys
byte knownKeys[NR_KNOWN_KEYS][MFRC522::MF_KEY_SIZE] =  {
    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // FF FF FF FF FF FF = factory default
    {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}, // A0 A1 A2 A3 A4 A5
    {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5}, // B0 B1 B2 B3 B4 B5
    {0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd}, // 4D 3A 99 C3 51 DD
    {0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a}, // 1A 98 2C 7E 45 9A
    {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}, // D3 F7 D3 F7 D3 F7
    {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, // AA BB CC DD EE FF
    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}  // 00 00 00 00 00 00
};

/*
 * Initialize.
 */
void setup() {
    Serial.begin(9600);         // Initialize serial communications with the PC
    while (!Serial);            // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();                // Init SPI bus
    mfrc522.PCD_Init();         // Init MFRC522 card
    Serial.println(F("Try the most used default keys to print block 0 of a MIFARE PICC."));
}

/*
 * Helper routine to dump a byte array as hex values to Serial.
 */
void dump_byte_array(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        Serial.print(buffer[i], HEX);
    }
}

/*
 * Try using the PICC (the tag/card) with the given key to access block 0.
 * On success, it will show the key details, and dump the block data on Serial.
 *
 * @return true when the given key worked, false otherwise.
 */
boolean try_key(MFRC522::MIFARE_Key *key)
{
    boolean result = false;
    byte buffer[18];
    byte block = 0;
    byte status;

    // Serial.println(F("Authenticating using key A..."));
    status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, key, &(mfrc522.uid));
    if (status != MFRC522::STATUS_OK) {
        // Serial.print(F("PCD_Authenticate() failed: "));
        // Serial.println(mfrc522.GetStatusCodeName(status));
        return false;
    }

    // Read block
    byte byteCount = sizeof(buffer);
    status = mfrc522.MIFARE_Read(block, buffer, &byteCount);
    if (status != MFRC522::STATUS_OK) {
        // Serial.print(F("MIFARE_Read() failed: "));
        // Serial.println(mfrc522.GetStatusCodeName(status));
    }
    else {
        // Successful read
        result = true;
        Serial.print(F("Success with key:"));
        dump_byte_array((*key).keyByte, MFRC522::MF_KEY_SIZE);
        Serial.println();
        // Dump block data
        Serial.print(F("Block ")); Serial.print(block); Serial.print(F(":"));
        dump_byte_array(buffer, 16);
        Serial.println();
    }
    Serial.println();

    mfrc522.PICC_HaltA();       // Halt PICC
    mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD
    return result;
}

/*
 * Main loop.
 */
void loop() {
    // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial())
        return;

    // Show some details of the PICC (that is: the tag/card)
    Serial.print(F("Card UID:"));
    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println();
    Serial.print(F("PICC type: "));
    byte piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));

    // Try the known default keys
    MFRC522::MIFARE_Key key;
    for (byte k = 0; k < NR_KNOWN_KEYS; k++) {
        // Copy the known key into the MIFARE_Key structure
        for (byte i = 0; i < MFRC522::MF_KEY_SIZE; i++) {
            key.keyByte[i] = knownKeys[k][i];
        }
        // Try the key
        if (try_key(&key)) {
            // Found and reported on the key and block,
            // no need to try other keys for this PICC
            break;
        }
    }
}

```

So i modified the code to see exactly what is happening there and here is my output:

Everything looks fine, right ? So i tried to modify it again by adding some more stuff to the *knownKeys* array but it looks like that only the first key is used in the actual authentication. Here's an output for the same card but i moved `{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // FF FF FF FF FF FF = factory default` to the end of that array.

So.. as you can see even if it used the right key, nothing happened. For the solution i tried few things but without a success. Thanks in advance for answering.

# Answer
> 1 votes
Call:

```
if ( ! mfrc522.PICC_IsNewCardPresent()) return false;
if ( ! mfrc522.PICC_ReadCardSerial()) return false;

```

before every re-authenticate.

---

According to NXPs application note (AN1304) regarding MIFARE CLASSIC cards (page 24/25):

> Each time an Authentication operation, a Read operation or a Write operation fails, the MIFARE Classic or MIFARE Plus remains silent and it does not respond anymore to any commands. In this situation in order to continue the NDEF Detection Procedure the MIFARE Classic or MIFARE Plus needs to be re-activated and selected.

1. `PICC_IsNewCardPresent` resets modulation parameters and performs RequestA - activates the PICC (Card).
2. `PICC_ReadCardSerial` basically just performs Select - with anti-collision algorithm.

In case there are multiple cards present it would be better to manually call `mfrc522.PICC_Select(&mfrc522.uid, mfrc522.uid.size * 8)`, the second argument tells it that you already know all of the bits for UID, thus it will select the same PICC that was selected previously.

# Answer
> 2 votes
Based on some experimenting, I believe the 1st key is skipped for one of two reasons:

1. If you follow the code flow, in `loop()`, `PICC_IsNewCardPresent()` and `PICC_ReadCardSerial()` called. If a "new" card/tag is present, then `try_key()` is called which calls `PICC_IsNewCardPresent()` \[and `PICC_ReadCardSerial()`\] again. Since the card/tag is not "new", `PICC_IsNewCardPresent()` returns false. or
2. It appears that if the correct key is the default of all 0xFF's, then a call to `PCD_Authenticate()` will fail.

I'm still working a new version of rfid\_default\_keys to fix the problem.

# Answer
> 0 votes
If called:

```
if ( ! mfrc522.PICC_IsNewCardPresent()) return false;
if ( ! mfrc522.PICC_ReadCardSerial()) return false;

```

before every re-authenticate. You will skip the FIRST item in array `knownKeys` so you will never test the default key `FF FF FF FF FF FF`.

---
Tags: arduino-uno, programming, rfid
---


title: esp8266 and arduino pro mini

text:
# Question
Title: 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.

# Answer
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.
> 2 votes

---
Tags: esp8266, arduino-nano
---


# Question
Title: 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?

# Answer
> 1 votes
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.

---
Tags: power
---


# Question
Title: 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.

# Answer
> 1 votes
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

---
Tags: i2c, library, display
---


# Question
Title: data integrity when interrupts are too fast
I have an encoder that fires ~54000 interruptions per second. This is way too fast for my arduino uno. But I'm trying to see what I can get from it anyway. For science.

```
unsigned long tickACount = 0;
unsigned long tickBCount = 0;

void myInterrupt(){
  tickACount++;
  tickBCount++;
}

```

Then in my main loop, every second I print `tickACount` and `tickBCount`. I can see my arduino is able to handle only about 2050 interrupts per second. No surprise here.

What surprises me, is that `tickACount` and `tickBCount` have different values! `tickBCount` is consistently higher that `tickACount`.

Ok now I switch them to volatile. And according to the documentation, volatile only makes sense for 8bit values. The counts will eventually overflow but it doesn't really matter. I just want to see if those two variables are still different.

```
volatile uint8 tickACount = 0;
volatile uint8 tickBCount = 0;

void myInterrupt(){
  tickACount++;
  tickBCount++;
}

```

The result is that the two values are still different. Also, wrapping them into some `ATOMIC` macro does not help.

From what I read, interrupts cannot be interrupted. And beside, if my interrupt was aborted midway, then `tickACount` would be higher than `tickBCount`, not the other way around.

Therefore, what can be the explanation for those two variables to be different?

Thank you for any idea!

# Answer
> 54000 interruptions per second \[...\] is way too fast for my arduino uno

Your test is probably flawed. My Uno does handle that interrupt rate with no issues. See my test code below.

> my arduino is able to handle only about 2050 interrupts per second

You are probably doing something wrong, like blocking interrupts for too long, or using a library that does so.

> What surprises me, is that `tickACount` and `tickBCount` have different values!

As previously stated in comments, this is not the case. Instead, the counters have been incremented while you were printing them.

> And according to the documentation, volatile only makes sense for 8bit values.

Either the documentation is grossly wrong, or (most likely) you have misread it.

> From what I read, interrupts cannot be interrupted.

This is indeed the default behavior. You could change it, by issuing `interrupts()` within the interrupt handler, or by declaring an ISR as

```
ISR(XXX_vect, ISR_NOBLOCK)
{
    ...
}

```

but that is seldom done.

Below is my test code. I used Timer 2 to generate a square wave on pin 3, which is both a PWM pin (OC2B) and an interrupt pin (INT1). The PWM frequency is about 54.054 kHz.

```
const uint32_t PRINT_PERIOD = 1e6;  // print counts every second

struct TickCounts {
    uint32_t tickA;
    uint32_t tickB;
};

volatile TickCounts rawCounts;

void myInterrupt() {
    rawCounts.tickA++;
    rawCounts.tickB++;
}

// Atomically read both counts.
static TickCounts getCounts() {
    TickCounts counts;
    noInterrupts();
    counts.tickA = rawCounts.tickA;
    counts.tickB = rawCounts.tickB;
    interrupts();
    return counts;
}

void setup() {
    // PWM at 54 kHz on OC2B = PD3 = INT1
    DDRD  |= _BV(PD3);    // pin PD3 as output
    OCR2A  = 37 - 1;      // period = 37 * 0.5 us = 18.5 us
    OCR2B  = 37/2 - 1;    // duty cycle ~ 50%
    TCCR2A = _BV(COM2B1)  // non-inverting PWM on OC2B
           | _BV(WGM20)   // mode 7: fast PWM, TOP = OCR2A
           | _BV(WGM21);  // ditto
    TCCR2B = _BV(WGM22)   // ditto
           | _BV(CS21);   // clock at F_CPU/8 = 2 MHz

    Serial.begin(9600);
    attachInterrupt(1, myInterrupt, RISING);
}

void loop() {
    static uint32_t last_time_printed;
    if (micros() - last_time_printed >= PRINT_PERIOD) {
        last_time_printed += PRINT_PERIOD;
        TickCounts counts = getCounts();
        Serial.print(counts.tickA);
        Serial.print(" ");
        Serial.println(counts.tickB);
    }
}

```

And here is the output:

```
54053 54053
108107 108107
162161 162161
216215 216215
270269 270269
324324 324324
378377 378377
432431 432431
486485 486485
540539 540539
...

```
> 3 votes

---
Tags: interrupt
---


title: Ethernet nodemcu

text:
# Question
Title: Ethernet nodemcu
I have a question that might be a #noob question but I am wondering if there is a board similar to the nodemcu in size that runs arduino code but instead can use ethernet to connect to the network instead of the wifi? I have already seen the connections to use one of the pins and such to connect that way but I am looking to see if there is a board that has the rj45 connection on it already.

# Answer
> 0 votes
I don't think you'll find a single off-the-shelf product. The closest I have managed to come to it is a Teensy 3.2 plus a WIZ820io & Micro SD Card Adaptor and a WIZ850io module, all stacked together. Footprint-wise it's around the same as (or smaller than) many ESP8266-based boards - however it's considerably chunkier when all combined:

# Answer
> -1 votes
Yes one does exist that I know of. It's called the EtherTen and is made by an Australian company called Freetronics.

It uses the ATMega328P microcontroller that is used on the Arduino Uno. It is 100% Arduino compatible with onboard (RJ45 wired) Ethernet.

It can be purchased from Freetronics.com.au or from Roboshop.com.

Freetronics provides a number of documents and resources on the page linked above.

---
Tags: ethernet, nodemcu, home-automation, iot
---


title: PMS5003 Serial Output Data to SD Issues

text:
# Question
Title: PMS5003 Serial Output Data to SD Issues
I'm trying to save the output of an air quality sensor to a SD card, but I'm having a few issues.

The sensor I'm using is a Plantower PMS5003 which puts out its data via serial. I've heavily tweaked the example sketch from Adafruit (here) as I'd like to use the Low Power library to sleep the unit, take a sample and note the time, write it to SD, then return to sleep.

I am getting the timestamp written no issue, but the data is coming out repeated as below:

```
22:13:10 - 34,55,61
22:13:18 - 34,55,61
22:13:27 - 34,55,61
22:13:36 - 34,55,61
22:13:44 - 34,55,61
22:13:53 - 34,55,61
22:14:1 - 34,55,61
22:14:10 - 34,55,61
22:14:18 - 34,55,61
22:14:27 - 34,55,61
22:14:35 - 34,55,61
22:14:44 - 34,55,61

```

The 8s timer appears to be working fine, but the repetition of data has me confused. I've tried adding delays and the like in case it was a lack of data but when I run that example sketch it comes screaming in over serial.

I also ditched using the software serial as I couldn't get it to stop messing with the low power library, it wouldn't ever sleep.

That and any general advice on the sketch is appreciated, it seems like its not the best way to accomplish this.

```
#include "LowPower.h"
#include <SdFat.h>
#include "RTClib.h"
#include <Wire.h>

SdFat SD;
RTC_DS3231 rtc;

File test;
String tString = "";
String sString = "";

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

  pinMode(10, OUTPUT);

  if (!rtc.begin()) while (1);

  if (!SD.begin(10)) while (1);
}

struct pms5003data {
  uint16_t framelen;
  uint16_t pm10_standard, pm25_standard, pm100_standard;
  uint16_t pm10_env, pm25_env, pm100_env;
  uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
  uint16_t unused;
  uint16_t checksum;
};

struct pms5003data data;

void loop() {
  //LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART0_OFF, TWI_OFF);
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

  DateTime now = rtc.now();
  test = SD.open("test.txt", FILE_WRITE);

  tString = String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second()) + " - ";

  readPMSdata(&Serial);
  sString = String(data.pm10_standard) + "," + String(data.pm25_standard) + "," + String(data.pm100_standard);

if (test) {
  test.print(tString);
  test.println(sString);
  test.close();

  delay(250);
}
}

boolean readPMSdata(Stream *s) {
  if (! s->available()) {
    return false;
  }

  // Read a byte at a time until we get to the special '0x42' start-byte
  if (s->peek() != 0x42) {
    s->read();
    return false;
  }

  // Now read all 32 bytes
  if (s->available() < 32) {
    return false;
  }

  uint8_t buffer[32];
  uint16_t sum = 0;
  s->readBytes(buffer, 32);

  // get checksum ready
  for (uint8_t i = 0; i < 30; i++) {
    sum += buffer[i];
  }

  //debugging
  for (uint8_t i = 2; i < 32; i++) {
    Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
  }
  Serial.println();

  // The data comes in endian'd, this solves it so it works on all platforms
  uint16_t buffer_u16[15];
  for (uint8_t i = 0; i < 15; i++) {
    buffer_u16[i] = buffer[2 + i * 2 + 1];
    buffer_u16[i] += (buffer[2 + i * 2] << 8);
  }

  // put it into a nice struct :)
  memcpy((void *)&data, (void *)buffer_u16, 30);

  if (sum != data.checksum) {
    Serial.println("Checksum failure");
    return false;
  }
  // success!
  return true;
}

```

# Answer
There is a mismatch in the code.
The Arduino `loop` function assumes that `readPMSdata` needs to be called just once for valid data but the function `readPMSdata` itself assumes that it will be called over and over again until a enough bytes are received and are valid.

The solution is to let the Arduino `loop` call `readPMSdata` over and over again, until it has valid data. It returns `true` when it has valid data, so that can be used in a `if` statement.
This might cause troubles with the rest of the code in the `loop`. The `delay(250);` may no longer be used and I don't know the best place to go into sleep mode. Therefor I removed the powerdown.

```
void loop() {
  if( readPMSdata(&Serial))        // call it many times to collect data
  {
    // there is valid data from the sensor
    DateTime now = rtc.now();
    test = SD.open("test.txt", FILE_WRITE);

    tString = String(now.hour()) + ":" + String(now.minute()) + ":" + String(now.second()) + " - ";

    sString = String(data.pm10_standard) + "," + String(data.pm25_standard) + "," + String(data.pm100_standard);

    if (test) {
      test.print(tString);
      test.println(sString);
      test.close();
  }
}

```
> 1 votes

---
Tags: serial, sd
---


# Question
Title: Can't create an array of type const char*
I have something being returned as a const char\* and would like to save it to an array.

I've tried this:

```
const char* book[amtBooks] = "";

```

and get this error:

```
error: array must be initialized with a brace-enclosed initializer

```

# Answer
> 2 votes
* `const char* book[amtBooks]` is an array of pointers.
* `""` is an array of chars (with only a NUL character).

You can initialize an array of chars with an array of chars:

```
const char foo[] = "hello";

```

You can also initialize a pointer to char with an array of chars:

```
const char *bar = "good bye";

```

this works because of the “decay to pointer” feature of C and C++.

But initializing an array of pointers with an array of chars simply does not make sense. An array of pointers to char could be initialized as

```
const char *book[] = {"hello", "good bye"};

```

---
Tags: array, data-type
---


# Question
Title: Reading names of files on sd card returning odd file names
When trying to read the file names from an sd card some are being returned with a ~1 and cutting off the full file name.

```
Initializing SD card...initialization done.
TEST.TXT        402
UNTITL~1        0
HELLOT~1        49
DATALOG.TXT     562288
ALONGN~1        0
done!

```

Is there any way I get the full file name of each file?

The code for this is from here: https://www.arduino.cc/en/Tutorial/Listfiles

# Answer
> 3 votes
That's the way the FAT filesystem works.

On the page you link to there's a link to a page on SDCardNotes.

> FAT file systems have a limitation when it comes to naming conventions. You must use the 8.3 format, so that file names look like “NAME001.EXT”, where “NAME001” is an 8 character or fewer string, and “EXT” is a 3 character extension. People commonly use the extensions .TXT and .LOG. It is possible to have a shorter file name (for example, mydata.txt, or time.log), but you cannot use longer file names.

When you wrote the files to the file system you were on an OS that supports longer filenames. When filenames are too long there's an 8.3 name created automatically with chunks of characters removed and replaced with `~`.

# Answer
> 1 votes
You have long filenames on your SD card. The SD library is too primitive to know what they are.

I'd suggest switching to FatFS (here is one implementation) which has the option of using long filenames.

---
Tags: sd-card
---


# Question
Title: Does a pin (input pin Arduino) still float when connected to GPIO on RPI?
I am currently testing my application on an Arduino, and I experience floating pin issues. My program reads the pin status of input pins, which are configured as

```
pinMode(5, INPUT);
digitalWrite(5, HIGH);

```

but still they tend to float sometimes.

Will this be solved when I connect the pin directly to a GPIO pin on a RPI? Specifically when the application running on the RPI is not active yet (thus the GPIO pin will not actively high or low yet).

Both the PI and and Arduino will be powered at the same time, but the application on the Arduino will be active much faster than the application on the RPI.

So my concern is that while the RPI is still booting and loading the app, the Arduino might still 'suffer' from floating pins, which gives undesirable output to the things my Arduino controls.

Or, will the fact that the RPI and Arduino both have power, share the same ground, will result in a stable input on the Arduino?

PS: not an expert on electronics, hence the question. I can't test this yet as I don't have all the hardware of this project.

# Answer
You need to enable the internal pull-up resistors which are designed to prevent undefined input states on unconnected inputs.

Change

```
pinMode(5, INPUT);

```

to

```
pinMode(5, INPUT_PULLUP);

```

For more information on this see Arduino digital pins.
> 3 votes

# Answer
> Does a pin (input pin arduino) still float when connected to GPIO on RPI?

Yes. Connecting one floating pin to another floating pin doesn't make either one of them stop floating. If anything, the fact that there's now a long wire connecting them (and picking up RF) will probably make the behavior of the pins even less predictable.
> 1 votes

---
Tags: pins, input
---