title: IR Remote control on UNO

text:
# Question
Title: IR Remote control on UNO
I am working on IR remote code run on Arduino UNO I can already get it work. but when I press the button and hold, the output is sent with the same value repeatly. So,the quesion is how can I do to make it send out only one output while I press and hold the button.

this is my code

```
#include <IRremote.h>
int RECV_PIN = 5;
#define PB  3392264773 // button code
#define VUP  3476004267 // button code
#define VDN  2998643817 // button code
#define SRC  387001607 // button code
#define MUTE  305976139 // button code

IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {

    if (results.value == PB) {
      Serial.println("Power");
    }
    if (results.value == VUP) {
      Serial.println("Vol UP");
    }
    if (results.value == VDN) {
      Serial.println("Vol Down");
    }
    if (results.value == SRC) {
      Serial.println("Select");
    }
    if (results.value == MUTE) {
      Serial.println("Mute");
    }

    irrecv.resume(); // Receive the next value

  }
}

```

and this is output when I press and hold the button

```
Power
Power
Power
Power
Power
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP

```

Thank you for all answers. Tanwa

# Answer
> 1 votes
by adapting chrisl's idea, I got it done. the code is here.

```
#include <IRremote.h>
int RECV_PIN = 5;
#define PB  3392264773 // button code
#define VUP  3476004267 // button code
#define VDN  2998643817 // button code
#define SRC  387001607 // button code
#define MUTE  305976139 // button code

int pre_p  = 0;
int pre_src  = 0;
int pre_mu  = 0;

//trigger
int p = 0;
int src = 0;
int mu = 0;

int pw = 0;
int s = 0;
int m = 0;

IRrecv irrecv(RECV_PIN);
decode_results results;

unsigned long previous_timestamp;
unsigned long check_timestamp;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {

        if (results.value == PB){
           p = 1;
          if(p != pre_p){
           pw = !pw;
            //Serial.println(pw);
              Serial.println("pw");
              Serial.println(pw);
          }
        }
      if (results.value == VUP) {
        Serial.println("Vol UP");
      }
      if (results.value == VDN) {
        Serial.println("Vol Down");
      }
      if (results.value == SRC) {
        src = 1;
          if(src != pre_src){
           s = !s;
          Serial.println("s");
          Serial.println(s);
          //Serial.println("Select");
          }
      }
      if (results.value == MUTE) {
        mu = 1;
          if(mu != pre_mu){
           m = !m;
          //Serial.println("Mute");
          Serial.println("mu");
          Serial.println(m);
          }
      }

    irrecv.resume(); // Receive the next value
    pre_p = p;
    pre_src  = src;
    pre_mu  = mu;

    p=0;
    src = 0;
    mu = 0;

    previous_timestamp = millis();

  }
    if(millis() - previous_timestamp > 200){
    pre_p = 0;
    pre_src  = 0;
    pre_mu  = 0;
  }
}

```

# Answer
> 0 votes
As noted in the comments, you cannot change what the remote is sending. Though I guess, that it would be OK for you to just react to the first occurence of a specific value send consecutively. For that you first need to check the time between these consecutive values send, when holding the button down. That (plus a small margin) will be the threshold to recognize multiple distinct button presses. Note: Depending on the rate, that the remote is sending when holding a button, this might mean, that you cannot distinguish between holding a button and pressing it multiple times in a fast pace.

First define a variable to hold the previous decode results and a timestamp for saving when it arrived:

```
decode_results previous_results;
unsigned long previous_timestamp;

```

On receiving a new value via IR, check if the new value is the same as in `previous_results`. If yes, don't execute the code checking for the actual value. If no, then update `previous_results` with the new value and act upon the actual received value. Then set the timestamp to the current `millis()` value and resume receiving.

```
if (irrecv.decode(&results)) {
  if(results != previous_results){
    previous_results = results;
    if (results.value == PB) {
      Serial.println("Power");
    }
    ....
  }
  previous_timestamp = millis();
  irrecv.resume(); // Receive the next value
}

```

Now you need to reset the `previous_results` variable after a specific time threshold, so that consecutive presses on the same button can be registered. Add a corresponding `millis()` statement to your `loop()` function:

```
if(millis() - previous_timestamp > 500){
  previous_results = 0;
}

```

Note: The value of 500ms is just a wild guess. As described at the start, you need to find that value yourself, fitting to your remote. Play a bit with this value until you are satisfied.

All in all something like this:

```
#include <IRremote.h>
int RECV_PIN = 5;
#define PB  3392264773 // button code
#define VUP  3476004267 // button code
#define VDN  2998643817 // button code
#define SRC  387001607 // button code
#define MUTE  305976139 // button code

IRrecv irrecv(RECV_PIN);
decode_results results;
decode_results previous_results;
unsigned long previous_timestamp;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {
    if(results != previous_results){
      previous_results = results;
      if (results.value == PB) {
        Serial.println("Power");
      }
      if (results.value == VUP) {
        Serial.println("Vol UP");
      }
      if (results.value == VDN) {
        Serial.println("Vol Down");
      }
      if (results.value == SRC) {
        Serial.println("Select");
      }
      if (results.value == MUTE) {
        Serial.println("Mute");
      }
    }
    previous_timestamp = millis();
    irrecv.resume(); // Receive the next value
  }

  if(millis() - previous_timestamp > 500){
    previous_results = 0;
  }
}

```

Note: I have not tested this code in any way.

---
Tags: arduino-uno, ir, remote-control
---


# Question
Title: ESP32 SocketIO Client is not connecting to Flask-SocketIO Server
I'm trying to connect a ESP32 client using `SocketIO` with a `Flask-SocketIO` server and it's not getting connected. The server uses SSL. The local server address is `https://192.168.1.137:3000`.Is the `https` causing issue here?

The following is the output from the ESP32 in the serial monitor. Note that esp32 successfully connects to the wifi.

```
> ["myEvent",{"now":95506}]
> [IOc] Disconnected!
> [IOc] Disconnected!
> [IOc] Disconnected!
> ...

```

Esp32 code:

```
/*
* WebSocketClientSocketIOack.ino
*/

#include <Arduino.h>

#include <WiFi.h>
#include <WiFiMulti.h>
#include <WiFiClientSecure.h>

#include <ArduinoJson.h>

#include <WebSocketsClient.h>
#include <SocketIOclient.h>

WiFiMulti WiFiMulti;
SocketIOclient socketIO;

#define USE_SERIAL Serial

void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
    switch(type) {
        case sIOtype_DISCONNECT:
            USE_SERIAL.printf("[IOc] Disconnected!\n");
            break;
        case sIOtype_CONNECT:
            USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);

            // join default namespace (no auto join in Socket.IO V3)
            socketIO.send(sIOtype_CONNECT, "/");
            break;
        case sIOtype_EVENT:
        {
            char * sptr = NULL;
            int id = strtol((char *)payload, &sptr, 10);
            USE_SERIAL.printf("[IOc] get event: %s id: %d\n", payload, id);
            if(id) {
                payload = (uint8_t *)sptr;
            }
            DynamicJsonDocument doc(1024);
            DeserializationError error = deserializeJson(doc, payload, length);
            if(error) {
                USE_SERIAL.print(F("deserializeJson() failed: "));
                USE_SERIAL.println(error.c_str());
                return;
            }

            String eventName = doc[0];
            USE_SERIAL.printf("[IOc] event name: %s\n", eventName.c_str());

            // Message Includes a ID for a ACK (callback)
            if(id) {
                // creat JSON message for Socket.IO (ack)
                DynamicJsonDocument docOut(1024);
                JsonArray array = docOut.to<JsonArray>();

                // add payload (parameters) for the ack (callback function)
                JsonObject param1 = array.createNestedObject();
                param1["now"] = millis();

                // JSON to String (serializion)
                String output;
                output += id;
                serializeJson(docOut, output);

                // Send event
                socketIO.send(sIOtype_ACK, output);
            }
        }
            break;
        case sIOtype_ACK:
            USE_SERIAL.printf("[IOc] get ack: %u\n", length);
            break;
        case sIOtype_ERROR:
            USE_SERIAL.printf("[IOc] get error: %u\n", length);
            break;
        case sIOtype_BINARY_EVENT:
            USE_SERIAL.printf("[IOc] get binary: %u\n", length);
            break;
        case sIOtype_BINARY_ACK:
            USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
            break;
    }
}

void setup() {
    //USE_SERIAL.begin(921600);
    USE_SERIAL.begin(115200);

    //Serial.setDebugOutput(true);
    USE_SERIAL.setDebugOutput(true);

    // USE_SERIAL.println();
    // USE_SERIAL.println();
    // USE_SERIAL.println();

      // for(uint8_t t = 4; t > 0; t--) {
      //     USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
      //     USE_SERIAL.flush();
      //     delay(1000);
      // }

    WiFiMulti.addAP("ssid", "mypass");

    //WiFi.disconnect();
    while(WiFiMulti.run() != WL_CONNECTED) {
        delay(100);
    }

    String ip = WiFi.localIP().toString();
    USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());

    // server address, port and URL
    socketIO.begin("192.168.1.137", 3000, "/socket.io/?EIO=4");

    // event handler
    socketIO.onEvent(socketIOEvent);
}

unsigned long messageTimestamp = 0;
void loop() {
    socketIO.loop();

    uint64_t now = millis();

    if(now - messageTimestamp > 2000) {
        messageTimestamp = now;

        // creat JSON message for Socket.IO (event)
        DynamicJsonDocument doc(1024);
        JsonArray array = doc.to<JsonArray>();

        // add event name
        // Hint: socket.on('event_name', ....
        array.add("myEvent");

        // add payload (parameters) for the event
        JsonObject param1 = array.createNestedObject();
        param1["now"] = (uint32_t) now;

        // JSON to String (serializion)
        String output;
        serializeJson(doc, output);

        // Send event
        socketIO.sendEVENT(output);

        // Print JSON for debugging
        USE_SERIAL.println(output);
    }
}

```

Server code (Removed unrelated parts):

```
from flask import Flask, render_template, Blueprint, current_app, request, session, url_for, render_template
from flask_socketio import SocketIO, emit

from threading import Thread
from queue import Queue
import logging

loggerPath = baseUrl + "logs/appLog.log"
os.makedirs(os.path.dirname(loggerPath), exist_ok=True)
with open(loggerPath, "a") as f:
    logging.basicConfig( level=logging.INFO,
        # format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
        format='%(levelname)s - %(message)s',
        filename=loggerPath
    )
bp = Blueprint('audio', __name__, static_folder='static',
            template_folder='templates')
app = Flask(__name__)

async_mode = "threading"

socketio = SocketIO(app, cors_allowed_origins="*", async_mode=async_mode)

@socketio.on('myEvent')
def test_connect(data):
    logging.info("receiving")

def runApp():
    try:
        certificatePath = os.getenv('BASE_URL')+"SSL/"
        key = certificatePath+"localhost.key"
        certificate = certificatePath+"localhost.crt"
        context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
        context.load_cert_chain(certificate, key)
        ip = socket.gethostbyname(socket.gethostname())
        socketio.run(app, host=ip, port=3000,ssl_context=context)
    except Exception as e:
        logging.error("Exception occurred in: "+__file__, exc_info=True)

q = Queue()
t = Thread(target=wrapper, args=(q, runApp), daemon=True)
t.start()

```

# Answer
This is version Socketio issue,I have successfully connected . This installed version Werkzeug 2.0.0 Flask 2.3.3 Flask-SocketIO 4.3.1 python-engineio 3.13.2 python-socketio 4.6.0
> 0 votes

---
Tags: c++, esp32, python, websocket
---


title: Multiple TFT's not displaying

text:
# Question
Title: Multiple TFT's not displaying
I am trying to connect about 5 TFT's to my Arduino Uno and I got to the point of hooking two of them up without any issues. However, after a code upload, they stopped working. I then took all the code out and tested each in isolation and they still function. However, together only one of them displays data. The TFT's I am using are the ST7789v2 found here. https://www.waveshare.com/wiki/1.69inch\_LCD\_Module#Hardware\_Connection\_3

I have wired them up according to the schematic with "all" pins being shared except the CS pin. Each display has its own.

The code looks like this;

```
#include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h>

#define TFT_CS1 10
#define TFT_CS2 3

#define TFT_RST        8 // Screens shared
#define TFT_DC         7 // Screens shared
#define TFT_BACKLIGHT  9 // Backlight for all screens

Adafruit_ST7789 tftHour1 = Adafruit_ST7789(TFT_CS1, TFT_DC, TFT_RST);
Adafruit_ST7789 tftHour2 = Adafruit_ST7789(TFT_CS2, TFT_DC, TFT_RST);

Adafruit_ST7789 setupScreen (Adafruit_ST7789 tft){
  tft.init(240, 280);
  tft.fillScreen(ST77XX_BLACK);
  return tft;
}

void setup(void) {
  tftHour1 = setupScreen(tftHour1);
  tftHour2 = setupScreen(tftHour2);
}

void loop(){
  tftHour1.print("1");
  tftHour2.print("2");
}

```

When this executes, display 2 shows output but display 1 does not. Weirdly if I take the CS from display 1 and pop it into the same line on the breadboard as CS2, and then put it back into its original position, display 1 and 2 seem to work. But only till the next power cycle or upload.

Also oddly, setting the colour of each screen works even if one is blue and the other is say green. Both change to their respective colours. But when I try to write text to them, only one of them has text.

If I comment the code for tftHour2, then tftHour1 starts showing text. If I swap the setup code for ftfHour1 and tftHour2, then the display that is last to init, is the one that shows the text and the other stays blank.

Like I said, I had all this working and then a simple font change upload and it all stopped working.

Any help on this is really appreciated.

I should mention that I am a programmer and very new to electronics so please keep it simple.

#**Update**. If I have separate RST pins then it works. But I need 5 screen and will run out of pins in that case. Is there a way to get around that?

# Answer
According to the data sheet, the RST signal is accepted without an active CS, so when sharing this signal, **all** displays are reset if you initialize just one of them. That explains the behavior you observe.

You found the solution: Do not share the RST signal in all instances of `Adafruit_ST7789`.

---

Now you worry about the needed number of pins, and that is indeed an issue.

One possible solution is to use a decoder that takes *n* inputs to activate 1 of 2n outputs, like this:

simulate this circuit – Schematic created using CircuitLab

To control 5 RST lines you will need only 3 pins. Use a binary value to select one of the unused outputs to deactivate all RST lines.

The same is true of the CS lines.

However, the library in use does not support this kind of control. Therefore, I'm afraid that you need to consider another Arduino model with more pins.

---

As a work-around, you might want to try this alternative:

Assign the same Arduino pin to all instances of `Adafruit_ST7789`, as in your first attempt. But do not connect it to the RST inputs of the displays. Leave the Arduino pin unconnected.

Instead, use another Arduino pin and connect that to the displays. Then during initialization, reset all displays with your own code. See the data sheet for correct levels and timing.

Or try to connect the RST inputs of all displays to VCC, as they may work without an explicit hardware reset just fine.

---

In a comment you brought up the idea of using a multiplexer.

Without any other change, you would need the selection signals as additional pins to the multiple CS pins, in your case 3 more.

Instead you can also share the CS signal in the same way:

simulate this circuit

It is very important that you use multiplexers that output the inactive level as required by the displays on not selected outputs!

Even now you should instantiate as many `Adafruit_ST7789` as you have displays, because each instance most probably stores internal information necessary for its correct working. But you can use the same pins on all of them.

Before you call any method of an instance, switch the multiplexers to the associated display.

To be sure that all data is completely transmitted, you might need a small delay after the called method. Perhaps the called method already blocks until all data is completely transmitted. You might try to read the library's source to learn more.
> 1 votes

---
Tags: adafruit, tft
---


# Question
Title: How to add one JsonDocument to another in ArduinoJson
I'm utilizing this json library: https://arduinojson.org/

I am attempting to write a function that creates a response object, and wraps an already built json document:

```
    void sendResponse(
            ResponseType state,
            JsonDocument *response
    ) {
        DynamicJsonDocument doc(256);

        doc[F("state")] = responseTypeFromEnum(state);
        doc[F("response")] = response; //breaks; how to do?

        this->sendJson(&doc);
    }

```

This fails of course, and I don't see a great solution anywhere...

I know I could use `createNestedObject()`, but this seems to require re-creating the given json object by hand? This would be a sub-optimal case.

Is there a way to easily wrap an existing JsonDocument in another?

Looking to take

```
{
  "some": "other document"
}

```

And wrap it like

```
{
  "state":"OK"
  "response": {
    "some": "other document"
  }
}

```

# Answer
You can add a `JsonDocument` inside another one, but you must pass the document by value, not by pointer. Since you receive a pointer, you need to dereference it before trying to assign:

```
doc[F("response")] = *response;

```

**Node 1**: you could avoid this problem by passing `response` by reference, like so:

```
void sendResponse(ResponseType state, const JsonDocument &response) {
  DynamicJsonDocument doc(256);

  doc[F("state")] = responseTypeFromEnum(state);
  doc[F("response")] = response;

  this->sendJson(doc);
}

```

**Node 2**: calling the assignment operator (`=`) causes a deep copy of the `response` document. You could avoid this copy by calling `shallowCopy()` instead:

```
doc[F("response")].shallowCopy(response);

```

**Node 3**: unfortunately `shallowCopy()` is unavailable on ArduinoJson 7.
> 0 votes

---
Tags: programming, json
---


# Question
Title: Why Arduino IDE is brignging wrong board name for ESP32 S3
I am designing a pcb for ESP32 S3 wroom-1 for testing pins which are safe to use.

My PCB look like this:

I program ESP32 S3 via USB interface gpio19 "D-" gpio20 "D+". When I plug in my usb, Arduino ide brings wrong name for my Esp32 board. By the way I use USB TYPE C. Everyday it gives different names. Correct one is "ESP32S3 DEV MODULE".

**How can I set it to select the correct module automatically on Arduino Ide** as ESP32S3 Dev Module?

WRONG 1

WRONG 2

WRONG 3

same board different names. interesting

# Answer
After an Arduino IDE update 2.2, something was solved, yesterday (30,08,2023).

There is a new edit button appearing on the board selection menu and then Arduino ide recognises esp32 even after plugging out and in again.
> 1 votes

# Answer
You can just force Arduino IDE to recognise your board by locating your *Boards Configuration File*, putting in your VID and PID values, repackage and host the configurations and Point the Arduino IDE to your custom board manager URL.

On my MacBook device I have used `ioreg -p IOUSB -l` after plugging in a device and copy the idVendor, idProduct properties. These are the VID and PID values. On Windows you may open Device Manager, look under the Ports (COM & LPT), right click on your board (it might appear as a COM port) and choose "properties", go to "details" menu, and there from the dropdown menu, select "Hardware Ids". you should see values like VID\_XXXX&PID\_YYYY. these are your VID and PID. on Linux you may just use "lsusb" and find the vendor ID and PID there.

After finding those you must go to ESP32 board package directory and find boards.txt (https://github.com/espressif/arduino-esp32/blob/master/boards.txt). Find the line that starts with `esp32s3.name=ESP32S3 Dev Module`. There you must modify the PID and VID values with your actual VID and PID values that you collected as mentioned above. Replace `0xXXXX` with your VID and `0xYYYY` with your PID.

After modifying, you'll need to compress the entire board package directory into a ZIP archive. Make sure the directory structure remains intact so that the Arduino IDE can recognize and install it correctly.

Then you can create a new repository on GitHub, upload the ZIP archive to this repository, then click on the ZIP file inside the repository, then click the "Download" button. Copy the link.

Now you must go to the Arduino IDE, go to `file` -\> `preferences`. in the "Additional Boards Manager URLs" field, click on the icon on the right to open a window where you can insert new lines. Add the direct link to your ZIP file and click OK. Go to Tools -\> Board -\> Boards Manager. then search for ESP32. your custom package should appear in the list. Click "Install". after it installs you are good to go.

**VERY IMPORTANT EDIT**: after investigating this issue a little more I have came to realisation that so called "random board names" that show up all have the same VID and PID values. The problem was not the incorrect VID and PID values for your board, **the problem was that a bunch of other boards also have the same VID and PID values**. A simple yet effective fix would be to assign random names to all the other ones than the one you want to use. Just edit the

```
adafruit_qtpy_esp32c3.vid.0=0x303a

adafruit_qtpy_esp32c3.pid.0=0x1001

```

lines for every board other than what you want to use. But never forget to change this text file if you ever start doing long-run development with one of the other boards. Or the other boards (such as u-blox NORA-W10 s3" won't be auto detected.
> 2 votes

---
Tags: arduino-ide, esp32, esp32-s3
---


# Question
Title: ESP32 struggling to trigger relay module consistently
I'm working with a 4-channel, 5 V relay module and an ESP32 which operates on 3.3 V.

The setup seemed to work well initially but I have started experiencing some inconsistencies. One of the four relays is working perfectly fine, but the other three are not triggering as they should.

Here are the symptoms:

* The LEDs on the non-working relays do light up when a signal is sent from the ESP32, indicating some form of communication.
* There is no audible 'click' sound from these relays when they are supposed to trigger. I noticed that if I gently tap the relay casing, the relay will sometimes trigger, and I can hear it closing.

I had previously thought that I might have fried my first relay module, so I replaced it, but the issue reappeared after a few days.

Any guidance would be greatly appreciated as I'm at a loss here.

# Answer
So it turns out that esp32 boards can actually output 5v alongside with 3.3v output pin, You just have to use the VN pin which is used for powering the board when not connected through USB, this is not what the pin is intended for and also might cause some problems and you cannot upload code to the board when VIN pin is connected but so far it works perfectly and outputs consistent 5V that triggers the relays just fine.

Obviously, I was just looking for a solution no matter what risks it imposed, can anyone with a deeper understanding of this topic explain why the power input pin can also work as output and why is this not a feature that comes with esp32 boards
> 0 votes

---
Tags: esp32, relay, voltage-level, electronics
---


# Question
Title: How to refresh an iframe in a page made with Espasyncwebserver
So, I have this page on esp8266:

```
  controlserver.on("/UDEL", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", htmltd);
  });

```

`htmltd`  is a string, generated by a function and it contains some forms, and they run in iframe tag,

```
<FORM action="/process" method="post" id="config" target="iframe">

</form>

<iframe style="visibility: hidden;" src="http://" )+local_IPstr+"/UDEL"  name="iframe"></iframe>

```

and processed by:

```
controlserver.on("/process", HTTP_POST, [](AsyncWebServerRequest *request) {
.
.
.
request->send(200, "text/html", HTML_CSS_STYLING + "<script>alert(\" Deleted \")</script>");
.
.
.
});

```

They work perfectly fine, and after clicking on submit button the page shows an alert, and it must be reloaded, because the submitted form must be removed from the page. it happens when I reload the page manually. but I want it to happen automatically after each form submission. it tried many ways like :

```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Reload iFrame</title>
  </head>
  <body>
    <iframe src="https://www.w3schools.com" id="myIframe"></iframe>

  <input onclick="reloadIframe()"  type="button" value="Click me">

    <script>
      function reloadIframe() {
        var iframe = document.getElementById("myIframe");
        iframe.contentWindow.location.reload();
      }
    </script>
  </body>
</html>

```

but it doesn't work in esp8266.

# Answer
From my understanding, your intention is to automatically reload the main page (which contains the form and the iframe) after submitting the form. but the challenge is that the form submits inside the iframe so when you send a response to the iframe, it won't directly impact the main page.

I believe you could use a small trick to work this problem around.

1- After successfully processing the form data inside the iframe, send back a script that communicates with the parent window (the main page) and instructs it to reload

2- In the main page, listen to the received message and then reload.

Here is how to implement the proposed solution:

On your ESP8266 route handler, send a script in the response to post a message to the parent window after processing the form:

```
controlserver.on("/process", HTTP_POST, [](AsyncWebServerRequest *request) {
    //add your processing code
    String response = HTML_CSS_STYLING +
                      "<script>"
                      "window.parent.postMessage('reloadPage', '*');"
                      "</script>";
    request->send(200, "text/html", response);
});

```

window.parent.postMessage will send "reloadPage" string from iframe to parent window. And on your main page (the page that contains the iframe), listen for this message and reload the entire page when the message is received:

```
<FORM action="/process" method="post" id="config" target="iframe">
    <!-- form field here -->
</form>

<iframe style="visibility: hidden;" src="http://"+local_IPstr+"/UDEL" name="iframe"></iframe>

<script>
    // listen for messages from iframes
    window.addEventListener('message', function(event) {
        // Await reloadPage message
        if(event.data === 'reloadPage') {
            location.reload();
        }
    });
</script>

```

Btw instead of using an iframe, you could use AJAX to submit the form so that you get a response directly from the server and refresh the page using `location.reload()`. This way you can submit form data (or retrieve data) without refreshing the entire page. Only the necessary parts of the page updates.

I hope that this helps, if not, please inform me.
> 1 votes

---
Tags: esp8266
---


title: ArduinoJson reading `null` from Serial

text:
# Question
Title: ArduinoJson reading `null` from Serial
I have a setup that reads from serial when I sense that there is something to be read (and always assume that what is sent to the arduino is valid json):

```
void setup(){
    Serial.begin(9600);
    while (!Serial) continue;
}

void loop() {

    if(Serial.available()){
        StaticJsonDocument<256> doc;

        deserializeJson(doc, Serial);

        serializeJson(doc, Serial);
        Serial.println();
    }
}

```

Given the following input from ArduinoIDE's serial monitor (Set to `newline` setting, `9600` baud):

```
{"hello": "world"}

```

This produces the following:

```
{"hello": "world"}
null

```

I have two questions:

* Is this setup correct/ how I should be waiting and retrieving json from serial?
* Why the additional `null` input? Looks like there is something still in the serial buffer even after the first iteration?
* How to detect the second case where the resulting document gets re-serialized as `null`? Comparing to `0`, `NULL`, and `nullptr` seem to not work Figured this one out, found out about `DeserializationError`

Upon utilizing `DeserializationError`, looks like the `null` parsing had an error of `EmptyInput`

# Answer
> 1 votes
As observed on your `serial console` settings, it mentions both **newline** and **9600 baud**. Let's break this down:

### **Issue with Serial Communication**

1. **Partial Payloads**: You are currently assuming that when `Serial.available()` returns `true`, the entire JSON payload has been received. However, due to the nature of serial communication (especially at 9600 baud), data can arrive in fragmented chunks. Invoking `deserializeJson()` on a partial JSON payload can result in incomplete or corrupted data.
2. **End-of-Message Ambiguity**: Lacking a definitive end-of-message marker makes it challenging to discern when a complete JSON payload has been received. For instance, when sending `{"hello": "world"}` from the Arduino IDE's serial monitor, it automatically appends a newline (or a carriage return based on your configuration). This newline is then misinterpreted as another JSON payload, leading to the undesired `null` output.

### **How you can solve this:**

1. **Use a Delimiter**: Choose a specific character or sequence to act as an end-of-message delimiter. The newline character (`\n`) is a typical choice, especially if data is exclusively sent from the Arduino IDE's serial monitor. Nevertheless, if you anticipate newlines within your JSON data, you might consider another distinct character, like `#`.
2. **Read Until Delimiter**: Adjust your code to continuously read characters from the serial port until the chosen delimiter is encountered. Upon receipt of the entire message, it can then be parsed.

### **Code Example**

Here's a sample code employing the newline character as a delimiter:

```
const int maxBuffer = 256;
char serialBuffer[maxBuffer];
int bufferPos = 0;

void setup() {
    Serial.begin(9600);
    while (!Serial) continue;
}

void loop() {
    if (Serial.available()) {
        char inChar = Serial.read();

        if (inChar == '\n') {  // EOM
            serialBuffer[bufferPos] = '\0';
            processMessage(serialBuffer);
            bufferPos = 0;  // Reset buffer pos
        } else if (bufferPos < maxBuffer - 1) {  // Avoid buffer overflow
            serialBuffer[bufferPos++] = inChar;
        }
    }
}

void processMessage(char* message) {
    StaticJsonDocument<256> doc;

    DeserializationError error = deserializeJson(doc, message);

    if (error) {
        Serial.println("Failed to parse JSON");
    } else {
        serializeJson(doc, Serial);
        Serial.println();
    }
}

```

This way you ensure the entirety of message is parsed and received and therefore avoiding unwanted `null` outputs.

I hope this helps ^\_^

---
Tags: serial, programming, json
---


# Question
Title: Using Internal Timer Interrupt to Read Analog Sensor
I'm having difficultly using an internal timer interrupt with my Arduino Nano to properly capture a specific value from a linear potentiometer and then instantly stopping the actuator.

I basically have the wiper of a linear potentiometer connected to the end of a linear actuator. The actuator extends/retracts via a L298N module being controlled by a Nano. From where its positioned, the potentiometer reads around "80" when the actuator is fully extended, and around "25" when fully retracted. I'm entering numbers via the serial monitor to prompt the actuator to move up or down, these numbers are being stored in the Nano's EEPROM.

My interrupt seems not to work while the actuator is in motion. For example, if I set the interrupt to stop the motor when the potentiometer reads "50", it just skips past this number without stopping the actuator. But if I set the interrupt to stop the motor when the potentiometer reads the minimum or maximum (where the actuator is currently located before activation), the actuator correctly doesn't extract or retract. I would think my interrupt is fast enough at 8Khz, so I feel there is something else prohibiting the actuator from stopping at a specific value between the max and min.

The my current code is below, any help would be much appreciated.

```
    //timer2 will interrupt at 8kHz

    #include <EEPROM.h>
    #define EEPROM_SIZE

    long number;
    long x;

    int toggle=0;
    int old_x=0;

    const int linPot = A1;

    int MotorSpeed=255;

    int enA = 9;
    int in1 = 8;
    int in2 = 7;

    int currentPosition;

    enum {IdleState, UpState, DownState} State;

    void setup(){

      Serial.begin(9600);

      number = EEPROM.read(0);

      x=number;

      pinMode(enA, OUTPUT);
      pinMode(in1, OUTPUT);
      pinMode(in2, OUTPUT);

      State = IdleState;

    //cli();//stop interrupts

    //set timer2 interrupt at 8kHz
      TCCR2A = 0;// set entire TCCR2A register to 0
      TCCR2B = 0;// same for TCCR2B
      TCNT2  = 0;//initialize counter value to 0
      // set compare match register for 8khz increments
      OCR2A = 249;// = (16*10^6) / (8000*8) - 1 (must be <256)
      // turn on CTC mode
      TCCR2A |= (1 << WGM21);
      // Set CS21 bit for 8 prescaler
      TCCR2B |= (1 << CS21);
      // enable timer compare interrupt
      TIMSK2 |= (1 << OCIE2A);

    sei();//allow interrupts

    }//end setup

    ISR(TIMER2_COMPA_vect){//timer1 interrupt 8kHz
    //generates pulse wave of frequency 8kHz/2 = 4kHz

    if(currentPosition==50){

      HALT();

    }

    }

    void loop(){

    if ((Serial.available()&&toggle==0)){

            x=Serial.parseInt();
            old_x=x;
            toggle=1;
          }

          if((Serial.available())&&(toggle==1)&&(Serial.parseInt()!=old_x)){
              toggle=0;
          }

            if((toggle==1)&&(Serial.parseInt()==0)){
              toggle=0;
          }

          if(x>78){
            x=78;
          }

           if(x<0){
            x=0;
          }

        EEPROM.write(0, x);
        Serial.print("X :");
        Serial.println(x);

        int data = analogRead(linPot);
        currentPosition = map(data, 0, 1023, 0, 100);
        Serial.print("Potentiometer at ");
        Serial.print(currentPosition);
        Serial.println("%");

        long difference = currentPosition-x;
        Serial.print("Difference :");
        Serial.println(difference);

    if(difference>0){

        State = UpState;

    }

    if(difference>0){

       State = DownState;
    }

    if(difference==0){

       State = IdleState;
    }

     switch (State) {

                   case IdleState:
                   Serial.println("Idle State");
                    HALT();
                    if((currentPosition-number)<0){
                     State = UpState;
                    }
                    if((currentPosition-number)>0){
                     State = DownState;
                    }
                    break;

                  case UpState:
                  Serial.println("Up State");
                    //Need to move down
                    DOWN();
                    if((currentPosition-number)>0){
                     State = DownState;
                    }
                    if((currentPosition-number)==0){
                     State = IdleState;
                    }
                    break;

                  case DownState:
                  Serial.println("Down State");
                    //Need to move up
                    UP();
                    if((currentPosition-number)<0){
                     State = UpState;
                    }
                    if((currentPosition-number)==0){
                     State = IdleState;
                    }
                    break;

     }

    }

    void DOWN(){
        analogWrite(enA, MotorSpeed);
        digitalWrite(in1, HIGH);
        digitalWrite(in2, LOW);
      }

    void UP() {
        analogWrite(enA, MotorSpeed);
        digitalWrite(in1, LOW);
        digitalWrite(in2, HIGH);

      }

    void HALT () {
        digitalWrite(in1, LOW);
        digitalWrite(in2, LOW);
    }

```

# Answer
> 1 votes
First, read Nick Gammon's answer: all his points are perfectly valid. He notes that the serial prints can be quite slow. And indeed, as I counted the characters, I find that the prints should take *at least* 54 ms per loop iteration. This is really very slow. In addition to this, the calls to `parseInt()` can be much slower yet, especially considering that one of them is not conditioned on `Serial.available()`.

Currently, the code that takes care of reading the potentiometer and stopping the actuator looks like this:

```
int currentPosition;

// Triggered every 125 µs.
ISR(TIMER2_COMPA_vect) {
    if (currentPosition == 50) HALT();
}

void loop() {
    // Potentially extremely slow code...
    currentPosition = map(analogRead(linPot), 0, 1023, 0, 100);
    // Definitely very slow code: takes at least 54 ms.
}

```

This is reading the potentiometer *at best* every 54 ms, and potentially much more slowly. On every read, `currentPosition` is updated. In parallel, the value of `currentPosition` is being tested every 125 µs.

Note that there is really no point in testing `currentPosition` that often. Once the value has been tested, testing it again before it is updated serves no purpose. Your code would actually be a tiny bit faster if you test the value right after updating it:

```
void loop() {
    // Potentially extremely slow code...
    currentPosition = map(analogRead(linPot), 0, 1023, 0, 100);
    if (currentPosition >= 50) HALT();
    // Definitely very slow code: takes at least 54 ms.
}

```

Note that I changed the equality test to an inequality test, for a reason explained in Nick Gammon's answer.

You still have the problem that the loop is very slow. If you want the potentiometer to be tested more frequently, you have several options.

1. The bad option: do it in the interrupt handler:

```
// Triggered every 125 µs.
ISR(TIMER2_COMPA_vect) {
    currentPosition = map(analogRead(linPot), 0, 1023, 0, 100);
    if (currentPosition >= 50) HALT();
}

```

This is a bad option because `analogRead()` takes at least 112 µs, which means that the ISR will eat 98.6% of the CPU cycles. You could make this work kind of reasonably if you lower the interrupt frequency to something like 1 kHz or below. Still, such a long ISR is not really good practice.
2. The better option: make loop non-blocking:

```
void loop() {
    // Non-blocking, very fast code.
    currentPosition = map(analogRead(linPot), 0, 1023, 0, 100);
    if (currentPosition >= 50) HALT();
    // More very fast code.
}

```

To read the serial port in a non-blocking way, see Reading Serial on the Arduino. For writing to the serial port in a non-blocking way, simply refrain to print very frequently.
3. The hard option: configure the ADC to read continuously.

You can program the ADC in “self-running mode”: it will then take a reading every 104 µs. You can program it to also deliver an interrupt every time a new reading is available: you can test the reading in this interrupt handler. This will give you the best possible response time:

```
void setup() {
    // Set the ADC to free running mode.
    // Enable the ADC interrupt.
}

volatile int raw_adc_reading;

// Triggered on every fresh ADC reading.
ISR(ADC_vect) {
    raw_adc_reading = ADC;
    if (raw_adc_reading >= RAW_THRESHOLD) STOP();
}

```

Note that I prefer to test the raw reading rather than the converted one. This is because `map()` is slow (it involves a long division) and an ISR should ideally be as fast as possible.

You will have to dig into the MCU datasheet to learn how to configure the ADC in free running mode.

# Answer
> 0 votes
For one thing, `currentPosition` is not declared `volatile` so the compiler may be keeping that value in a register, which is not consulted inside the ISR.

I'm also concerned about all the serial prints at 9600 baud (quite slow) which may make the position skip from 49 to 51 while you are busy printing values.

Comparing to be exactly equal in order to do something is always fraught.

---

```
   x=Serial.parseInt();
    old_x=x;
    toggle=1;
  }

  if((Serial.available())&&(toggle==1)&&(Serial.parseInt()!=old_x)){
      toggle=0;
  }

    if((toggle==1)&&(Serial.parseInt()==0)){
      toggle=0;
  }

```

Are you expecting three integers from serial?

---
Tags: arduino-nano, motor, interrupt, timers, potentiometer
---


# Question
Title: Arduino MKR wifi 1010 ssl certificate protection
I'm using Arduino IDE v2.1.1 and Arduino MKR wifi 1010. Everything works fine and at this moment I have a need to protect the wifi connection with ssl certificate. I have generated the ssl certificate using the openssl tool and now I have following files that needs to be set in the controller:

* ca.crt
* client.crt
* client.key

how can I set these three files to the MKR wifi 1010 to enable the SSL certificate protected communication? I couldn't find the tutorial or example on the internet.

let me explain how I do that at the moment. I do have a valid self-signed CA certificate and I'm trying to establish a SSL / TLS connection using the CA sertificate only. This is my code which doesn't work unfortunately:

```
#include <WiFiNINA.h>
#include <ArduinoJson.h>
#include <ArduinoMqttClient.h>
#include <ArduinoBearSSL.h>
#include <ArduinoECCX08.h>
#include "secrets.h"

char wifiSsid[] = SECRET_WiFi_SSID;
char wifiPass[] = SECRET_WiFi_PASS;
char mqttUserId[] = MQTT_USERID;
char mqttPass[] = MQTT_PASS;
int status = WL_IDLE_STATUS;
const char* rootCAcertificate  = \
"-----BEGIN CERTIFICATE-----\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
"-----END CERTIFICATE-----\n";

bool dev_debug_mode = IS_DEBUG;

WiFiClient    wifiClient;         // Used for the TCP socket connection
BearSSLClient bearSslClient(wifiClient); // Used for SSL/TLS connection, integrates with ECCX08
MqttClient    mqttClient(bearSslClient); // Used for MQTT protocol usage

const char mqttBroker[] = MQTT_BROKER_HOST;
int mqttPort = 8883;

const char deviceRegisterTopic[] = "device/register";

//set interval for sending the Observation (the measurement from the sensor) messages (milliseconds)
const long interval = 3000;

unsigned long previousMillis = 0;

bool deviceIsRegistered = false;

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (dev_debug_mode && !Serial) {
    ; // wait for serial port to connect. Needed for native USB port only - development mode. It has to be removed when releasing to live!!!
  }

  // Check the crypto chip module presence (needed for BearSSL)
  if (!ECCX08.begin()) {
    Serial.println("No ECCX08 present!");
    while (1);
  }

  bearSslClient.setEccSlot(0, rootCAcertificate); // inserting a certificate into the slot 0 (zero)

  // ================ SSL SETUP ================
  // Set a callback to get the current time
  // (used to validate the servers certificate)
  ArduinoBearSSL.onGetTime(getTime);

  // attempt to connect to the Wifi network
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to network: ");
    Serial.println(wifiSsid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(wifiSsid, wifiPass);

    Serial.print("Attempt status: ");
    Serial.println(status);

    if(status != WL_CONNECTED) {
      // waiting 10 seconds before trying to connect if it is needed:
      delay(10000);
    }
  }

  // WiFi network connection established! sending some messages to the console
  Serial.println("You're connected to the network");

  Serial.print("Attempting to connect to the MQTT broker: ");
  Serial.println(mqttBroker);
  Serial.println(mqttPort);

  mqttClient.setId(mqttUserId);

  // adding first level of proptection using MQTT broker username and password
  mqttClient.setUsernamePassword(mqttUserId, mqttPass);

  delay(30000);
  while (!mqttClient.connect(mqttBroker, mqttPort)) {
    Serial.print("MQTT connection failed! Error code = ");
    Serial.println(mqttClient.connectError());
    delay(10000);
  }

  // MQTT broker connection established! sending some messages to the console
  Serial.println("You're connected to the MQTT broker!");
  Serial.println();
}

void loop() {

  // call poll() regularly to allow the library to send MQTT keep alive which
  // avoids being disconnected by the broker
  mqttClient.poll();

  // if this current device is not registered yet, registering the device for the first time
  if(!deviceIsRegistered) {
    Serial.print("Sending Device Register message to topic: ");
    Serial.println(deviceRegisterTopic);
    // DO SOMETHING
  }

  unsigned long currentMillis = millis();

  // sending the actual measurement data to the FHIR Server with some time interval, like few seconds. To be defined later.
  if (currentMillis - previousMillis >= interval) {

    // save the last time a message was sent
    previousMillis = currentMillis;

    Serial.println();
  }
}

// ================================== Auxiliary functions ===================================
unsigned long getTime() {
   Serial.print("Current WiFi time:");
   Serial.println(WiFi.getTime());
  // Get the current time from the WiFi module
  return WiFi.getTime();
}

```

in the code above, I'm using the **BearSSLClient** and the certificate is set manually (I prefer this way as it is more transparent for me) `bearSslClient.setEccSlot(0, certificate);` \- this is how the certificate is set. Also I do the following call: ArduinoBearSSL.onGetTime(getTime); - to get the proper time. The CA certificate is validated using the **openssl** tool. It is a valid self-signed root certificate. Please, any help is much appreciated. I'm really confused as it should work since the certificate is a valid self-signed certificate and it is confirmed and verified using the **openssl** tool. When something should work but it doesnt work and I don't have any details except the **-2** error message it makes me feel completely crazy ((((

@b1n3t thank's dude for your help. I appreaciate that. Let me start with one thing, I do software developent for more than 16 years, but I was working with hardware like microcontrollers and i8086 architecture based hardware more than 10 years ago. I was never investigating the SSL / TLS issues deeply. Now, I go through your questions one by one: yes, I'm sure that Arduino's internal clock is accurate because I have configured myself a mutual TLS connection to the AWS (Amazon) MQTT broker with this clock engaged and everything works fine. The private key might not be properly stored within the ECC608, this might be the issue because I'm not 100% sure that I've done that right. Yes, I have verified that mosquitto MQTT broker's domain and port are accessible from the device, because it connnects successfully without the mutual TLS. I can send message back anf force from the device to the mosquitto MQTT broker server without mutual TLS and without SSL. Yes, I have configured the linux server to enable the 8883 for external connection. I have used the MQTT Explorer tool to establish a mutual TLS connection using the CA root certificate, client and server certificates from another physical device over my LAN network, everything works smoothly, it connects with the CA and client certificate to the MQTT broker server and I can send and receive messages. All is good here. Let me capture the logs and get back. Broker is configured to trust the CA, however all the certificates are self-signed. I have been struggling with this for about five days now and I figured out few important things: the ECC608 is by default (from the factory) in the unlocked state, it can't be used until it is locked (manually from the code). The certificate sign request should be generated on the MRK WiFi 1010 device and the private key is stored internally within the MKR WiFi 1010 device, tha'ts very important detail. Afte that, the CSR should be passed to the certification provider and the sercret certificate should be generated based on that CSR (certificate sign request). Another very important detail is that the self-signed certificate that I'm using for the development might be an issue as it is marked ALWAYS as invalid just because it is self-signed.

**update 22 September**

I'm still struggling with this problem. At this moment, everything is setup and configured on the microcontroller side. The microcontroller can connect to any online test MQTT broker via ssl/tls protocol. I have checked that and double checked. Everything is good on the microcontroller side. My MQTT broker is configured to use TLS v 1.2 it is deployed live, the cetificate is valid, it is generated by the zerossl trusted authority and it just works. I can connect from the test clients to my Mosquitto MQTT broker. I have tried multiple clients and everythig works fine. At this point, I have verified that client is valid and server is valid, both can connect to another party using TLS secure protocol. But, when I'm trying to pair my microcontroller with my Mosquitto MQTT broker - TLS SSL error is thrown, saying that the handshake failed. ssl tls 1.2 error ACCEPT\_SR\_KEY\_EXCH ssl handshake failure. I have tried to debug it using the Wireshark, but there are no details at all. when I try to debug the SSL/TLS using the Wireshark, I see that there is a Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done and it repeats in a sequence again:

Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done

Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done

Client Hello, after that the Server Hello, then Certificate, Server Key Exchange, Server Hello Done

any help is appreciated.

# Answer
seems like you have made quite a progress. Frankly, I believe that the problem lies behind not storing your private key in the ECC608.

If the private key is not correctly stored in the ECC608 TLS Handshake will fail. You mentioned the ECC608 is unlocked by default. You're correct that to use the secure functionalities of the chip, it has to be locked. However, as far as I know once it's locked, it can't be unlocked. Make sure you've followed the necessary steps to store your private key in the ECC608 and then locked it to secure the key. I think you can use `ArduinoECCX08` library since it seems to have `ECCX08.begin()`, `ECCX08.lock()`, `ECCX08.generatePrivateKey(slot)` functions. Your approach to generating the CSR directly on the MKR WiFi 1010 device is on point. This method ensures the private key never leaves the device. Consequently, only the public part is sent to the CA, even if it's self-signed. With the CSR, obtain your device certificate. This certificate, coupled with the private key securely housed in the ECC608, should facilitate the TLS handshake.

**TL;DR**: Make sure that you've stored the private key appropriately in the ECC608. Before locking the ECC608, test to ensure that the private key functions as expected. Check your MQTT Broker Logs for further debugging (when provided and when I get time for that I will try my best to pinpoint the error) and try using WireShark to capture SSL traffic.

That is as far as my knowledge goes, all the best luck to you. I hope that I could be of help dude.
> 1 votes

---
Tags: wifi, mkr1010wifi
---


# Question
Title: Can I power ESP8266 with more than 3.5 V?
I am concerned whether I need to use a voltage divider to power my ESP8266 module. My concerns stem from the warnings that I have heard in multiple tutorials. Everyone seems to regard the ESP8266 as being very sensitive to supply voltage.

Has anyone use the ESP8266 with an supply voltage greater than 3.5 V? What were the effects? Is it even necessary to make a voltage divider?

I am asking because my application has limited real estate.

# Answer
> 7 votes
The datasheet usually is definitive on the allowable range of voltages.

Look in Section 5.1: Electrical Characteristics.

## Working Voltage Value:

* Min: 2.5 V
* Typical: 3.3 V
* Max: 3.6 V

If you have to feed in signals that could go higher than 3.3 V in normal operation, you need to either clamp it with Zener diodes, or use a voltage divider.

If you are asking about powering the chip with more than 3.3 V, don't. You can get away with a 3.3 V linear regulator and 2 capacitors so that you are powering it with no more than designed supply voltage.

# Answer
> 1 votes
The result to apply more voltage to a circuit is that the components will be burn. The same if you apply for a long time the maximum voltage. So the board works at 3.3v, your source maybe fluct between that but you will burn it if you apply 3.6 or more as a regular voltage.

# Answer
> 1 votes
Usually ESP8266 **modules** have an onboard voltage regulator, USB connector and a pin labeled **5V**. This pin or the USB cable certainly tolerate resp. need a 5V power supply.

The ESP8266 controller itself will not survive 5V, neither at the Vcc nor at the signal pins.

BTW: a voltage divider (two resistors) is ok for signals, but does not help with the power supply.

# Answer
> 0 votes
I have 4 pieces of ESP01-S with DHT11 that connect to the WiFi every 30 minutes and send temperature data and then go into DeepSleep. In addition, an ESP01-S as a motion detector and one as a push button. These two usually in DeepSleep. All are directly connected to a Li-Ion battery as power supply. This has been running for over a year (except for changing the battery) and so far I haven't had any problems

---
Tags: esp8266
---


# Question
Title: Is there any way I can connect the RAM of a computer to Arduino?
I was thinking about a way to reuse the RAM of my old computer on my Arduino board. I was thinking about some peojects using neural networks, and more RAM would let the Arduino use more neurons.

So that's my question, how could I do that? Maybe soldering some cables to Tx/Rx pins and creating and interface between the board and the memory?

# Answer
> 5 votes
No, you can't connect your normal desktop computer memory to your Arduino. For a number of reasons:

1. Computer memory (at least for the past 20 years) is DDR SDRAM. That's Synchronous Dynamic RAM. It requires very strict timing and synchronous (clock based) data transfers with clocks measured in the hundreds of MHz - something the Arduino cannot do.
2. You need lots and lots of I/O pins to interface with SDRAM. I mean, just look at all those pins - how would you connect all those up to a little Arduino?
3. Being DRAM you need to use quite a complex process to keep the data refreshed and stop the capacitance of each cell from draining away. Yes, that side of things is do-able, but not child's play.

The only way you will be able to interface DDR SDRAM with an Arduino is through some intermediate interfacing system that can do all the above for you. Your best candidate is to design an SPI to DDR conversion chip using an FPGA and Verilog or VHDL. That way you can communicate with the FPGA using SPI (or you could choose I2C if you like, or a simple 8-bit parallel protocol) and the FPGA then does all the grunt work that the Arduino isn't capable of.

However, while you're at it, you may as well put a CPU core in the FPGA (e.g., NIOS II or something) and do away with the Arduino altogether...

# Answer
> 1 votes
I know this is old, but it comes up on Google so here I am.

Forget about connecting any kind of *modern* computer RAM to an Arduino. Period.

However, an old school SIMM from the 80's/early 90's is very much possible to use with some effort and they're cheap enough to buy on eBay. These are the ones you would have usually found on a 386/486 or early Pentium system.

Here is an example: http://dmitry.gr/?r=05.Projects&proj=07.%20Linux%20on%208bit

There are much easier and more cost-effective ways to add RAM to your 8-bit Arduino though. Look up SPI RAM. That's probably what you want. It's only a 4 pin connection, and numerous libraries already exist to interface with them.

# Answer
> 0 votes
If you try hard enough it might work, but it will not be easy.

In general there are 2 types of RAM. Static and Dynamic. You can cram a lot more memory into a Dynamic RAM chip so that is what is most likely in your computer. And probably what you are asking about in your question.

Dynamic memory needs to be refreshed continuously. Otherwise the data will be lost. This is such a repetitive and time consuming process that special hardware is used to relieve the processor of this task. In general, embedded processors such at the Atmel (used in most Arduinos) do not have such specialized hardware.

So it will be (very) difficult to use your computer memory in your Arduino.

That said, there are some specialized RAM chips that you can use with your Arduino. But they likely do not look like the memory chips in your computer.

---
Tags: memory-usage, sram, memory
---


# Question
Title: Arduino Nano is performing really slowly, even though the calculations are simple and there are no delays
I'm working on a tiny ping-pong game based on Arduino Nano. Its modes are "person vs person" and "person vs computer" (the computer just tries to keep its racket at the same Y position as the ball). There are 2 "up" buttons, 2 "down" buttons, two 7-segment score indicators and 2 shift registers controlling them. The display is SSD1306 (128x32 pixels).

I'm posting here the entire code because I don't know where the issue lies.

```
#include <Adafruit_SSD1306.h>

// Up/down buttons
#define UP1 2
#define DOWN1 3
#define UP2 4
#define DOWN2 5

// Shift registers that control score indicators
#define DATA1 6
#define CLOCK1 7
#define LATCH1 8
#define DATA2 9
#define CLOCK2 10
#define LATCH2 11

#define RANDOM_NUMBERS A0  // This port isn't connected to anything and is used to get random seed
#define WRAP 118  // Text on display wraps on this position

#define SSD1306_ADDRESS 0x3C  // I2C address of display

Adafruit_SSD1306 ssd1306;

const byte numbers[10] = {  // Arab numbers for score indicators
  0b1111110, 0b0011000, 0b1101101, 0b0111101, 0b0011011, 0b0110111, 0b1110111, 0b0011100, 0b1111111, 0b0111111
};

short currentDirection = -1;
short directionState = -1;  // The sequence number of next move in the period of ball trajectory
short nextMove = -1;
short ballX = 63;
short ballY = 15;
short racket1 = 12;
short racket2 = 12;

short score1 = 0;
short score2 = 0;
bool gameOver = false;

bool playingWithComputer = false;

void setup() {
  pinMode(UP1, INPUT_PULLUP);
  pinMode(DOWN1, INPUT_PULLUP);
  pinMode(UP2, INPUT_PULLUP);
  pinMode(DOWN2, INPUT_PULLUP);
  pinMode(DATA1, OUTPUT);
  pinMode(CLOCK1, OUTPUT);
  pinMode(LATCH1, OUTPUT);
  pinMode(DATA2, OUTPUT);
  pinMode(CLOCK2, OUTPUT);
  pinMode(LATCH2, OUTPUT);

  randomSeed(analogRead(RANDOM_NUMBERS));

  updateScores();

  ssd1306.begin(SSD1306_SWITCHCAPVCC, SSD1306_ADDRESS);
  ssd1306.display();
  delay(2000);  // A delay to show the Adafruit logo
  ssd1306.clearDisplay();

  ssd1306.setTextSize(1);
  ssd1306.setTextColor(WHITE);
  ssd1306.setCursor(0, 0);  // Cursor should be at this position to draw objects correctly

  printLongText(5, 0, "Press \"up\" to play with computer, otherwise press \"down\"");

  while (true) {
    if (!digitalRead(UP1) || !digitalRead(UP2)) {  // Both "up" buttons (as well as both "down" ones) are treated the same unless there's a game "person vs person"
      playingWithComputer = true;
      break;
    }
    if (!digitalRead(DOWN1) || !digitalRead(DOWN2)) break;

    delay(5);  // This delay is here to avoid overloading the processor
  }

  ssd1306.clearDisplay();
  ssd1306.display();

  delay(100);  // This delay is intended to show user that they don't need to hold button any more
}

void loop() {
  if (gameOver) {
    delay(1000);
    return;
  }

  if (nextMove < 0) {
    pickDirection();
    return;
  }

  short oldDirection = currentDirection;
  switch (getBounceType()) {
    case 0:
      verticalFlipDirection();
      ballY++;
      break;
    case 1:
      verticalFlipDirection();
      ballY--;
      break;
    case 2:
      if (ballY < (racket1 - 1) || ballY > (racket1 + 8)) {  // This determines if the ball ran shorto the racket or not (true if it did not)
        score2++;

        // Ball goes to the center of the screen after goal
        ballX = 63;
        ballY = 15;
        pickDirection();

        updateScores();
      }
      else {
        horizontalFlipDirection();
        ballX++;
      }

      break;
    case 3:
      if (ballY < (racket2 - 1) || ballY > (racket2 + 8)) {
        score1++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        horizontalFlipDirection();
        ballX--;
      }

      break;
    case 4:
      if (racket1 > 1) {
        score2++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        reverseDirection();  // This occurs when the ball rans exactly shorto the corner of its zone
        ballX++;
        ballY++;
      }

      break;
    case 5:
      if (racket2 > 1) {
        score1++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        ballX--;
        ballY++;
        reverseDirection();
      }

      break;
    case 6:
      if (racket1 > 1) {
        score2++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        reverseDirection();
        ballX++;
        ballY--;
      }

      break;
    case 7:
      if (racket2 > 1) {
        score1++;
        ballX = 63;
        ballY = 15;
        pickDirection();
        updateScores();
      }
      else {
        ballX--;
        ballY--;
        reverseDirection();
      }

      break;
  }
  if (oldDirection != currentDirection) directionState = 0;  // Resetting direction state if the ball bounced
  pickMove();  // Next move may have changed if the ball bounced

  switch (nextMove) {
    case 0:
      ballY--;
      break;
    case 1:
      ballX++;
      break;
    case 2:
      ballY++;
      break;
    case 3:
      ballX--;
      break;
  }
  directionState++;
  pickMove();

  ssd1306.clearDisplay();
  ssd1306.drawRect(ballX, ballY, 2, 2, WHITE);

  if (playingWithComputer) {
    if (!digitalRead(UP1) || !digitalRead(UP2)) {
      if (racket1 > 0) racket1--;
    }
    if (!digitalRead(DOWN1) || !digitalRead(DOWN2)) {
      if (racket1 < 24) racket1++;
    }

    // This is the algorithm used by computer — it just tries to keep the computer-controlled racket at the same Y position as the ball
    if ((racket2 + 3) > ballY) {
      if (racket2 > 0) racket2--;
    }
    if ((racket2 + 3) < ballY) {
      if (racket2 < 24) racket2++;
    }
  } else {
    if (!digitalRead(UP1)) {
      if (racket1 > 0) racket1--;
    }
    if (!digitalRead(DOWN1)) {
      if (racket1 < 24) racket1++;
    }
    if (!digitalRead(UP2)) {
      if (racket2 > 0) racket2--;
    }
    if (!digitalRead(DOWN2)) {
      if (racket2 < 24) racket2++;
    }
  }

  ssd1306.drawRect(0, racket1, 2, 8, WHITE);
  ssd1306.drawRect(126, racket2, 2, 8, WHITE);

  ssd1306.display();
}

// This function picks a random direction for the ball
void pickDirection() {
  currentDirection = random(0, 20);
  directionState = 0;
  pickMove();
}

// This function determines the next move of the ball (up/right/down/left) based on its current direction and direction state
void pickMove() {
  short sector = getSector();  // Directions that go to up-right are in sector 0, those going to down-right are in sector 1, etc

  switch (currentDirection) {
    case 0:
    case 5:
    case 10:
    case 15:
      directionState = directionState % 5;  // Resetting direction state when the ball reaches next period of its trajectory

      // At certain direction states the ball goes to its primary direction (e.g. in an almost vertical trajectory the primary direction would be up)
      // At other states it goes to the secondary direction, which when added to the primary one forms the actual trajectory of the ball
      // Sectors divide into 2 parts. The first part includes 3 trajectories which have their primary direction number (up - 0, right - 1, down - 2, left - 3) same as sector number
      // Secondary directions in first part are sector number plus 1
      // In the second part the primary direction is (sector_number + 1) % 4 and the secondary one is the sector number
      // There are 20 supported trajectories (5 in each of 4 sectors). They are presented in Ping-Pong.png
      // First trajectories in each sector (as well as second ones etc) have the same structure, so there's only one code block
      // for handling first trajectories of all sectors. However, their primary and secondary directions differ in each sector
      // The following line determines if the ball should now go to the primary or secondary direction and based on that sets nextMove
      nextMove = (directionState == 0 || directionState == 1 || directionState == 3) ? sector : (sector + 1) % 4;
      return;
    case 1:
    case 6:
    case 11:
    case 16:
      directionState = directionState % 4;
      nextMove = (directionState < 2) ? sector : (sector + 1) % 4;
      return;
    case 2:
    case 7:
    case 12:
    case 17:
      directionState = directionState % 4;
      nextMove = (directionState == 0 || directionState == 2) ? sector : (sector + 1) % 4;
      return;
    case 3:
    case 8:
    case 13:
    case 18:
      directionState = directionState % 4;
      nextMove = (directionState < 2) ? getSecondPartMove(sector) : sector;
      return;
    case 4:
    case 9:
    case 14:
    case 19:
      directionState = directionState % 5;
      nextMove = (directionState == 0 || directionState == 1 || directionState == 3) ? getSecondPartMove(sector) : sector;
      return;
  }
}

// Just a helper for pickMove (determines primary direction of second-part trajectories in a certain sector)
short getSecondPartMove(short sector) {
  return (sector + 1) % 4;
}

// This function determines the current bounce type (-1 - currently no bounce, 0 - bounce from upper wall,
// 1 - bounce from lower wall, 2 - facing the first player's wall, 3 - facing the second player's wall,
// 4 - facing upper-left corner, 5 - upper-right corner, 6 - bottom-left, 7 - bottom right
// On 4-7 the ball reverses its trajectory
short getBounceType() {
  if (ballX <= 2 && ballY <= 0) return 4;  // Made ballX indents so that the ball bounces from rackets and not bounds of screen
  if (ballX >= 124 && ballY <= 0) return 5;
  if (ballX <= 2 && ballY >= 30) return 6;
  if (ballX >= 124 && ballY >= 30) return 7;

  if (ballX <= 2) return 2;
  if (ballX >= 124) return 3;

  if (ballY <= 0) return 0;
  if (ballY >= 30) return 1;

  return -1;
}

// This function flips the current trajectory of the ball vertically to bounce from the upper/lower wall
// (source and flipped trajectories have a relationship that differs in different sectors of the source trajectory, see this function)
void verticalFlipDirection() {
  short sector = getSector();

  switch (sector) {
    case 0:
    case 1:
      currentDirection = 9 - currentDirection;
      return;
    case 2:
    case 3:
      currentDirection = 10 + (9 - (currentDirection - 10));
      return;
  }

  directionState = 0;
}

// Same as previous function but the translation is horizontal here
// (the relationship between source and flipped trajectories is different)
void horizontalFlipDirection() {
  short sector = getSector();

  switch (sector) {
    case 0:
    case 3:
      currentDirection = 19 - currentDirection;
      return;
    case 1:
    case 2:
      currentDirection = 5 + (9 - (currentDirection - 5));
      return;
  }

  directionState = 0;
}

// This function reverses the trajectory of the ball
void reverseDirection() {
  currentDirection = (currentDirection + 10) % 20;
  directionState = 0;
}

// This function determines the sector of the current trajectory
short getSector() {
  if (currentDirection < 5) return 0;
  else if (currentDirection < 10) return 1;
  else if (currentDirection < 15) return 2;
  else return 3;
}

// This function prints text on the display, wrapping it at a certain X position
void printLongText(short cursorX, short cursorY, String text) {
  ssd1306.setCursor(cursorX, cursorY);

  int16_t x, y;
  uint16_t w, h;

  short lastSpace = -1;
  short i;

  // Adding character by character to current line until the wrapping position is reacher
  // In parallel finding the last space before wrap (it will be where the line breaks)
  for (i = 0; i < text.length(); i++) {
    if (text.charAt(i) == ' ') lastSpace = i;

    ssd1306.getTextBounds(text.substring(0, i + 1), 0, 0, &x, &y, &w, &h);

    if (x + w > WRAP && lastSpace >= 0) {
      ssd1306.println(text.substring(0, lastSpace + 1));  // Wrapping position reached; breaking the current line at the index of last space in it and printing it
      text = text.substring(lastSpace + 1);

      i = -1;  // Now the same with next line
      lastSpace = -1;
      ssd1306.setCursor(cursorX, ssd1306.getCursorY());
    }
  }
  ssd1306.println(text);  // printing the rest of text

  ssd1306.display();

  ssd1306.setCursor(0, 0);  // Cursor should be at this position to draw objects correctly
}

// This function displays the scores on corresponding indicators and checks if the game if over
// (i.e. one of the players has a score of 7)
void updateScores() {
  digitalWrite(LATCH1, false);
  shiftOut(DATA1, CLOCK1, MSBFIRST, numbers[score1]);  // Sending the necessary mask to the shift registers
  digitalWrite(LATCH1, true);

  digitalWrite(LATCH2, false);
  shiftOut(DATA2, CLOCK2, MSBFIRST, numbers[score2]);
  digitalWrite(LATCH2, true);

  if (score1 >= 7) {
    ssd1306.clearDisplay();
    printLongText(10, 12, "Player 1 wins!");
    ssd1306.display();

    gameOver = true;
  }
  if (score2 >= 7) {
    ssd1306.clearDisplay();
    printLongText(10, 12, "Player 2 wins!");
    ssd1306.display();

    gameOver = true;
  }
}

```

**Look how slowly does the ball move, even though a `loop` iteration doesn't include any `delay`s at all, and there are no complex calculations.** Conversion to GIF didn't change the speed.

My circuit looks like this (it's just a test, so no buttons, just pull-ups, and no score indicators).

simulate this circuit – Schematic created using CircuitLab

Answers here didn't help. Changing the I2C clock speed to 400 KHz didn't help either.

So — is such slowness caused by the (not very high) complexity of my code? Or is it some kind of glitch? **Please don't suggest using libraries instead of my own moving and bouncing logic.**

# Answer
I put in some timing into your code. As a tip for you and others who may want to time code, here is a simple way of doing that ...

## Timer class

Define a timer class as follows:

```
class timer
  {
  unsigned long start;
  const char sReason [50];

  public:

    // constructor remembers time it was constructed
    timer (const char * s)
      {
      strncpy (sReason, s, sizeof (sReason) - 1);
      start = micros ();
      Serial.print (F("Start:  "));
      Serial.println (sReason);
      };

    // destructor gets current time, displays difference
    ~timer ()
      {
      unsigned long t = micros ();
      Serial.print (F("Finish: "));
      Serial.print (sReason);
      Serial.print (F(" = "));
      Serial.print (t - start);
      Serial.println (F(" µs"));
      }
  };    // end of class timer

```

## How to use the timer class

If you want to time "loop" then just put this at the start of it:

```
void loop() {
  timer t ("Loop");
  ... other code ...
}  // end of loop

```

The constructor starts timing, and the destructor (when `loop` is exited) works out the difference and displays it.

To time some specific code, make a "block" like this:

```
  {    // start of block
  timer t ("Draw ball");
  ssd1306.clearDisplay();
  ssd1306.drawRect(ballX, ballY, 2, 2, WHITE);
  }    // end of block

```

Inside the block the timer instance is created, it times what is inside the block, and displays the result after the `}` is passed.

Naturally, for all this to work you need to do a `Serial.begin (115200);` in `setup`.

---

## Results of timing

I added the above two timing calls, plus for drawing the rackets and updating the display:

```
  {
  timer t ("Draw rackets");
  ssd1306.drawRect(0, racket1, 2, 8, WHITE);
  ssd1306.drawRect(126, racket2, 2, 8, WHITE);
  }

  {
  timer t ("ssd1306.display");
  ssd1306.display();
  }

```

The results I got were:

```
Start:  Loop
Start:  Draw ball
Finish: Draw ball = 1812 µs
Start:  Draw rackets
Finish: Draw rackets = 1956 µs
Start:  ssd1306.display
Finish: ssd1306.display = 168944 µs
Finish: Loop = 178516 µs

```

Clearly, updating the display is taking almost all the time (169 ms each time, which means you will be doing around 5 loops per second).

Following on from a suggestion in the Adafruit forum I changed your constructor for ssd1306 to be:

```
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 ssd1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

```

Now the timing is:

```
Start:  Loop
Start:  Draw ball
Finish: Draw ball = 1780 µs
Start:  Draw rackets
Finish: Draw rackets = 1956 µs
Start:  ssd1306.display
Finish: ssd1306.display = 21192 µs
Finish: Loop = 30648 µs

```

So that is around 33 FPS rather than 5 FPS. A big improvement!

---

## Further speed improvements

Following on from your edit about changing from I2C to SPI "not making much difference", the speed difference would indeed be significant. According to my page about protocols SPI can be 30 times as fast as I2C (depending on the I2C clock speed) so I suggest that getting the SPI version of that board would indeed give you a significantly faster refresh rate — at least 10 times as fast.

You may then need to rework how you show scores but bit banged SPI could be an option for the them. The scores hardly need to update all that quickly, and in any case there would be a lot less data. (The screen has 4096 pixels, and the scores would only be a handful of digits).

---

From a comment by SNBS:

> But I noted in my question that changing the I2C clock speed to 400 KHz (which is 4 times as fast as its regular speed) didn't affect the situation at all.

Yes, well the default behaviour for the constructor is to use a 400 kHz clock, see the constructor declaration:

```
Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi = &Wire,
                   int8_t rst_pin = -1, uint32_t clkDuring = 400000UL,
                   uint32_t clkAfter = 100000UL);

```

The constructor definition saves `clkDuring` into `wireClk`.

```
Adafruit_SSD1306::Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi,
                                   int8_t rst_pin, uint32_t clkDuring,
                                   uint32_t clkAfter)
    : Adafruit_GFX(w, h), spi(NULL), wire(twi ? twi : &Wire), buffer(NULL),
      mosiPin(-1), clkPin(-1), dcPin(-1), csPin(-1), rstPin(rst_pin)
#if ARDUINO >= 157
      ,
      wireClk(clkDuring), restoreClk(clkAfter)
#endif

```

At the start of the `display` function it calls TRANSACTION\_START

```
void Adafruit_SSD1306::display(void) {
  TRANSACTION_START

```

This is a define:

```
#define TRANSACTION_START                                                      \
  if (wire) {                                                                  \
    SETWIRECLOCK;                                                              \
  } else {                                                                     \
    if (spi) {                                                                 \
      SPI_TRANSACTION_START;                                                   \
    }                                                                          \
    SSD1306_SELECT;                                                            \
  } ///< Wire, SPI or bitbang transfer setup

```

And `SETWIRECLOCK` sets the I2C clock speed for you:

```
#define SETWIRECLOCK wire->setClock(wireClk)    ///< Set before I2C transfer

```
> 10 votes

---
Tags: arduino-nano, performance, ssd1306
---


# Question
Title: Arduino will not recognise USB ports on my Mac running Sierra
Arduino will not recognise USB ports on my Mac running Sierra I am a teacher who helps teachers to use LilyPad. I used to be able to plug in my LilyPad Arduino and see the USB port. I have read all the answers and dowloaded the drivers from Spark fun and another driver from Github. Nothing is working and i am not technical enough to find the answer myself. I have spent three hours today trawling through the answers to this problem and still cannot fix it myself. I am a luddite who needs a simple step by step remedy. Apple support had no idea when I rang them and told me it was an Arduino problem and to talk to them. you cant talk to anyone at Arduino you can only go to the forums. the forums tell you to read others answers before you post. I have. it's still not working. i need help. And not a lecture about being on a forum asking dumb questions.

I even mucked around in terminal and am hoping it's not a 'terminal" problem because I have no clue what i am doing. If you can explain in plain speak please respond. i have to teach this stuff in 4 days.

This is the message I get when I try to upload a sketch

# Answer
I spoke to a very clever friend who has had similar problems. The answer lay in downloading the FTDI helper package not just the driver. If anyone else is having a similar problem the website is

https://www.ftdichip.com/Drivers/D2XX/MacOSX/D2xxHelper\_v2.0.0.pkg

I downloaded it and now my lilypad and USB port is recognised by the Arduino software.

Just in time for Thursday.

Thanks to all who tried to help.

K
> 2 votes

# Answer
I had a problem getting my computer (Mac Pro, OS 1.12.1 Sierra) to recognize my Arduino Leonardo and Micro boards. Tried many different fixes, nothing worked. Finally used a different cable, and both boards worked fine. NB: I didn't suspect a cable problem, since I removed the cable from a working device. Just to make things weirder, the original device I removed the cable from worked just fine when I re-installed the (supposedly defective) cable.
> 1 votes

# Answer
The Lillypad uses the ATMega32U4 chip. This is the same as the Arduino Leonardo and the Arduino Micro, and suffers the same basic issue that they both suffer from.

Basically, the USB connection is driven by the main chip, not by an interface chip as in most other Arduino boards. This gives you increased flexibility (e.g., using it as a keyboard or a mouse) and decreased cost (less components on the board), but at the additional cost of certain problems that you have to be prepared to resolve.

Because the main chip runs the USB connection that main chip must be working properly for there to even be a USB connection. With other boards that isn't the case - you can remove the main chip completely and the USB interface chip will still work. So it is perfectly possible to "kill" the board by installing a sketch on it which stops the main chip from functioning. As soon as the main chip stops functioning the USB stops functioning - and if the sketch that is installed never starts working at all then you never see a USB connection.

Sometimes it is possible to get the USB port to appear for a short period (a few seconds) by pressing the reset switch, but you have to time it right (press reset and immediately select the port in the menu, then press upload, and press reset again just *before* the uploading itself starts).

The sure-fire fix, though, is to erase the entire chip (along with your installed "broken" sketch) and reinstall the bootloader using the IDE's tools. You'll need either a hardware programmer (the USBASP is dirt cheap and easy to get on eBay) or another Arduino using the *ArduinoISP* sketch bundled with the IDE.

If you're going to do any serious work or teaching with any microcontroller-based system it's always good to have a hardware programmer available to help recover from problems, no matter what platform you're working with. **Remember: if there's a way to break it, kids will find it. And do it.**
> 0 votes

# Answer
I had the same problem: my MacBook Air registered by Arduino Board in the USB Device Tree but it was not showing up in the Ports list of the Arduino IDE. It was resolved when I changed the Privacy and Security setting for Allow Accessories to Connect. When I changed the setting to "Automatically When Unlocked" the Arduino IDE was able to recognize my board.

Route to setting: Apple Logo on top Right -\> System Settings -\> Privacy and Security -\> (scroll down to Security) Allow Accessories to Connect.
> 0 votes

---
Tags: mac-os
---


# Question
Title: Reading a string from the serial port and comparing to another string
I'm using an Arduino Mega 2560 and writing a really simple piece of code that doesn't work.

```
String a, letra;
#define led 13

void setup() {
  Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
  pinMode(led, OUTPUT);
}

void loop() {
  while(Serial.available()) {
    letra= Serial.readStringUntil('\n');
    letra.trim();
    Serial.println(letra);

    if(letra.equals("aa\r\n")){
      Serial.println("ABRE 1");
    }
    if(letra == "aa\r\n"){
      Serial.println("ABRE 2");
    }
    if(letra.compareTo("aa\r\n") == 0){
      Serial.println("ABRE 3");
    }
  }
}

```

It's returning what I typed, but it's not entering any of the if conditions... Can someone help me with that ?

# Answer
> 1 votes
Trim removes whitespace, and you are comparing for `\r` and `\n` to be there. Since they are whitespace naturally the compare fails.

See here for one definition of whitespace for C.

---
Tags: serial, string
---


# Question
Title: ESP-32 Upload Files to SPIFFS via browser
I am using ESPAsyncWebServer Library in a ESP32 DevKit. I want to make a form in the browser in order to upload files in SPIFFS.

I have to notice that the whole device works perfectly. I connect to Wi-Fi, it uploads files via IDE etc.

Through searching in the net, I found this part of code that does not work.

```
server.on("/upload-file", HTTP_GET, [](AsyncWebServerRequest* request) {
    String html = "<body><div><form method='post' action='/upload-file'><input type='file'><button>Send</button></form></div></body>";
    request->send(200, "text/html", html);
    });

server.on("/upload-file", HTTP_POST, [](AsyncWebServerRequest* request) {
    AsyncWebServerResponse* response = request->beginResponse(200, "text/html", "hello world");
    response->addHeader("Connection", "close");
    request->send(response);
    }, handleUpload);
server.onFileUpload(handleUpload);

```

The handleUpload function:

```
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if (!index) {
    request->_tempFile = SPIFFS.open("/" + filename, "w");
}
if (len) {
    request->_tempFile.write(data, len);
}
if (final) {
    request->_tempFile.close();
    request->redirect("/files");
}
}

```

It shows the form but the file doesn't upload. Is there any idea on how can I make it work?

# Answer
I had the same problem and thanks to you, I did solve the problem!

Here is the full code, My html code for the upload page, the form is in the tag:

```

<!DOCTYPE html>
<html>
<head>
  <title>File Upload Example</title>
</head>
<body>
  <h1>File Upload Example</h1>
<form method="POST" action="/upload" enctype="multipart/form-data" target="iframe"><input type="file" name="upload"><input type="submit" value="Upload"></form>
<iframe style="visibility: hidden;" src="http://" )+local_IPstr+"/Usm" name="iframe"></iframe>
</body>
</html>

```

code for ESP:

```

void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if (!index) {
    request->_tempFile = SPIFFS.open("/" + filename, "w");
    Serial.println("1");
}
if (len) {
    request->_tempFile.write(data, len);
     Serial.println("2");
}
if (final) {
   Serial.println("3");
    request->_tempFile.close();
    request->redirect("/");
}
}

 controlserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request) {
        request->send(200); }, handleUpload);

  controlserver.on("/UPL", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", upl);
  });

  readFile(SPIFFS, "/11.txt"); // show the content of the uploaded file, obviously you should know the name of the uploaded file!

```

you can write a function like this to make sure the file was delivered:

```
  readFile(fs::FS &fs, const char * path){
  Serial.printf("Reading file: %s\r\n", path);
  File file = fs.open(path, "r");
  if(!file || file.isDirectory()){
    Serial.println("- empty file or failed to open file");
    return String();
  }
  Serial.println("- read from file:");
  String fileContent;
  while(file.available()){
    fileContent+=String((char)file.read());
  }
  file.close();
  Serial.println(fileContent);

}

```
> 2 votes

---
Tags: esp32, spiffs
---


title: how to make this code work with spiffs?

text:
# Question
Title: how to make this code work with spiffs?
So, I have a page to select a txt file from the user's device and save it to SD card:

```
<!DOCTYPE html>
<html>
<head>
  <title>File Upload </title>
</head>
<body>
  <h1>File Upload </h1>
<form method='POST' action='/upload' enctype='multipart/form-data'>
<input type='file' name='upload'>
<input type='submit' value='Upload'>
</form>
</body>
</html>

```

and here is my esp8266 code for handling the form :

```

  controlserver.on("/UPL", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", upl);
  });
 controlserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request) {
        request->send(200); }, handleUpload);

void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
  String logmessage = "Client:" + request->client()->remoteIP().toString() + " " + request->url();

  if (!index) {
    logmessage = "Upload Start: " + String(filename);
    request->_tempFile = SD.open("/" + filename, "w");
  }

  if (len) {
    request->_tempFile.write(data, len);
    logmessage = "Writing file: " + String(filename) + " index=" + String(index) + " len=" + String(len);
  }

  if (final) {
    logmessage = "Upload Complete: " + String(filename) + ",size: " + String(index + len);
    request->_tempFile.close();
    request->redirect("/");
  }
}

```

My project is not big and it doesn't require SD card, and esp8266 has 4mb memory, I have tried to replace SD with spiffs, but I wasn't successful. I don't know that if it's possible to directly write the txt file to spiffs, but it will be ok if I could save it to a string the write it to a file in spiffs.

# Answer
> 1 votes
Thanks to this post, I did solve the problem.

Here is the full code, My html code for the upload page, the form is in the tag:

```

<!DOCTYPE html>
<html>
<head>
  <title>File Upload Example</title>
</head>
<body>
  <h1>File Upload Example</h1>
<form method="POST" action="/upload" enctype="multipart/form-data" target="iframe"><input type="file" name="upload"><input type="submit" value="Upload">
</form>
<iframe style="visibility: hidden;" src="http://" )+local_IPstr+"/Usm" name="iframe"></iframe>
</body>
</html>

```

code for ESP:

```

void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if (!index) {
    request->_tempFile = SPIFFS.open("/" + filename, "w");
    Serial.println("1");
}
if (len) {
    request->_tempFile.write(data, len);
     Serial.println("2");
}
if (final) {
   Serial.println("3");
    request->_tempFile.close();
    request->redirect("/");
}
}

 controlserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request) {
        request->send(200); }, handleUpload);

  controlserver.on("/UPL", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", upl);
  });

  readFile(SPIFFS, "/11.txt"); // show the content of the uploaded file, obviously you should know the name of the uploaded file!

```

you can write a function like this to make sure the file was delivered:

```
  readFile(fs::FS &fs, const char * path){
  Serial.printf("Reading file: %s\r\n", path);
  File file = fs.open(path, "r");
  if(!file || file.isDirectory()){
    Serial.println("- empty file or failed to open file");
    return String();
  }
  Serial.println("- read from file:");
  String fileContent;
  while(file.available()){
    fileContent+=String((char)file.read());
  }
  file.close();
  Serial.println(fileContent);

}

```

---
Tags: esp8266, spiffs
---


title: ESP32 TTGO T-Call connect to SX1276

text:
# Question
Title: ESP32 TTGO T-Call connect to SX1276
I have an ESP32 TTGO T-Call and I want to add a LoRa SX1276. I am new to that and I am trying to write a simple program that, when it receives a packet from a LoRa sender, sends via gsm an HTTP request. GSM communication works fine with the TinyGSM library. My problem is the LoRa connection.

Specific chips according to this issue have some reserved pins. If I use the pins of the above example lora works but GSM does not work, because of the reserved pins for the SIM800. I am posting a piece of code with the LoRa setup that is not working. If there is a need for further explanation please ask. I will appreciate any kind of help.

```
#define SCK 14
#define SS 15
#define MISO 19
#define MOSI 27
#define RST 34
#define DIO0 33

SPI.begin(SCK, MISO, MOSI, SS);
//setup LoRa transceiver module
LoRa.setPins(SS, RST, DIO0);

while (!LoRa.begin(866E6)) {
    SerialMonitor.println(".");
    delay(500);
}
SerialMonitor.println("LoRa Initializing OK!");

```

**Edited**

With setting

```
#define LORA_MISO 19
#define LORA_MOSI 27
#define LORA_SCK 5
#define LORA_SS 18

#define LORA_RST 14
#define LORA_DIO0 26

```

Lora works (not sim800) but with the settings of @Juraj comment i am getting

> E (11571) gpio: GPIO can only be used as input mode \[ 11575\]\[E\]\[esp32-hal-gpio.c:130\] \__pinMode(): GPIO config failed E (11571) gpio: gpio\_set\_level(226): GPIO output gpio\_num error E (11586) gpio: gpio\_set\_level(226): GPIO output gpio\_num error

**Edit**

Although the error exists it is working with the above settings:

```
#define LORA_MISO 2
#define LORA_MOSI 13
#define LORA_SCK 14
#define LORA_SS 15

#define LORA_RST 34
#define LORA_DIO0 25

```

Some packets from the sender are lost but it seems to be working. I don't know why, but it is working... Also it does not seem very stable.

Finally pins 34-39 can be used as input so `#define LORA_RST 34` is not working. But it is not receiving yet from the sender.

# Answer
> 1 votes
The issue seems to be arising from the pin definitions and the fact that the SIM800 and the SX1276 LoRa chip on the board might be competing for the same pins, causing interference

First, let's understand the TTGO T-Call pin mapping for SIM800:

SIM800L IP5306 version 20190610:

1. **4: SIM800L RST**
2. **23: SIM800L DTR**
3. **26: SIM800L PWR**
4. **27: SIM800L TX**
5. **32: SIM800L RX**
6. **33: SIM800L RI**

From the pins you've listed for the LoRa SX1276:

1. **SCK: 14**
2. **SS: 15**
3. **MISO: 19**
4. **MOSI: 27**
5. **RST: 34**
6. **DIO0: 33**

It's clear that MOSI on 27 and DIO0 on 33 interfere with SIM800L's pins.

You need to select pins for LoRa that do not interfere with the SIM800L. However, **keep in mind that the ESP32 has certain pins that are not suitable for all types of connections.**

a proposed remapping would be as follows:

```
#define SCK 14
#define SS 15
#define MISO 19
#define MOSI 22
#define RST 34
#define DIO0 25

```

Tell me if this works.

---
Tags: esp32, spi, lora
---


# Question
Title: Micropython installation on Arduino nano
I am currently trying to use micropython on an arduino Nano 33 BLE using MacOS. Following the instructions from arduino website I was able to complete steps 1-3. At step 4, I can find the bossac file but when I try to run the provided command:

`bossac -e -w —offset=0x16000 —port=usbmodem14201 -i -d -U -R file.bin`

the terminal says no device `found on usbmodem14201` which is a port appearing under the nano board in the IDE.

As a sanity check I ran serialportlist in matlab and the same port was returned when the Nano is plugged in.

I even ran ioreg -p IOUSB in terminal and found the nano: ‘’’ Arduino Nano 33 BLE@14200000 \<class AppleUSBDevice, id 0x100008674, re$ ‘’’

That 142… number didn’t work either.

What am I doing wrong?

# Answer
Welcome to Arduino StackExchange:

1. Firstly your computer translates double dashes into single long dashes. the dashes should be double dashes (`--`) for options such as `--offset`, `--port`, etc. The command should be:
```
bossac -e -w --offset=0x16000 --port=usbmodem14201 -i -d -U -R file.bin

```

but I can see that your computer translated these `--` to those  ?

2. Before you try to upload code confirm that the board is recognized by the system using the `ls` command:

```
ls /dev/cu.*

```

This should list all serial devices and you should see something like `/dev/cu.usbmodem14201` in the list if your board is connected.
3. Ensure that you have the necessary permissions to access the serial port. You can try running the `bossac` command with `sudo` to run it as the superuser:

```
sudo bossac -e -w --offset=0x16000 --port=usbmodem14201 -i -d -U -R file.bin

```
4. Instead of just the port name `usbmodem14201`, you might need to use the full path like `/dev/cu.usbmodem14201`:

```
bossac -e -w --offset=0x16000 --port=/dev/cu.usbmodem14201 -i -d -U -R file.bin

```
5. Check that the Arduino Nano 33 BLE is in the bootloader mode. Typically, this can be achieved by double pressing the reset button. When it's in bootloader mode, the board might appear on a different port. Check the ports again with `ls /dev/cu.*` after you double press the reset button.

If you try all those and still it doesn't work maybe you should try installing latest drivers or check compatibility. Anyways, good luck.
> 1 votes

---
Tags: usb, python, flash, firmware, arduino-nano-ble
---