# Question
Title: Asynchronous function calls in Arduino sketch
In an Arduino sketch, is there a way to make asynchronous function calls within the loop? Like listening to requests through http server and process them in a **non-blocking** way.

# Answer
> 16 votes
**Yes and no.** You're kinda vague on what you want to do. I've made this into a few different sections (mainly focused on reading sensor data... it applies to everything but that's the context I'm using):

## Threads

AFAIK all Arduinos only have one core (they can do one thing at once). For most Arduino boards, hardware multithreading isn't supported. However, there are ways to implement software multithreading. The approach by AsheeshR wouldn't work well for functions that take a long time to complete (i.e. something in a library that takes a while, or a delay) because it would get jammed up by those instructions, but it would work well for short functions like `pinMode()`. The Protothreads library listed there might be better at this, but I don't really know.

It'd be hard to orchestrate this with HTTP, especially since you have to make

## Delays

A common way for a sketch to stall is the use of a delay. This can be solved by using, in the main loop, a if statement and the `millis()` function that returns a time (not a clock time, but rather the time since the Arduino started). You could also do a loop within the loop to poll sensor data.

The `millis()` approach wouldn't work well with things that cause the whole program to stall (i.e. *more* delays or loops that last a noticeable amount of time). Note that 100ms IIRC is the general maximum time to make a UI not seem laggy.

## Interrupts

Interrupts are a great way to keep things almost asynchronous. They run a short piece of code (that you specify) every time a pin state changes. It breaks from the `loop()`, and goes back where it left off once the "*ISR*" has been ran. I don't have much time to explain how to do this, but a quick Google search will yield a lot of results.

---

As far as you example, the threading section would be the most applicable. This topic is pretty vague, so you'll have to experiment with a few things and find something that works.

# Answer
> 3 votes
I just posted some code for a task scheduler on the playground the other day, you may want to take a peek, maybe you can adapt it to your needs.

The Arduino's processor is inherently single-threaded and cannot multi-task. As has been mentioned there are however ways to create the illusion of multi-tasking. Annonomus Penguin hit on those pretty well.

Also check out TimerOne (It's probably better ;)

# Answer
> 1 votes
You can definitely make asynchronous code on devices with only one thread. This is what the "static" keyword is for in C. It helps you to setup functions as a "state machine" so that they can run concurrently with other functions.

Let's take a simple function for example. These are just made up functions and not meant to be compiled in any IDE, just to show you the general principles.

```
char read_bit_sync()
{
    while ( digitalRead(PIN_CLOCK) ) {}
    while ( !digitalRead(PIN_CLOCK) ) {}
    return digitalRead(PIN_DATA);
}

void loop()
{
    char c = read_bit_sync();
    Serial.println(c);
}

```

In the example code above, we wait for the clock pin to go high and then low again, and then on the falling edge we read the bit and print it to the Serial output in a loop.

The problem is, what if we want to read this pin asynchronously? These "while" loops cause the whole program to freeze until it receives a bit.

The trick is to reimagine our algorithm as one that can be done in many small steps that each can be completed in a very short amount of time, so that the function will need to be called repeatedly until those steps are completed.

```
int read_bit_async()
{
    static int state = 0;
    int ret;

    switch (state)
    {
        case 0:
            if ( digitalRead(PIN_CLOCK) )
            {
                return -1;
            }
            state++;
            return -1;
        case 1:
            if ( !digitalRead(PIN_CLOCK) )
            {
                return -1;
            }
            state++;
            return -1;
        default:
            ret = digitalRead(PIN_DATA);
            state = 0;
            return ret;
    }
}

void loop()
{
    int c = read_bit_async();
    if (c != -1)
    {
        Serial.println(c);
    }
}

```

In the example above, the function starts in a "0" state which it will remain in that state until it reads that the clock pin is high. It then transitions into a "1" state which it then will remain in until the clock pin is low. It then transitions to a "2" state which the next time you read it, it will return the bit read, and then reset its internal state to the "0" state.

Now in the main loop, we can call the read\_bit\_async() every iteration of the loop and it will return -1 when it's still "awaiting" the bit but when it received the bit then we get the actual bit value. The main loop can continue to run and process other code while waiting for the bit to be received.

I've used in this past to, for example, write a library that can read keyboard input from a PS/2 keyboard asynchronously alongside the main program. I've also used it to write a communication protocol that could send bytes of data down a single wire asynchronously, so if you have two wires for upstream and downstream data then the two devices could communicate without blocking the main program loop.

For what you are personally trying to do, let's say you receive an HTTP request and you want to respond to it with an HTTP file, but sending out the whole file is too time consuming. You could have each iteration send out only one byte.

You could also have a "listening", "processing", and "responding" state where at first it is listening for a request, and then if it receives one it switches to the "processing" state where it interprets the request, and then after that it switches to the "responding" state where it produces the output.

Also, the second block of code I wrote is not necessarily the most optimal, for example the last two states can be merged into one, but I prefer to write them this way because I find it to be more clear and easier to follow along with.

If you want to create a non-blocking asynchronous function on a single thread, the easiest way to do it is to reimagine the algorithm you're trying to write as a state machine that can be broken up into many many different tiny parts, where enough iterations of these parts can eventually complete task, and then to implement this.

When I say "tiny" I mean mostly in terms of speed. If a single iteration of the function takes too long, it can noticeably interfere with other asynchronous functions, so you want to make sure each iteration can be done in very little time. If a single iteration takes too long, then you should try to figure out how to break it up into even more states.

---
Tags: programming, sketch
---


# Question
Title: Removing spaces between characters in MD_Parola
I'm using ESP8266 and Max7219 module (8\*32) and MD\_Parola library. To create my own font, at first I used of MDParolaFontEditor and created the following fonts.

I edited file MD\_MAX72xx\_font.cpp using Arduino IDE and saved them as 150 and 151. I want to have the output as the following.

But, the output is as:

As you can see, there is a space between them! I think this space is automatically added between characters. My problem is that, how can I remove this space?

My code:

```
void loop () {
char MyText[]={151,150,0};
P.displayText(MyText, PA_CENTER, 0, 0, PA_PRINT, PA_NO_EFFECT);
P.displayAnimate();
delay(3000);
}

```

# Answer
> 2 votes
add this line in the void setup part

P.setCharSpacing(0);

# Answer
> 0 votes
The matrix with the extra space is 9 (not 8) columns wide (possibly because is was designed to be able to display a colon on a clock).

---
Tags: arduino-uno, esp8266, max7219
---


# Question
Title: How to install FTDI Serial Drivers on Mac?
I'm following this tutorial on how to install FTDI drivers on macOS, but am facing some issues. After downloading the USB Serial Driver version 2.4.4 (for OS X 10.14) from FTDI Chip's virtual COM port (VCP) driver page (recommended by the tutorial), I still don't see any `usbserial` option listed under the Serial Port tab, shown below.

Because I'm running macOS Monterrey (12.0.1), I also tried downloading the Beta driver release (version 1.5.0) for OS X 10.15 and macOS 11/12. After running the installer from my Applications folder (as recommended), I get the following result, indicating success, but the options list remains the same as shown above.

Are there any workarounds? For reference, I am using Arduino IDE 2.0.0.

# Answer
I have just managed to get the FTDI set up for my M1 mac using the Pro Mini. I think the issue is that newer macs automatically block the FTDI serial connection from being used as a com port. You need to install a program called **D2XXHelper** to prevent this behaviour.

I did the following, hopefully this will work for you too:

1. Install **FTDI VCP Driver**, found here: Scroll down to first table and find the latest Mac OS drivers. There are 2, the 2.4.4 version and the 1.5 version. I think you need to use the 1.5 version for the M1 but I’m not sure because I installed both before I did the next steps to get it working.
2. Install the **D2XXHelper** found here: Scroll down to first table and look in the comments column for the Mac OS row to find the download link.
3. After installing the D2XXHelper, you should get a security prompt saying **system extension blocked**. Follow this guide which shows how to provide permission for the system extension to be applied – this requires going into recovery mode and requires several computer restarts.
4. After following the steps in the guide, you should have enabled the D2XXHelper system extensions to be applied, in which case when you connect your Arduino to your computer via the FTDI connector, the Arduino IDE 2 should now recognise that a device has been connected via the FTDI virtual com port.
5. **optional** – to check that your FTDI is connected correctly to your Arduino, connect it up, Open a Terminal window and type “ls /dev/tty.\*” and run this command. If the FTDI is connected properly then a usb serial device should show up in the results to this command.
> 2 votes

---
Tags: serial, arduino-ide, usb, ftdi
---


title: LoRa to MQTT sensor data can't be read

text:
# Question
Title: LoRa to MQTT sensor data can't be read
I'm trying to transfer data from a temperature sensor that is located outside my WiFi area. I have chosen LoRa technology between an ESP32 equipped with an SX1278 and a TTGO Lilygo LoRa.

So far everything works fine, but as soon as I try to publish the data via Mosquitto MQTT in order to have access to the home assistant, things are get worse. I use MQTT Explorer to view the exchanges with Mosquitto. I also monitor the data on the serial port. Everything works correctly as long as I don't publish the temperature data. But from the moment I publish it after changing it to string to switch to MQTT, I have some problems:

* The serial port displays wrong values of the string and scrolls continuously.
* The data sent to MQTT are well displayed, coherent with the serial port, but remain incoherent and the number of publications increase quickly.
* From a certain moment, things do not move anymore.

So I have at least two problems, and even though I looked at many examples, I have trouble understanding everything.

You will find attached the code loaded into the Lilygo receiver hoping that it will help solve my problem(s):

```
#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Streaming.h>
#include <Ticker.h>

#define OLED_SDA 21 // Attention: Les broches SDA et SCL de l'affichage OLED sont inversées sur le dessin de LilyGO et sur GitHub.
#define OLED_SCL 22
#define OLED_RST 12 // Note: Le TTGO Lora32 v2 n'utilise pas le signal reset, mais la librairie Adafruit_SSD1306, oui.
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

const int csPin = 18; // LoRa radio chip select-TTGO
const int resetPin = 23; // LoRa radio reset-TTGO
const int irqPin = 26; // change for your board; must be a hardware interrupt pin-TTGO
const int sckPin = 5; //-TTGO
const int misosPin = 19; //-TTGO
const int mosiPin = 27; //-TTGO
const char* ssid = "xxxxxx"; // Nom du wifi
const char* password = "xxxxxx"; // Mot de passe wifi

const char* mqtt_server = "xxx.xxx.x.xx"; // Adresse IP du brovker MQTT
const char* mqtt_username = "xxxxx"; // User MQTT
const char* mqtt_password = "xxxxxx"; // Password MQTT
const char* mqtt_topic = "ESP32/DS18B20/temp_piscine"; // Nom du topic MQTT envoyé par home assistant

char incoming ;
char msg[4];

WiFiClient espClient;
PubSubClient client(espClient);

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);

void setup() {
  Serial.begin(115200);
  while (!Serial);

  // setup WiFi
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  //initialize OLED
  Wire.begin(OLED_SDA, OLED_SCL);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
  }
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(1);
  display.setCursor(0,0);
  display.print("LORA RECEIVER ");
  display.display();

  Serial.println("LoRa Receiver");

  // override the default CS, reset, and IRQ pins (optional)
    SPI.begin(sckPin, misosPin, mosiPin, csPin);
    LoRa.setPins(csPin, resetPin, irqPin); // set CS, reset, IRQ pin

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

//Fonction connexion au wifi appelé dans le setup
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  display.setCursor(0,0);

  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

//Fonction connexion au wifi appelé dans le setup
void callback(char* topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;

  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();
}

//Fonction connexion au serveur Mqtt  dans le loop
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client", mqtt_username, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void loop() {
  client.loop();
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet ");
    // read and print packet
    display.clearDisplay();
    display.setCursor(0,0);
    while (LoRa.available()) {
      incoming = ((char)LoRa.read());
      //Serial.print((char) LoRa.read());
      Serial.print(incoming);
      display.print(incoming);
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
    //display.setCursor(0,0);
    display.print("' with RSSI ");
    display.println(LoRa.packetRssi());
    display.display();
  }
  if (!client.connected()) {
    reconnect();
  }
  dtostrf(incoming, 6, 2, msg);
  Serial.print (msg);
  client.publish(mqtt_topic,msg,false);
  //client.publish(mqtt_topic,dtostrf(LoRa.packetRssi(),6,2,msg),false);
}

```

# Answer
Hello and thank you for your support. I finally found the problem, which was that using incoming needs to be stored in a buffer to be used as it was sent char by char. I also found the possibility to use `LoRa.readString()`, which allows a full string storage. I used after the function LoRaData.indexOf..., which allows to select specific parts of text with specific marks such as #, \*, /, ... Here is an example of the code used for those who could be interested.

```
void loop() {
  client.loop();
// try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize)
{
    // received a packet
    Serial.println("Received packet ");
    // read and print packet
    display.clearDisplay();
    display.setCursor(0,0);
    while (LoRa.available()) //>0 retiré
    {
      String LoRaData = LoRa.readString();
      Serial.print(LoRaData);
    // Get Text, temperature and end text : *Temp.piscine #21.56*C*
      int pos1 = LoRaData.indexOf('#');
      int pos2 = LoRaData.indexOf('*');
      Text = LoRaData.substring(0, pos1);
      temperature = LoRaData.substring(pos1 +1, pos2);
      End = LoRaData.substring(pos2+1, LoRaData.length());
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
     display.print("temperature Piscine = ");
    display.print(temperature);
    display.print("°C");
    display.print("' with RSSI ");
    display.println(LoRa.packetRssi());
    display.display();
      }
}

```

I still need to work on it, but it seems to work fine.
> 2 votes

# Answer
In your `dtostrf(incoming, 6, 2, msg);`, you want to store a float that has a minimum width of 6, with 2-digit precision, you will need an array of at leat 9 bytes(plus NULL terminator) for a value like '12345.78', you only allow 4 bytes for your `msg[4];` which is definitely insufficient.

Even if your temperature is 32.45, it will still need an array of 6 for `msg`.
> 0 votes

---
Tags: programming
---


title: Arduino Timer Drift Issue

text:
# Question
Title: Arduino Timer Drift Issue
I have two Arduinos that communicate over serial. Each arduino runs a TDMA algorithm where each arduino is assigned one timeslot. The arduinos should transmit during their timeslot, which does work fine. However, over time, say 10-15 minutes the arduinos start to overlap their timeslots. To keep time I am using the millis() function to determine when to send a message. I have tried both delay() and manually setting up counters but getting the same drifting behavior. On one of the iterations of the code I had a Serial.readStringUntil() function that was being called during every timeslot and the arduinos stayed in sync for over 13 hours with no detected drift, with an exact timeslot of 1000ms. I now am aware that the delay I was seeing is caused by the timeout parameter, which defaults to 1000ms, in the readStringUntil function, but it does not make sense that there would be no drift when the arduino was delayed in this way. I know that the stability of the ceramic resonator on each arduino would cause drift.

Why would delay(), millis(), and manually configuring timer1 cause drift, but the timeout functionality of the readStringUntil function seemingly does not drift?

Also, is there a better way to setup the timing functionality, the goal is to have the nodes go as long as possible without needing a resync?

The following psuedo is how the timing is currently setup.

```
count = 0;

if(millis() - previous_action >= TIME_SLOT) {
   count++;
   if(correct timeslot) {
       TRANSMIT();
   }
   previous_action = millis();
   loop_back_to_check;
}

```

EDIT: RTC and other devices that can keep the devices sync'd are not in the scope of the project.

# Answer
Any fee-running clock will drift. Worse yet: its drift rate will not be constant. This is a fact of life, and there is nothing you can do about it. There is no software solution, although your software can certainly make things *worse*. What you can do is:

1. Synchronize the clocks of both Arduinos to an external time source. The time source doesn't have be accurate if you only care about the relative drift between the Arduinos. This could be the receiver of the messages sending an acknowledgement at a specific time, or the same receiver sending a pulse on a dedicated line, or an NTP server if your Arduinos are networked, or a radio-broadcast time signal, or a GPS receiver...
2. Use clocks that are so good that their drift becomes irrelevant. The drift rate has to be less than the timing tolerance of your TDMA protocol divided by the expected service life of your devices. A good RTC can give you a drift rate less than about 2 ppm (i.e. 2×10<sup>−6</sup>). If that is not good enough, you may consider an OCXO (oven-controlled crystal oscillator) or an atomic clock (the rubidium-based ones are the most affordable).
3. Calibrate your clocks. As the variations of the drift rate are typically much less than the average drift rate, you can remove most of the drift by first measuring it and then removing in software the value you measured. You are then left with the random variations of the drift rate (“frequency wander”). I suggest you read Arduino clock frequency accuracy to get an idea of the kind of accuracy you can expect.
4. Use temperature control: keep you clocks at constant temperature, as temperature variations are often the main cause of frequency wander. Alternatively, use temperature compensation: measure the drift rate at multiple temperatures, fit a continuous curve through these measurements and use this curve (and continuous temperature measurements) to correct the drift in software.
5. Avoid making things worse with your software: update `previous_action` with

```
previous_action += TIME_SLOT;

```

rather than assigning `millis()` to it, as this approach is *guaranteed* to cause drift.

> Why \[...\] the timeout functionality of the readStringUntil function seemingly does not drift?

Nobody can answer this question without a careful examination of both the specific version of the software you used and the physical setup. It could be that you accidentally implemented a synchronization mechanism. It could be that your measurements were not accurate enough to reveal the drift.
> 3 votes

# Answer
You can use one of the many RTC (Real Time Clock) modules, they are crystal controlled where your Arduino is not. There are several varieties, pick the one you like. There is a large difference in stability between the Arduino timing and the RTC timing. You can update the clocks on a regular basis. Using NTP (Network Time Protocol) which would be very accurate and reliable. You can do the NTP on a regular basis on one unit and have it update the others. Side benefit they will not drift much as the temperature changes.
> 1 votes

# Answer
According to my experience, they are the clients that should follow the server's timing. On the client side:

1. On each server transmission, calculate the ETA (Estimated Time of Arrival and ATA (Actual Time of Arrival) of the message, based on your time slot scheduling and adjust your local clock accordingly.
2. It would be nice to treat all transmissions as timing messages, no matter the destination, just ignore the payload.
3. It is obvious that the client should be a little overhead timed, in case the server's clock is a little faster.
4. For long inactive periods, the server should broadcast a periodic timing message, so that the error will be kept to a minimum.
5. It would be convenient to add a "timing preamble" in each transmission.

With all that in mind, the readStringUntil function is your friend in many ways. By waiting for the timing preamble, you can determine easily the timing error. By waiting for a known postamble, you read "late" messages (don't forget the timeout value!).

Use a bi-numbering scheme for each transmission, one for each client's message and one for each broadcast (total transmissions). Calculate the minimum convenient modulo (overflow) values. Each client will know if there's something missing. (usually, a too-early transmission or a collision)

Although it is communications-medium agile, I would recommend a preamble like:

```
$FF $00 $FF $00 AA BB CC DD EE $FF $FF FF with PAYLOAD following, where:

AA = 1 byte, the destination addr, $00 = Broadcast

BB = 1 byte, message type (optional, $00 for timing msg)

CC = 1..2 bytes, msg no. to this dest.

DD = 1..2 (3?) bytes, total msg no., no matter the dest.

EE = 1 byte, payload length, if variable. (EE<$FF, $00 for timing msg)

FF = 1 byte checksum (optional). (Why should you place it AFTER the "$FF
$FF" combination?)

```

Use the time you receive the "$FF $FF" combination as a time-mark to calculate ATA & ETA. (It is common sense to treat your values so that this combination cannot show before the end of the preamble)

Consider using a postamble, with redundant info & End-Of-Message mark.
> 1 votes

---
Tags: serial, communication, timing
---


# Question
Title: best practice for performance: empty loop() when using interrupt?
I'm working on a little midi hardware project and I'm using `attachInterrupt()` to assign a callback function to an interrupt pin.

Nothing gets done in the loop function, so it looks like this:

```
void loop() { return; }

```

So far this seems to work out, but I'm wondering if this is a bad practice? I tried adding a short delay() call in there instead but I couldn't really measure if it performed better or worse.

# Answer
> 1 votes
There is no particular reason to worry about doing nothing in `loop` \- the processor has to be doing *something* \- you don't need to give it extra work.

Plus, there is an implied `return` at the end of functions, you don't need to add your own.

The bigger issue is that interrupt handlers should be short, so that you don't miss another interrupt while you are doing something lengthy in the first interrupt.

# Answer
> 0 votes
I think I can answer my own question.

I realized that I can keep my state change and debouncing logic in the interrupt routine and move everything else to the loop function, which seems cleaner.

edit: well not necessarily cleaner. I agree with @jsotola, ISR should only do the bare minimum.

In the end I figured not even using an ISR in the first place was even better for my use case.

---
Tags: interrupt, code-optimization, timing, performance
---


# Question
Title: What should I do with stackOverflow in compile error?
I don't have port, but when I want to compile my code (even empty files), I encounter this error:

```
Sketch uses 444 bytes (1%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.

```

The code is:

```
int LED_red=4;
int LED_yellow =2;
int green =0;

void setup() {
  // put your setup code here, to run once:
  pinMode(LED_red,OUTPUT);
  pinMode(LED_yellow,OUTPUT);
  pinMode(green,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LED_red,HIGH);
  digitalWrite(LED_yellow,LOW);
  digitalWrite(green ,LOW);
  delay(5000);
  digitalWrite(LED_yellow,HIGH);
  digitalWrite(LED_red,LOW);
  digitalWrite(green,LOW);
  delay(5000);
  digitalWrite(green,HIGH);
  digitalWrite(LED_yellow,LOW);
  digitalWrite(LED_red,LOW);
  delay(5000);
}

```

```
Sketch uses 998 bytes (3%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.

```

I want a hex address for cordinate this code with Proteus, but it doesn't compile and dosn't give me hex address.

# Answer
> 2 votes
> `Sketch uses 444 bytes (1%) of program storage space. Maximum is 32256 bytes.`
> `Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.`

This is not an error message. Rather, it's a message that results from a successful compile of your empty programme.

> `Sketch uses 998 bytes (3%) of program storage space. Maximum is 32256 bytes.`
> `Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.`

Neither is this an error message. Rather, it's a message that results from a successful compile of your more substantial programme.

To export the HEX file from the Arduino IDE for Proteus, go to:

* Menu bar -\> Sketch -\> Export compiled Binary

The short-cut is `Ctrl+Alt+S`.

You will find the .hex file in the same directory as your sketch.

# Answer
> 1 votes
There is nothing to do.

What you are seeing is *not an error*. It is merely an informational message telling you how much of the available resources your sketch is using. Since it is using far less than the maximum available (as you would expect from an empty sketch) you have no problem.

You only need to worry about those figures when the "amount left" gets too small.

# Answer
> 0 votes
What you are seeing is not an error.

Although your sketch is empty, there is Arduino framework code that gets created with it. This code actually calls your `setup()` and `loop()` functions so things operate as you would expect. It was designed this way to make it eaiser to get started.

# Answer
> 0 votes
You can change the processor settings from Tools--\>Processor--\>Atmega328P(Bootloader). It solved my problem.

---
Tags: arduino-uno, arduino-ide, compile, compilation-errors, error
---


# Question
Title: How do I properly receive MIDI with Arduino, with 6n138?
UPDATE : I still can't receive MIDI as of 2019/07/01.

Here goes so far : I'm trying to follow this schematics from instructables, using 6N138. To make it easier, I'm going to copy his schematics.

===================================

I'm using Arduino Mega. I tried to find specific topic about this and can't find any.

The target is actually send and receive MIDI, then replace the whole Arduino Mega to ESP8266 (probably the ESP-01, or Wemos D1), but I'm afraid it is too specific.

Here's the code so far on PasteBin

Here's my work so far.

The diodes were replaced with LED, because I don't have one Original guide here. But that schematics on that thread also didn't work for some reason.

# Answer
> 2 votes
How to connect 6N138 to Arduino :

Schematics :

Basically the above schematics and installation is already okay, but instead of 1k, I used 10k on 6N138 PIN 7 to GND. VCC to 470 ohm is on PIN 6, also RX out, connected in series.

---

Just in case you want to use 6N137 :

Schematics :

* Pin 5 of the MIDI DIN connector goes to pin 2 of the 6N137
* Pin 4 of the MIDI DIN connector goes via 330 ohm resistor to pin 3 of the 6N137 (so the 6N137 pins and the resistor are connected in series)
* You should also have a reverse connection protection diode between pins 2 and 3 of the 6N137 but I like living dangerously and rely on the diode inside the 6N137
* Pin 8 and 7 are connected to VCC
* Pin 6 is connected to RX
* Pin 5 is connected to GND
* 4.7 kohm pullup resistor between pin 8 and 6 (VCC and signal out)

Adapted from this blog post.

---

How to test it :

1. I used Arduino Mega with this code.
2. I then attached the Arduino Mega to Hairless MIDI, then to loopMIDI.
3. Then I read the MIDI output using MIDIOX.

---

I might update it with H11L1 / PC900 later, if I have some time. Also, I'm going to put this thread in Indonesian in my blog later.

# Answer
> 3 votes
Most start at the midi site at playground.arduino.cc. But there are numerous web sites across the Internet. It is important to understand that the MIDI interface uses a current loop to send and receive data. While the Arduino normally uses voltage levels to communicate. As such, an electronic interface needs to be built or bought to convert between these two types of signals. Some interface designs are simple and limited. Others are complex and robust.

# Answer
> 3 votes
There are plenty of MIDI circuits and most of them are quite simple, mostly an optocoupler (6N137 or 6N138, although I had better luck with H11L1), some resistors and that's mostly it. I also added ferrite beads for EMI protection, but this is not absolutely necessary.

To test your circuit, use a lot of data (e.g. by pitchbend/aftertouch), and play notes meanwhile. If you hear stuck notes (meaning the MIDI Note Off command is missed), you know the circuit is not full proof.

Regarding libraries: the FortySeven Effects library is really easy to use. I used it in the beginning before I moved on to STM32 and having to write my own, but this is a good starting point.

For the schematics I based my circuit of can be found at H11L1 optocoupler.

The best way is to read the official MIDI documentation, see page MIDI 1.0 Specification, than search for

```
Download the Complete MIDI 1.0 Detailed Specification Document (1996)
(Please Register! It's Free!).

```

# Answer
> 0 votes
I use this library with Arduino Uno (where can change bootloader): https://github.com/TheKikGen/USBMidiKliK And after the device is recognized from windows how a Midi device, so not need any other program to interface em.

You can use your preferred sequencer program and your arduino interface is recognized how a midi interface.

The sketch is very simple:

```
    /**********************************************************************************

  KIKGEN MIDI USB
  A MIDI USB RELIABLE INTERFACE
  USB-MIDI simple converter Sketch for Arduino
       USB                           ATMEGA8U2                    ATMEGA 328P
  --------------         ------------------------------         ---------------
  IN Endpoint  o<--------o USBOUT | usbMidiKliK |  RX o<--------o (TX) MIDI IN
  OUT Endpoint o-------->o USBIN  |  firmware   |  TX o-------->o (RX) MIDI OUT

  The RX/TX on the Arduino must no be crossed, as the ATMEGA8U2 is directly connected
  to the RX and TX pins.  When PIN0 (RX) and PIN1 (TX) are configured as INPUT, we
  can talk directly with the ATMEGA8U2 managing the USB, making the Arduino transparent.

************************************************************************************/

void setup() {

  // Make Arduino transparent for serial communications from and to USB

  pinMode(0,INPUT); // Arduino RX - ATMEGA8U2 TX

  pinMode(1,INPUT); // Arduino TX - ATMEGA8U2 RX

}

void loop() {

}

```

And hardware schema is this:

---
Tags: serial, arduino-mega, midi, opto-isolator
---


title: IDE will not upload to ATTiny88

text:
# Question
Title: IDE will not upload to ATTiny88
I was successfully compiling sketches and uploading to various MCUs, including the ATTiny88. Suddenly the IDE quit compiling and complained of various missing compilers. I found and corrected an issue with my anti-virus, which helped some. Eventually I uninstalled and wiped the entire IDE. I then reinstalled from scratch, and now everything compiles OK, butt he IDE will not upload the code to the ATTiny88. This is done a bit differently than other MCUs. Instead of creating a virtual com port, the driver creates a different virtual USB device, and then searches for the MCU on that USB device. The driver should cause the "unknown" MCU to become known to the system, but this does not happen, despite having installed the drivers. The IDE, in turn, does not create a specific error when uploading, but merely times out. How can I get the virtual driver working again? I am running IDE 1.8.13 on a Windows 7 PC.

# Answer
> 0 votes
There is an updated driver that fixes the issue. It will still show as unknown, however it will properly connect for programming when you reset or power up the ATTiny. NOTE: One component will say it failed during install, but it doesn't matter, ignore it, it will work.

Driver is here: https://github.com/MHEtLive/MHEtLiveArduino/releases/download/1.0.0/2.0a4.rar

---
Tags: arduino-ide, atmega328, attiny
---


# Question
Title: Troubleshooting UART communication between nano 33 ble sense r2 and Adafruit Feather 32u4 with LoRa Radio Module
I've tried connecting the gnd's for both the boards and have connected rx to tx and vice versa in both the boards. I've powered both by batteries, and I'm trying to get sensor data from the nano, and trying to send it to the feather via UART, and long distance away using the Lora capabilities of the Feather.

I've loaded this program in the nano:

```
/*
Including libraries
*/
//Accelerometer{
#include "Arduino_BMI270_BMM150.h"
//Accelerometer}
//Temperature and humidity{
#include <Arduino_HS300x.h>
//Temperature and humidity}
//Pressure{
  #include <Arduino_LPS22HB.h>
//Pressure}

/*
Creating variables for sensors
*/
//Acceleration variables{
float x, y, z;
//Acceleration variables}
//Temperature and humidity variables{
float temperature;
float humidity;
//Temperature and humidity variables}
//Pressure variables{
float pressure;
//Pressure variables}

void setup() {

/*
Setting up sensors
*/
Serial1.begin(9600);
//Accelerometer{
  if (!IMU.begin()) {
    Serial1.println("Failed to initialize IMU!");
    int i = 0;
    Serial1.println("Trying again\n");
    while (!IMU.begin()){
      if(i>0){
        Serial1.print(" Failed\n");
      }
      Serial1.print("Try number ");
      Serial1.print(i);
      i++;
      delay(1000);
    }
    Serial1.print("Passed\nOn attempt number ");
    Serial1.print(i);
    Serial1.print("\n");
  }
//Accelerometer}
//Temperature and humidity{
if (!HS300x.begin()) {
  Serial1.println("Failed to initialize humidity temperature sensor!");
  int i = 0;
    Serial1.println("Trying again\n");
    while (!HS300x.begin()){
      if(i>0){
        Serial1.print(" Failed\n");
      }
      Serial1.print("Try number ");
      Serial1.print(i);
      i++;
      delay(1000);
    }
    Serial1.print("Passed\nOn attempt number ");
    Serial1.print(i);
    Serial1.print("\n");
}
//Temperature and humidity}
//Pressure{
if (!BARO.begin()) {
  Serial1.println("Failed to initialize pressure sensor!");
    int i = 0;
    Serial1.println("Trying again\n");
    while (!BARO.begin()){
      if(i>0){
        Serial1.print(" Failed\n");
      }
      Serial1.print("Try number ");
      Serial1.print(i);
      i++;
      delay(1000);
    }
    Serial1.print("Passed\nOn attempt number ");
    Serial1.print(i);
    Serial1.print("\n");
}
//Pressure}
}

void loop() {
  /*
  Read sensor data into the variables
  */
  //Read acceleration{
  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);
  }
  //Read acceleration}
  //Read temperature and humidity{
  temperature = HS300x.readTemperature();
  humidity = HS300x.readHumidity();
  //Read temperature and humidity}
  //Read pressure{
  pressure = BARO.readPressure();
  //Read pressure}

  /*
  Print the sensor data to Serial1 (hopefully implement sending this data to the lora feather, which will radio it to a distant arduino)
  */
  Serial1.print("\nAcceleration (x, y, z): ");
  Serial1.print(x);
  Serial1.print(", ");
  Serial1.print(y);
  Serial1.print(", ");
  Serial1.print(z);
  Serial1.print("\nTemperature: ");
  Serial1.print(humidity);
  Serial1.print("\nHumidity: ");
  Serial1.print(humidity);
  Serial1.print("\nPressure: ");
  Serial1.print(pressure);
  delay(1000);

}

```

I've loaded this program in the transmitting feather:

```
/* The program for the feather1 to take information from nano 33 ble sense rev2 and radio it to  where the feather2
** will communicate to the ground station's program todisplay the data in a user friendly manner, and will display results
*/
#include <RH_RF95.h>

// LoRa settings
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7
#define RFM95_FREQ 915.0

RH_RF95 rf95(RFM95_CS, RFM95_INT);

void setup() {
  Serial.begin(9600);
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);
  delay(100);
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);
  if (!rf95.init()) {
    Serial.println("LoRa init failed. Check your connections.");
    while (1) ;
  }
  rf95.setFrequency(RFM95_FREQ);
  rf95.setTxPower(23, false);
  Serial.println("LoRa Transmitter Ready!");
}

void loop() {
  static uint16_t messageCount = 0;
  String input;
  while (Serial.available() > 0) {
    char c = Serial.read();
    input += c;
  }
  if (input.length() > 0) {
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    input.getBytes(buf, input.length() + 1);
    rf95.send(buf, input.length() + 1);
    rf95.waitPacketSent();
    Serial.println("Sent message #" + String(messageCount) + ": " + input);
    messageCount++;
  }
  delay(1000);
}

```

I've got this program in the receiving feather:

```
/* The program for the feather2 to recieve information from feather1 ** and will communicate to the ground station's program todisplay the data in a user friendly manner, and will display results
*/

#include <RH_RF95.h>

// LoRa settings
#define RFM95_CS 8
#define RFM95_RST 4
#define RFM95_INT 7
#define RFM95_FREQ 915.0

RH_RF95 rf95(RFM95_CS, RFM95_INT);

void setup() {
  Serial.begin(9600);
  while (!Serial) ; // Wait for serial port to be available
  /* The infinite while loop above not needed if you're not using rx/tx for sending
  ** the recieved radio data to your program or are using some other method to
  */
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);
  delay(100);
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);
  if (!rf95.init()) {
    Serial.println("LoRa init failed. Check your connections.");
    while (1) ;
  }
  rf95.setFrequency(RFM95_FREQ);
  rf95.setTxPower(23, false);
  Serial.println("LoRa Receiver Ready!");
}

void loop() {
  if (rf95.available()) {
    uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
    uint8_t len = sizeof(buf);
    if (rf95.recv(buf, &len)) {
      Serial.print("Received: ");
      Serial.println((char*)buf);
    } else {
      Serial.println("LoRa receive failed");
    }
  }
}

```

I have been able to establish UART communication between two Unos before, but I'm unable to find out why it isn't working in this case. I can confirm it isn't working because the Serial monitor for the recieving feather (feather2) only shows this:

```
17:52:39.840 -> LoRa Receiver Ready!

```

Why this is happening, and any potential fixes for this?

# Answer
As I see 32U4 I'd expect the Serial is used for native USB serial (CDC). If you want to use usart on pins 0 and 1, you'd have to use Serial1 instead.

Nano 33 BLE is the same, it has native USB and you are correctly using Serial1 for accessing serial pins 0 and 1 (however nRF52840 can use any pins).
> 0 votes

---
Tags: communication, uart, feather, arduino-nano-33-iot
---


# Question
Title: D1 mini esp8266 error: esptool.FatalError: Failed to connect to ESP8266: Timed out waiting for packet header
I am pretty sure this device worked yesterday. I tried to short GPIO0 to ground (flash), nothing. I have a second ESP that uploads fine, but this one does not.

Is their another way to get this bootloader to open up? Or am I the owner of a brand new door stop?

# Answer
> 3 votes
I'm not sure if this will help EVERYONE, but I hope it at least helps someone. I had the same issue with several different boards (3 Nano's, 2 NodeMCU ESP8266's, and 1 Uno). I searched and searched for an answer and I kept reading about this pin or that pin being "pulled low" or "pulled hi" interfering with uploading sketches. Well, since I couldn't find a solid answer anywhere I decided to disconnect all of the peripherals hooked to my board (except for powers and grounds) and Wah Laa!!! The sketch uploaded like it was supposed to. So, I believe if you just unhook all of the sending and receiving pins from all of your peripherals during upload, the sketch should upload just fine. I hope this helps you.

# Answer
> -1 votes
You must use the Arduino only as a pass-thru! -\> So for programming the the esp8266, you need to BRIDGE the Arduino-RESET to GROUND!

---
Tags: esp8266, pins, bootloader, flash
---


title: AD7768-1 library " Arduino "

text:
# Question
Title: AD7768-1 library " Arduino "
I am working on a project and I need an AD7768-1 library to make this analog-digital-converter talk to my Arduino using SPI. " The AD7768-1" doesn't exist in Arduino's library. Thanks in advance.

# Answer
> 1 votes
At present, there is no Arduino library available for this device. As suggested by @chrisl, the easiest way to proceed would be to develop your own driver. However, if you wish to leverage all the advanced features of the device, you could use the drivers provided by Analog Devices. The AD7768-1 differs significantly from the AD7705/6!!!. Having personally interfaced with this device (and AD7768/AD7768-4) using STM32 microcontrollers and Xilinx FPGAs, I would recommend using the no-OS drivers provided by Analog Devices. This approach has worked well for me using an STM32:

1. Please read this article first: Understanding and Using the No-OS and Platform Drivers.
2. And this one:No-OS Overview.
3. Gather all the necessary files you would need from the Analog Devices Github repository no-OS:
4. Get AD7768-1 drivers from the "/drivers" folder.
5. Get Platform Drivers from "drivers/platform/". Since we are using STM32, then pick one of these three (STM32, MBED or Generic):**/STM32**: suitable for STM32CubeIDE or similar. I will use this one. **MBED**: for MBED platforms. Check this out AD7768-1 IIO Application. **Generic**: With this one, you need to fill-in platform peripheral calls manually (in the case of Arduino platforms, this would be something like *SPI.beginTransaction*, etc.). All the associated source and header files are available in the same repository. *To simplify, I would assume you are using STM32CubeIDE and you just want to configure and read data from the device. Then,*
6. Configure the STM32 Microcontroller as an SPI Master-Full-Duplex MODE 3 \[MOSI, MISO, CLK\].
7. Slave select PIN software-controlled \[SS\].
8. \[Optional\] One Pin for data-ready interrupts \[DRDY\].
9. Place the required source and header files in their respective folders. At a minimum, you need (ad77681.c/h, no\_os\_spi.c, stm32\_spi.c, no\_os\_gpio.c, stm32\_gpio.c) and all their linked header files.
10. Initialize No-OS drivers and platform drivers. It would be something like this:

```
struct stm32_spi_init_param stm32_init = {
      .chip_select_port = 1,
      .get_input_clock = &HAL_RCC_GetPCLK1Freq
  };

```

---

```
struct no_os_spi_init_param spi_init_param = {
      .device_id = 1,
      .max_speed_hz = 64000000,
      .chip_select = 6,
      .mode = NO_OS_SPI_MODE_3,
      .bit_order = NO_OS_SPI_BIT_ORDER_MSB_FIRST,
      .platform_ops = &stm32_spi_ops,
      .extra = &stm32_init ,
      .parent = NULL
  };

```

---

```
 struct ad77681_init_param ad77681_init = {
      .spi_eng_dev_init = spi_init_param,
      .power_mode = AD77681_MEDIAN,
      .mclk_div = AD77681_MCLK_DIV_8,
      .conv_mode = AD77681_CONV_CONTINUOUS,
      .diag_mux_sel = AD77681_AIN_SHORT,
      .conv_diag_sel = false,
      .conv_len = AD77681_CONV_24BIT,
      .crc_sel = AD77681_NO_CRC,
      .status_bit = 0,
      .VCM_out = AD77681_VCM_2_05V,
      .AINn = AD77681_AINn_ENABLED,
      .AINp = AD77681_AINp_ENABLED,
      .REFn = AD77681_BUFn_ENABLED,
      .REFp = AD77681_BUFp_ENABLED,
      .filter = AD77681_SINC5,
      .decimate = AD77681_SINC5_FIR_DECx32,
      .sinc3_osr = 0,
      .vref = AD77681_VOLTAGE_REF,
      .mclk = AD77681_MCLK,
      .sample_rate = AD77681_DEFAULT_SAMPLING_FREQ,
      .data_frame_byte = AD77681_DECIMATION_RATE,
  };

```

---

Finally setup the Device like this:

---

```
struct ad77681_dev *device = NULL;
struct ad77681_status_registers *status = NULL;
int32_t init_status = ad77681_setup(&device, ad77681_init, &status);

```

---

If the init\_status is 0 then you’ve successfully initialized the device!! You would read data like this:

---

```
ad77681_spi_read_adc_data(device, data_buffer, AD77681_REGISTER_DATA_READ);

```

---

I hope this is helpful.

---

---
Tags: arduino-uno, spi, communication, adc
---


# Question
Title: Correctly connecting a four-pin tilt sensor to a breadboard before going live
I'm working on Arduino Kit book's Project 8: the digital hourglass. I've got the picture and the circuit diagram below.

My question is a fundamental one, and I really don't know how others figured it out. The question is: How do I correctly tie a four-pin tilt sensor to the power and to the ground? I've been through a couple of datasheets for the RBS040100 and none of them were particularly helpful in determining which pin is responsible for what. The most helpful anything has got to be is this pdf sheet where the PCB layout diagram points out an index for every pin and how the pins within the sensor are related, yet it does not explain where the power goes and where the ground is connected.

I also ran into this Arduino SE page but nobody got close to actually explaining how to use (i.e., correctly integrate) the sensor into the circuit.

I know that if you plug a capacitor in the wrong way, it may explode. By the same token I do not want to screw up the sensor or the board, but what do I know. This is the only tilt sensor I've got.

Before my board goes live, I'd like to confirm whether I have the tilt sensor connected correctly.

Any help would be appreciated. Let me know if you need anything else for further clarification. Thank you in advance.

Edit: Here's a picture of the four-pin tilt sensor:

# Answer
> 0 votes
So I've asked this question on the Arduino.cc forum (just to get a safe answer quickly to hustle up on the project). If you look at the pins on the four-pin tilt switch with the notch facing down (as shown on the aforementioned RBS040100 datasheet's PCB layout diagram), you need to know that the connected pins 1 and 2 are to be tied to the power and the connected pins 3 and 4 are to be tied to the ground **with a high-Ohm-value resistor (which will serve as a pull-down resistor, e.g. 10kOhm)**. That means that the "up" arrow on my pictures is indeed to face "east" (in relation to the breadboard) if northern pins are power and southern pins are grounded with a resistor. If for some reason you need it pointing "to the west", then the pins on the northern half are to be connected to ground with a good resistor and the pins to the south are to be connected to power.

Edit: Here are the results. Image 1 is for the first take and image 2 is for the second take after a tilt to the switch.

# Answer
> 0 votes
Like any switch, this is a passive device. It doesn't require power to operate, in the usual sense - it has no active circuitry. Read it just like a push button. Wire one side to a pullup (or pulldown) and an input pin, and the other side to ground (or to +V). When the input is in it's non-passive state (opposite the state it is being pulled to), the device is tilted. The metal ball inside it just shorts two pins (or not).

The only thing that isn't clear from the data sheet is whether all four device pins are independent so the device could indicate one of four directions of tilt (and therefore needs four input pins); or the pins are internally connected in pairs, and only one direction of tilt can be indicated (with a single input pin). A quick experiment should resolve that.

A search for 'tilt sensor' yields a page on arduino.cc relating to tilt sensors and apparently refers to the latter type (one direction of tilt, one input pin). The remaining question is whether your sensor is of the same type.

# Answer
> 0 votes
A tilt switch is just a switch and doesn't need to be powered per se. You just need to detect when it is open or closed, like any other mechanical switch. I have a page about switches: http://www.gammon.com.au/switches

In brief, you can wire a switch with a pull-down resistor as you appear to have done in the end:

In this configuration the input pin will be 0V (LOW) when the switch is open and 5V (HIGH) when it is closed.

---

Or, you can wire it with a pull-up resistor:

In this configuration the input pin will be 5V (HIGH) when the switch is open and 0V (LOW) when it is closed.

---

Or, you can use the internal pull-up of the processor and wire it like this:

In this configuration the input pin will be 5V (HIGH) when the switch is open and 0V (LOW) when it is closed.

In this case your code might be:

```
const byte switchPin = 8;

void setup ()
  {
  Serial.begin (115200);
  pinMode (switchPin, INPUT_PULLUP);
  }  // end of setup

void loop ()
  {
  if (digitalRead (switchPin) == LOW)
     {
     Serial.println ("Switch closed.");
     delay (1000);
     } // end if switchState is LOW

  // other code here ...

  }  // end of loop

```

---

Your switch appears to have 4 pins rather than two. Maybe they work in different planes (eg. tilting left/right for one and up/down for the other) or maybe they work at different angles of tilt. A quick check with a multimeter should confirm that.

---
Tags: arduino-uno, sensors, switch
---


# Question
Title: If I reduce ADC sample rate, do I get an average over the time period?
I am working with a ESP32-C3 devkit. I am using the internal ADC on that chip to read from an analog microphone. I initialize the ADC like this:

```
adc_continuous_config_t dig_cfg = {
    .sample_freq_hz = 20000,
    // ...
};
ESP_ERROR_CHECK(adc_continuous_config(handle, &dig_cfg));

```

If I reduce the sample frequency to, say 1000 Hz, then will each sample represent, roughly, an average of 20 samples from my previous stream (where the sample frequency was 20,000 Hz)? Or is it more like I will get just one out of every 20 samples from the original stream?

The reason I ask is that I'm hoping to perform a kind of low-pass filter by changing the ADC sampling frequency and I'm wondering what's going on inside the ADC hardware when I change the sampling frequency.

# Answer
Possibly not. The ADC on the Arduino Uno (a different processor, I know) uses the "sample and hold" technique. This means that the ADC samples the input voltage at a point in time, copying it into a sample-and-hold capacitor. It then successively compares it to be above or below threshold voltages to generate the individual bits of the resulting number. I have some details about the Uno ADC here.

It probably does this so that, when sampling a rapidly changing signal (like audio) it samples a moment in time, rather than having the comparison be of a signal that is changing over time.

I can't find technical details for the ESP32 ADC sampling method, but it seems likely that a lower sample rate will simply sample less data points, not take an average. This could lead to wildly inaccurate results.

You might want to check out the Nyquist Frequency to see the reasons for choosing a certain sample rate.

If you want an average, feeding the signal into a suitably-sized RC filter might be a good way of finding an average voltage.
> 1 votes

---
Tags: esp32, adc, signal-processing
---


# Question
Title: How do I make the Arduino print on my Mac's Arduino IDE through Bluetooth?
This is a basic question, but I really have tried my best to find a solution on the internet to no avail.

I have a fairly normal setup. HC05 module connected to an Arduino. The HC05 is also connected to my Mac's Bluetooth (fairly sure of this bc I used AT Commands to confirm). However, when I select the HC05 port in the Arduino IDE, nothing is printed in that port's serial monitor. Am I fundamentally misunderstanding something?

How do I make the Arduino print on my Mac's Arduino IDE through Bluetooth?

Here's my code:

```
#include <SoftwareSerial.h>

SoftwareSerial MegaloDon(10, 11);

bool isConnected = false;

void setup() {
  pinMode(9, HIGH); //this pin is connected to "EN" on the HC05 and enables AT commands
  Serial.begin(9600);
  MegaloDon.begin(9600); //
  connectBluetooth();
}

void connectBluetooth() {
    digitalWrite(9, HIGH);
    MegaloDon.println("AT"); //AT command
    if (MegaloDon.find("OK")){
      MegaloDon.println("Bluetooth ON");
      digitalWrite(9, LOW);
      Serial.println("Connected");
    } else {
      Serial.println("Attempting to reconnect...");
      delay(2000); // wait 2 seconds before trying again
    }
  }

void loop() {
  if (isConneced()) {
    Serial.println("conneced?");
    **//I'd like to transmit data to my mac's serial monitor on the Arduino IDE here**

  } else {
    Serial.println("not conneced");
    connectBluetooth(); // Attempt to reconnect
  }
}

bool isConneced(){
  Serial.println("is it conneced?");
  digitalWrite(9, HIGH);
  MegaloDon.println("AT");
    if (MegaloDon.find("OK")){
      isConnected = true;
    }
    else{
      isConnected = false;
    }
    digitalWrite(9, LOW);
}

```

# Answer
I see two problems:

1. Your AT commands don't actually confirm, that the HC05's bluetooth is connected to anything. You are only ever sending "AT", which sets the HC05 to AT mode for a specific amount of time. So basically you are only testing the Serial connection between the Arduino and the HC05. If you want to get other information from the HC05, you need to get into AT mode and then use other AT commands (so commands with the "AT" at the start but other information following that) to check the connection.

So the question is: Is the HC05 really connected to the Mac? The HC05 can be either in device or master mode for bluetooth. When in device mode, the Mac will be able to initiate the connection (like with any other bluetooth device like a headset). When it is in master mode, it itself has to initiate the connection (then the Mac would need to be the device), which would need to be done with AT commands. How exactly do you know, that the HC05 is connected to the Mac and that you are looking at the correct port in the Arduino IDE? Does the port vanish and reappear, when you turn the Arduino/HC05 combo off and a little bit later on again?
2. In your code you are only sending data through the `MegaloDon` interface at one point:

```
 MegaloDon.println("Bluetooth ON");

```

All the other calls to `MegaloDon` are the "AT" command. And this line is executed directly after sending "AT" to the HC05 and getting "OK" back. Do you remember what I wrote above? The "AT" command will set the HC05 to AT mode for a limited amount of time (typically 1 or 2 seconds). The firmware on the HC05 will then try to interpret all data send in this time as AT commands. It will not send this data through the bluetooth interface! So, if you want to send that data to the Mac, then you should wait with sending it for a bit, so that the HC05 is no longer in AT mode.
> 1 votes

---
Tags: arduino-uno, bluetooth, softwareserial, hc-05, mac-os
---


# Question
Title: tone() corrupts the PWM on a different pin
I have to use PWM to control some lights. I do this successfully with: `analogWrite(11, 127);` for a 50% PWM pulse on `pin 11`.

Now, i also have to have `tone()` support on my code. When I do: `tone(10, melodyArray[thisNote], noteDuration);` I invoke the `tone()` function on `pin 10`.

When I do so, then PWM pulse is corrupted. Since I do not have an oscilloscope, I cannot exactly understand what happens. But from the effects on the lights, I can speculate that the PWM pin (`pin 11`) is always `HIGH` or always `LOW`.

It is obvious that the PWM pin and the `tone()` pin are different.

Why does this happen? Perhaps the `tone()` uses some timers that interfere with the PWM? When I comment out the `tone()` line, the PWM works as intended.

Is there a solution to this? Can I use the tone() function and still have `PWM` support (on another pin)?

# Answer
To quote from the Arduino documentation of `tone()`:

> Use of the tone() function will interfere with PWM output on pins 3 and 11 (on boards other than the Mega).

So yes, you should use a different pin than 3 or 11 for `analogWrite()`. This is because `tone()` will configure the hardware Timer2 for outputting these timed signals via hardware. PWM on these pins is also tied to Timer2. When both functions are trying to configure Timer2 in a different way, there will be conflicts.

Note: The documentation talks about "boards other than the Mega", which was true when there weren't other Arduino boards than the old Uno/Nano/Mini (based on the Atmega328p). Nowadays there are so much boards, which all can be programmed with the Arduino framework, that this sentence is a real stretch. Instead I would say "on boards based on the Atmega328p". Depending on your used board your mileage may very. Check the microcontrollers datasheet for the hardware Timers it has and their connected pins.
> 4 votes

---
Tags: pwm, audio
---


title: Is my 8x8 led matrix module broken?

text:
# Question
Title: Is my 8x8 led matrix module broken?
I have an Arduino Mega set up with an 8x8 led matrix as laid out in this circuito.io project: https://www.circuito.io/static/reply/index.html?solutionId=6013e67aeaa9ed0030f668fb&solutionPath=storage.circuito.io

But when I plug in the usb cable, it looks like this:

I'm using the default code supplied by circuito.io (this was just meant to be a "hello world" jumping off point)

When I run the code, some of the leds flicker on and off, but the ones that are on in the image tend to stay on regardless.

# Answer
It's likely that it is just the orientation of the module is wrong. Pull out the LED module, rotate 180 degrees, put it back in and it should work. The dot point should be on the bottom right.
> 1 votes

---
Tags: led-matrix
---


# Question
Title: How to produce multiple DC voltages for a single project with different dc requirements
I have a project that has 2 12V .2 amp fans, and 1 30 3 amp LED COB panel, and a 5 V Arduino. I was wondering if there was a simple method to power all of these devices from a 120 V wall outlet?

As of right now considering a 30 volt AC to DC power supply. Then a series of switch buck converters. Or something along these lines.

Thanks for the help.(also I realize there was a similar post before but wanted some additional insight)

# Answer
> 2 votes
If it wasn't for the LED panel then I'd say use a mains to 12V DC power supply. You can then get small off the shelf switching regulator modules that with the addition of a couple of capacitors will reduce that down to 5V for the arduino.

If you genuinely need 3A at 30V (90 Watts of LEDs? That's a LOT of light) then use a compatible mains supply for that. You can get off the shelf switching modules that will drop from ~30V down to 12V 1A, they are a little more expensive than 12V to 5V parts, mainly because it's a less common requirement, but a quick search on RS shows up some options for around $15.

---
Tags: power, electronics, voltage
---


title: MKR 1010 voltage confusion

text:
# Question
Title: MKR 1010 voltage confusion
I'm very confused about powering my MKR 1010 on a breadboard. It says use USB, but that is 5.5 V and it specifically says never go above 3.3 V, yet there is a 5 V pin. So what size external power supply do I need and where to attach it? Some sites say anywhere from 3.3 to 7 V and even 12 V????

# Answer
> -1 votes
As per the reference at Arduino Docs! it's nominal input voltage is between 5-7V. But make sure you apply in between 3.3V - 5V. And remember to supply it at power socket and not the 5V port itself.

---
Tags: voltage, mkr1010
---


# Question
Title: How to connect a NRF24L01 to a Wemos D1 R2
I have troubles to connect a NRF24L01 transceiver to a Wemos D1 R2 board. I succeeded on an Arduino Uno. Does anyone know the pinout?

I used (same as with Uno):

```
D13 - SCK
D12 - MI
D11 - MO

D8 and D9 for CE and CSN

```

Code:

```
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

// NRF24 Radio
#define CE_PIN   'D8'
#define CSN_PIN  'D9'

RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

// NRF24 Radio
radio.begin();
if (!radio.isChipConnected()) {
  Serial.println("ERROR: NRF24 Chip not connected");
} else {
  Serial.println("NRF24 Chip connected");
  radio.setDataRate( RF24_250KBPS );
  radio.setRetries(3,5); // delay, count
  radio.openWritingPipe(slaveAddress);
}

```

Result: ERROR: NRF24 Chip not connected

If I use:

```
#define CE_PIN   8
#define CSN_PIN  9

```

then Wemos crashes (reboot exception (4)) so I tried with D, but I get a warning, maybe related:

```
warning: multi-character character constant [-Wmultichar]
   22 | RF24 radio(CE_PIN, CSN_PIN); // Create a Radio
      |            ^~~~~~
 warning: multi-character character constant [-Wmultichar]
   22 | RF24 radio(CE_PIN, CSN_PIN); // Create a Radio

```

# Answer
> 0 votes
Select Wemos D1 R2/mini in Tools menu in IDE. Then you can use the Dx names of the pins. Don't put them in quotes.

Since D8 is CS pin at the Uno pin 10 location, you can't use it as CE. And because esp8266 has less pin than Atmega328 of Uno, there is no pin D9. I recommend you to use pins D1 and D2 for CE and CSN.

```
RF24 radio(D1, D2);

```

Here you can read how the Dx pins are mapped to esp8266 pins and what is the common function of the pins.

---
Tags: arduino-uno, spi, nrf24l01+
---


# Question
Title: fastLED help - special reinforcements needed
Hello help needed trying to get fastLED to start and stop at specific points on the strip, i have this nice fade animation but need to split the strip intov about 3 sections and have it run at different times.

here is the mess i have made any help welcome...

```
#include <FastLED.h>
#define NUM_LEDS 60
#define DATA_PIN 6 //How boring and obvious!
#define COLOR_ORDER GRB //Green (G), Red (R), Blue (B)
#define CHIPSET WS2812B
#define BRIGHTNESS 60
#define VOLTS 5
#define MAX_AMPS 500 //value in milliamps

//ENOUGH NONSENSE!

CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<CHIPSET,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setMaxPowerInVoltsAndMilliamps(VOLTS, MAX_AMPS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();
  FastLED.show();
}

void loop() {
  fadeToBlackBy(leds, NUM_LEDS, 4);      // Smaller value = longer tail
  int i = (millis()/40) % NUM_LEDS;      // How fast it goes.
  leds[i] = CRGB::White;
  FastLED.show();
}

```

Cheers Rob

# Answer
Here is an example sketch that shows how to manipulate data in a sub-section of an array.

https://wokwi.com/projects/362275278547275777

The important thing to understand, is that the `FastLED.show();` is the function that does the sending of the `leds[]` array contents to the physical LED strip.

That means that you can do anything you want to the `leds[]` array, and the changes will not be visible until the `show()` function is called.

You can make changes in bits and pieces, without seeing the change increments.

This sketch also shows how to use timers to synchronize actions

```

#include <FastLED.h>

#define CHIPSET     WS2812B
#define COLOR_ORDER     GRB         // Green (G), Red (R), Blue (B)
#define NUM_LEDS         95
#define DATA_PIN          3
#define BRIGHTNESS      255
#define VOLTS             5
#define MAX_AMPS        500         // value in milliamps

CRGB leds[NUM_LEDS];                // main LED array
CRGB test[10];                      // set up separate array for merging with main LED array
                                    // kind of a sprite
int indx = 0;

boolean tick[4] = {false, false, false, false};    // countdown timers flags

unsigned long timeInterval  [4] = {10, 20, 1, 2};  // timers load with these values
unsigned long timeCounter   [4];                   // these are the actual timers

unsigned long previousMicros = 0;

void setup() {

  Serial.begin(115200);

  FastLED.addLeds<CHIPSET,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS);
  FastLED.setMaxPowerInVoltsAndMilliamps(VOLTS, MAX_AMPS);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();

  memcpy(timeCounter, timeInterval, 4 * sizeof(long));  // preload timers
}

void loop() {

  unsigned long currentMicros = micros();

  if (currentMicros - previousMicros >= 1000) {   // 1 ms tick
    for (int i = 0; i < 4; i++) {
      previousMicros = currentMicros;

      timeCounter[i]-- ;                          // keep track of 4 time intervals
      if (timeCounter[i] == 0) {
        timeCounter[i] = timeInterval[i];         // reached zero, reload counter and emit a "tick"
        tick[i] = true;
      }
    }

    // fade sections of leds[] array at different rates
    // NOTE: "&leds[0]" and "leds" both point to the beginning of the array
    fadeToBlackBy(&leds [0], 30,  3);               //  long tail
    fadeToBlackBy(&leds[30], 30, 10);               //   mid tail
    fadeToBlackBy(&leds[60], 30, 20);               // short tail
    fadeToBlackBy(&leds[90],  5,  1);               // really long tail

    if (tick[0]) {    // 10 ms tick
      tick[0] = false;
      leds[indx] = CRGB::White;                   // add the "running dot" after fades are applied
      indx++;
      if (indx > (NUM_LEDS-1)) indx = 0;
    }

    if (tick[1]) {    // 20 ms tick
      tick[1] = false;

//    the &test[0] points to the array element directly
//    it allows the choice of a starting point for the fade function

//    fadeToBlackBy( test,    3, 16);               // these two lines are the same
      fadeToBlackBy(&test[0], 3, 16);               // fade only first three elements in the array
      fadeToBlackBy(&test[3], 1, 20);               // fade only the third element in the array

      if(test[0].r < 64){                           // pixels faded enough
        test[0]= CRGB(248, 11, 130);                // reload pixels
        test[1]= CRGB(221, 245, 6);
        test[2]= CRGB(112, 16, 236);
        test[3]= CRGB(16, 236, 53);
      }
    }
    memcpy(&leds[10], test,     4 * sizeof(CRGB));    // apply 4 pixels to leds[] array
    memcpy(&leds[50], &test[0], 4 * sizeof(CRGB));    // apply 4 pixels to leds[] array
    memcpy(&leds[80], &test[1], 3 * sizeof(CRGB));    // apply 3 pixels to leds[] array

    FastLED.show();                                   // send pixel data to the LED strip
  }
}

```
> 2 votes

---
Tags: led
---


# Question
Title: Creating an IPAddress object from an unsigned int
If I create an IPAddress object using a decimal IP address, it appears to be reversed. What am I doing wrong? See code examples below.

```
IPAddress addressOne(192,168,50,1);
Serial.print(addressOne);                // ==> prints "192.168.50.1"

//The decimal version of 192.168.50.1 is 3232248321
unsigned int iAddress = 3232248321;
IPAddress addressTwo(iAddress);
Serial.print(addressTwo);                // ==> prints "1.50.168.192"

```

# Answer
> 0 votes
You just found out that this `IPAddress` constructor interprets its parameter in little endian order. Then encode your address as little-endian:

```
//The decimal version of 192.168.50.1 is 20097216
unsigned int iAddress = 20097216;

```

---
Tags: programming
---


# Question
Title: Using Serial Plotter with Visual Studio Code
I'm using the Visual Studio Code extension to develop for Arduino which works great.

It doesn't have a Serial Plotter like the regular Arduino IDE, which I need to debug this project. I can run the Arduino IDE's Serial Plotter alongside Visual Studio Code without too much of a problem.

However, if I try to compile and upload from Visual Studio Code while the Arduino IDE is running, the port is busy (not a surprise):

```
avrdude: ser_open(): can't open device "/dev/cu.usbmodem14201": Resource busy
An error occurred while uploading the sketch

```

So I have to keep exiting and relaunching the Arduino IDE every time I build.

Anyone have a suggestion for how to work around this? Using an iMac as development environment.

# Answer
Without very specialized software that can create two new devices with the correct "teeing" policy, it's not going to be possible. Only one program can open a serial port at a time (certainly and have it get anything intelligible out of it...)

I would suggest you may want to add a second serial port. Use an FT232 adaptor to communicate on another serial connection (or a SoftwareSerial connection at a pinch) for your debugging information. You really want a board with more than one serial port for this - or a board with a native USB for programming and a hardware serial port for data communication.

Another alternative is to ditch the serial for programming altogether and program your board through a dedicated programmer, thus leaving your serial port free for data communication.
> 3 votes

# Answer
Try teleplot extension in vscode
> -1 votes

---
Tags: debugging, visualstudio
---


# Question
Title: help with error: cant open device "\\.\COM6":Access is denied
I built a new pc which I use as a flight simulator. On my old PC I had ArduinoIDE for programming a pro micro as well as a teensy 4.1 using the teensyduino library. I installed all the necessary libraries and can make revisions to the code for the Teensy and successfully upload them. However when I try to upload anything to the arduino I get the above mentioned error. The old pc could program the arduino without a problem.

The arduino is showing up in device manager and it disappears when the usb cable is unplugged. The correct port is chosen in the tools menu and I can get the board info. I just can upload it to the board. Still using windows 10 pro, the same OS as on the previous pc.

Running the arduino IDE (v2.1.0) as admin does not help.

# Answer
Installing Arduino 1.8.19 solved the problem. I guess v2.1.0 has some code that trips over itself.
> 0 votes

---
Tags: arduino-ide, arduino-leonardo
---


# Question
Title: Why does the interrupt not work after pressing the button
Implement interrupt processing when the button is pressed, and the very start on the rising edge, the interrupt pin and to which the button is connected 11. Why does the interrupt not work after pressing the button?

```
#include <PinChangeInterrupt.h>

const uint8_t buttonPin = 11;
volatile bool buttonPressed = false;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachPCINT(buttonPin, buttonISR, RISING);
  Serial.begin(9600);
}

void loop() {
  if (buttonPressed) {
    Serial.println("Button pressed!");
    buttonPressed = false;
  }
}

void buttonISR() {
  buttonPressed = true;
}

```

Model:

# Answer
I just tested proper code with some changes:

```
#include <PinChangeInterrupt.h>

const uint8_t buttonPin = 11;

volatile bool buttonPressed = false;

void buttonISR() {
  buttonPressed = true;
}

void loop() {
  if (buttonPressed) {
    delay(20);
    buttonPressed = false;

    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING);

  pinMode(LED_BUILTIN, OUTPUT);
}

```

And with `attachPCINT(digitalPinToPCINT(buttonPin), buttonISR, RISING);` it works flawlessly. Only difference is that `digitalPinToPCINT` (as every example for PinChangeInterrupt library tries to suggest).

You also tried attachInterrupt + digitalPinToInterrupt with the pin 11, but Arduino Uno has only two external interrupt capable pins D2 and D3. So it couldn't work with D11. It also depends on MCU (see attachInterrupt() reference).

The PCINT is more or less related to the old AVRs like Atmega328 or Atmega2560. And PCINT in Atmega2560 isn't available on all port (it uses ISR per port and it has many ports.

If the proteus simulator is the cause, you can also ommit the ISR (as you are not doing anything big here) and just poll the pin:

```
const uint8_t buttonPin = 11;
bool buttonPressed = false;

void loop() {
  bool pinHigh = (digitalRead(buttonPin) == HIGH);

  if (pinHigh && buttonPressed) { // button released
    delay(20);
    buttonPressed = false;
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  } else if (!pinHigh && !buttonPressed) {
    buttonPressed = true;
  }
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
}

```
> 2 votes

---
Tags: arduino-uno, interrupt
---


# Question
Title: Tone() generates a high pitched sound when button is released
I have a simple circuit that makes use of the `tone()` function to produce some sounds. I also have a button, hooked with an interrupt function, that whenever is pressed, a variable changes.

Sometimes, when the button is pressed, a high pitched sound is produced. What is weird is that this does not happen every time.

You can take a look at this simulation: https://wokwi.com/projects/291958456169005577

If you press the buttons continuously, you will hear the sound.

Why is this sound triggered? Is there a way to mitigate this? Perhaps making changes to the `tone()` function? Or perhaps placing a low-pass filter - as this seems like a high frequency sound?

# Answer
Here is the result of my investigation.

The problem is caused by two factors.

First one is the contact bounce of the switch.

Second one is inadequate pullup strength at the switch, but this may be a simulator issue.

The attached picture shows the data that was captured by the Wokwi logic analyzer module.

The top trace pair shows the tone when the switch bounce is turned off in the simulator.

The rest of the traces are labeled.
> 4 votes

# Answer
My explanation for this issue is that the last pulse generated by the `tone()` function is interrupted while the output is on a high level. This results in the last pulse being shorter than it should be to correspond to the desired sound frequency.

While the pulse length doesn't matter for a continuous output (where the pulse frequency determines the sound frequency), a single short pulse can be interpreted as a pulse of a higher frequency. According to Fourier theory at least its fundamental frequency will be higher than the one of the longer pulses.

## Observations that might substantiate my theory:

* the issue happens randomly in ~50% of the cases (for a 50% duty cycle signal).
* the frequency of the erronous tone varies and is always higher than the desired frequency, depending on how short the trailing pulse is.

These seem to be the case for the simulation.

## Possible fixes:

a) provide the `tone()` function with the optional `duration` argument and hope the library itself addresses this problem (which it actually might not as the issue is even in the simulation)

b) make sure to only use multiples of the square wave period for `duration`, so the wave always stops on a low level

According to my theory, a low-pass filter will not work as a fix because the fault frequency can be close to the desired frequency and is the "primary signal", not just some low amplitude harmonic which would be easier to filter from a (much stronger) fundamental.
> 1 votes

---
Tags: interrupt, button, audio, frequency, sound
---


# Question
Title: How much time does it take to propagate the control signal through all LEDs in the ws2812b strip?
In my next small Arduino project, I wanted to use some addressable rgb led strips. I made some small research and choose to use a strip with ws2812b. Generally, I know how this works but I am not 100% sure if what I think is correct. So please correct me if I am wrong.

For each pixel in the strip, we need to send 24 bits to control it. If we have 10 pixels in a strip then we need to send 240 bits. Then first pixel reads all 240 bits, sets itself color, and lastly propagates other 216 bits to the next pixel. And so on to the last pixel.

I am wondering, how much time does it take to update state of the last pixel in strip?

If sending 24 bit takes something about 30us (1.25us for 1 bit) then is that mean that sending signals to the last pixel in a strip with 10 pixels would take 300us + 270us + 240us + ... + 30us or is it rather just 300us?

# Answer
I have a page about the WS2812 chip along with a suggested way of writing code simply for it. It also describes the timing.

The documented timing for a 0-bit is 1150 ns and for a 1-bit is 1300 ns.

Thus, if we assume all bits are on, then 24 bits would take 24 * 1300 ns which is 31.2 µs.

Since the bits are propagated along the strip, then it would take 10 * 31.2 µs (312 µs) to send all 10 colours.

What I mean by "propagated" is that as each bit arrives at each chip it also forwards it onward to the next chip, much like a shift register. Thus the more bits you send the further the original ones are "pushed" towards the end of the strip.

As the documentation describes, each chip "reshapes" the incoming bit, so that any jitter or noise in the arriving bit is cleaned up as it is forwarded so that the individual bits do not degrade as they are forwarded. Think of Chinese Whispers \- because of the reshaping by each chip the information is **not** corrupted as it is passed on.

Then you send 50 µs of 0V to latch the new colours to the entire strip.

So, the answer to your question is 362 µs (roughly).
> 0 votes

---
Tags: rgb-led
---


title: Correct syntax for setCACert ESP8266

text:
# Question
Title: Correct syntax for setCACert ESP8266
I am trying to use a cert with an ESP8266. The identical code works fine on ab ESP32, but in the ESP8266 I am getting errors.

I set the cert as follows:

```
const char *ROOT_CERT PROGMEM = R"EOF(= "-----BEGIN CERTIFICATE-----
MIIFYDCCBEigAwIBAgIQQAF3ITfU6UK47naqPGQKtzANBgkqhkiG9w0BAQsFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
...
-----END CERTIFICATE--------)EOF";

```

For the ESP32 I use:

```
wifiClient.setCACert(ROOT_CERT)

```

This works fine, but on the 8266 I get:

```
no matching function for call to 'BearSSL::WiFiClientSecure::setCACert(const char*&)'

```

I have done some research and there are some suggestions the length is required, so I tried that also:

```
 wifiClient.setCACert(ROOT_CERT, sizeof(ROOT_CERT)-1);

```

But that produces the following error:

```
invalid conversion from 'const char*' to 'const uint8_t* {aka const unsigned char*}' [-fpermissive]

```

I am using the 2.7.4 8266 board library as I have heard the 3.X has similar issues.

I have tried V 3.X but I get the following:

```
class BearSSL::WiFiClientSecure' has no member named 'setCACert'

```

# Answer
> 1 votes
i could not use setCACert with 8266. you need to do it differently and i had to do some web hunting.
But finally i did get my telegram test working from esp32 to 8266, here is what i did and hope that you can adapt it

you need :

```
#include <ESP8266WiFi.h>

```

after your defines add:

```
X509List cert(TELEGRAM_CERTIFICATE_ROOT);
WiFiClientSecure client;
UniversalTelegramBot bot(BOTtokenValue,client);

```

in setup i had to add BOTH of these lines (i initially didnt think i needed the 1st line, but apparently you do) :

```
configTime(0, 0, "pool.ntp.org");   // get UTC time via NTP
client.setTrustAnchors(&cert);      // Add root certificate for api.telegram.org

```

this got my ESP32 code converted from ESP32 to 8266

---
Tags: esp8266
---


# Question
Title: What's Memory Allocation technique in Arduino
I am currently working on an assignment for my embedded systems course, and my professor has asked us to determine the memory allocation technique employed in Arduino. Specifically, I need to identify whether it utilizes best fit, quick fit, worst fit, next fit, or first fit memory allocation methods.

Despite conducting online research and seeking input from my colleagues, We have been unable to find an answer to this question.

I would greatly appreciate any insights or information on the memory allocation technique used in Arduino.

Thank you.

# Answer
> 2 votes
Use the source, Luke!

The AVR-based Arduinos rely on the avr-libc library, which provides `malloc()` and friends. You can read the source code online. It is generously commented, and you can understand pretty well the allocation strategy by reading the comments alone.

# Answer
> 1 votes
Long answer short, it used both first-fit and best-fit.

The malloc function in the avr-libc makes use of a so-called free list to track the free spaces in the memory.

When there is a memory request, it starts by looping over this list searching for the first exact match **\[First Fit\]**.

While looping over the list, it keeps track of the piece of memory that will leave the least amount of space(best-fit). If it didn't find the exact match, it uses this piece of memory **\[Best Fit\]**.

Furthermore, it doesn't use this piece of memory directly, it checks for its size first, if it is big enough, it takes the amount of memory needed and adds the leftover to the free list, else, it allocates the whole piece of memory.

N.B. it allocates new memory space to the heap if it doesn't find the first-fit or best-fit.

---

### Example Scenarios:

1. First Fit:

* Free list: \[64, 128, 128, 256, 512, 128\]
* Request: 128
* Action: Take the first 128.

2. Best Fit:

* Free list: \[64, 256, 512\]
* Request: 128
* Action: Take the 256, use 128, and add the other 128 to the free list.

3. Best Fit:

* Free list: \[64, 256, 512, 130\]
* Request: 128
* Action: Take the 130 and use it all.

Hope things are clear now!

---
Tags: arduino-uno, avr, memory, avr-toolchain
---


# Question
Title: How to make an arduino webserver over USB? without ethernet shield nor wifi chip
I would like to begin to understand ethernet handshakes by integrating an Ethernet over USB protocol within an arduino mega or nano. Is there something about the ethernet protocol that requires more components? I know that USB to ethernet adapters exist. In this scenario, it would be more like a USB to arduino webserver experiment, except the arduino webserver would also be providing the IP address to the laptop during the initial handshake.

Shouldnt it be possible to create a simple router from an ATMega2560, where you plug in an arduino to a computer, and the computer is assigned an IP address on the ATMega's network?

Likewise, couldnt you then serve small files from the ATMega to a web browser through this IP connection?

I know this sounds dumb and like over engineering. But i promise i am not crazy and that this could be useful. USB to Ethernet adapters and drivers exist, so i am not sure that there is a hardware limitation. In other words, while ethernet normally requires 4 data lines and USB 2.0 has only 2 data lines, there are still kernel drivers that allow USB to work fine in this way. Likewise the ATMega has only 2 available data lines. So couldnt you begin by simulating a USB to Ethernet device firmware using the ATMega?

A new avenue here that isnt available with Serial connections would be that you could access the ATMega from a web browser, whereas in other driver modes the browser doesnt have the permission to communicate with the Mega.

Why or why not? / How could this be done?

# Answer
> 2 votes
You cannot change what the Arduino's USB does. The USB is not provided by the ATMega2560, but by the USB to UART interface chip.

On a genuine Arduino that may be an ATMega16U2 which could be reprogrammed, but on Chinese clones it most often isn't.

You would need to start with a board that has a real "native" USB connection, such as the Arduino Leonardo (ATMega32U4) or the much more capable (though deprecated) Arduino Due.

Then you would need to create not only the USB "CDC/ECM" device profile, but also the IP stack on top of it to handle the IP data, then a TCP later on top of that to handle the socket data.

The actual CDC/ECM device itself is very simple - much like the CDC/ACM (USB serial) device it's really just a dumb pipe that sends and receives raw Ethernet frames. Interpreting those frames and managing TCP/IP sessions and streams is a far more involved process and would be the bulk of the work. You'd probably want to take an existing standalone IP stack implementation and replace the existing layer 2 code with the CDC/ECM interface instead.

An alternative, as advocated by @Juraj, is to use IP over Serial. This uses a serial protocol (SLIP) to encapsulate the IP frames and has a rudimentary cut-down IP stack in it. However this is old technology and is not well supported by operating systems any more. For example the home versions of Windows no longer have any SLIP support (it used to be provided through "DUNS" - the Dial UP Network Server - which no longer exists).

# Answer
> -1 votes
Try the Web Serial API instead. Example usage.

---
Tags: arduino-mega, usb, ethernet
---


title: DS1302 RTC module running too fast

text:
# Question
Title: DS1302 RTC module running too fast
I am using a DS1302 RTC module with an Arduino Mega 2560 Rev 3. I follow steps on this website since I have no experience with RTC module before. Here are the outputs I am getting.

```
17:15:21.835 -> Current Date / Time: 26/2/2023 17:15:44
17:15:26.830 -> Current Date / Time: 26/2/2023 17:16:13
17:15:31.856 -> Current Date / Time: 26/2/2023 17:16:42
17:15:36.853 -> Current Date / Time: 26/2/2023 17:17:11

```

As you can see from the above output, the DS1302 is running five times faster than the real time (output past 30 seconds as real word past 5 seconds). Same thing happened if use different codes with different libraries.

Does this mean the RTC module itself is broken, or I can modify RTC module's speed with code?

```
//This code is to use with DS1302 RTC module, it permits you to setup the actual time and date
//And you can visualize them on the serial monitor
//This code is a modified version of the code provided in virtuabotixRTC library
//Refer to https://Surtrtech.com for more information

#include <virtuabotixRTC.h> //Library used

//Wiring SCLK -> 6, I/O -> 7, CE -> 8
//Or CLK -> 6 , DAT -> 7, Reset -> 8

virtuabotixRTC myRTC(6, 7, 8); //If you change the wiring change the pins here also

void setup() {
  Serial.begin(9600);
  // Set the current date, and time in the following format:
  // seconds, minutes, hours, day of the week, day of the month, month, year
  myRTC.setDS1302Time(15, 15, 17, 7, 26, 2, 2023); //Here you write your actual time/date as shown above
  //but remember to "comment/remove" this function once you're done
  //The setup is done only one time and the module will continue counting it automatically
}

void loop() {
  // This allows for the update of variables for time or accessing the individual elements.
  myRTC.updateTime();

  // Start printing elements as individuals
  Serial.print("Current Date / Time: ");
  Serial.print(myRTC.dayofmonth); //You can switch between day and month if you're using American system
  Serial.print("/");
  Serial.print(myRTC.month);
  Serial.print("/");
  Serial.print(myRTC.year);
  Serial.print(" ");
  Serial.print(myRTC.hours);
  Serial.print(":");
  Serial.print(myRTC.minutes);
  Serial.print(":");
  Serial.println(myRTC.seconds);

  // Delay so the program doesn't print non-stop
  delay(5000);
}

```

# Answer
> 0 votes
I stumbled over the exact same issue today (using Arduino Uno/atmega328) and a module/board like this: https://surtrtech.com/2018/01/27/how-to-simply-use-ds1302-rtc-module-with-arduino-board-and-lcd-screen/ When reading out time after setting it, it runs 5-6 times too fast.

I found some hint here regarding precision: https://forum.arduino.cc/t/ds1302-drift/327796/7

However, they were talking about a 2 minutes of drift every 24 hours which for sure is a totally different thing. One comment there was to pay special attention to the ground as noise there might be interpreted as additional clock signals and speed up the clock. So I played with the grounds on the board and disconnected everything else connected so far to pins of the Arduino board, but that did not change anything, still 5-6 times faster.

I also played with and without CR2032 battery and 5V and 3.3V input to the clock board's VCC input pin and ...suddenly... it worked ok. I think with 3.3V input on VCC and no battery, it initially had the "normal" precision but now I can again connect it to 5V input and it still runs normal... I also kept it a while disconnected from external power source (only running on battery), then connecting it back to the Laptop and reading out date/time values and still it worked ok.

It is totally weird.

Regards, Dan

---
Tags: arduino-mega, rtc
---


# Question
Title: Problem with using PubSubClient, the "callback" function doesn't seem to work correctly
I have a program that communicate between a esp8266 and a atmega328 using Serial, the esp8266 will connect to a MQTT server running on local network, and publish/subscribe to some topics. In the callback function for the subscribing, it will send an instruction to atmega chip to toggle the LED (pin 13). I am using XC4411 board which is an integrated 2-in-1 board with both esp and atmega.

The code looks like this: On esp side:

```
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "credentials.h" // this is where I define the wifi ssid, psw, mqtt username/psw etc.
#include <Arduino.h>

#define SERIAL_BAUD 115200 //make sure this is the same in atmega code, serial communication with atmega chip
#define ESP8266_LED 1

WiFiClient espWifiClient;
PubSubClient espMQTTClient(espWifiClient);
const char* test_topic = "/test/msg01";
void reconnect();
void callback(char *topic, uint8_t *payload, unsigned int length);

void setup_wifi() {
    delay(10);
    WiFi.begin(MY_SSID, MY_WIFIPSW);
    while (WiFi.status() != WL_CONNECTED) delay(500);
}

void setup_mqtt() {
    espMQTTClient.setServer(MY_MQTT_SERVER_ADDRESS, MY_MQTT_SERVER_PORT);
    reconnect();
    espMQTTClient.subscribe(test_topic);
    espMQTTClient.setCallback(callback);

}

void reconnect() {
    while(! espMQTTClient.connected()) {
        if (espMQTTClient.connect(MY_MQTT_CLIENT_ID, MY_MQTT_USER, MY_MQTT_PSW)) {
            espMQTTClient.subscribe(test_topic);
        }
        else delay(500);
    }
}

void callback(char *topic, uint8_t *payload, unsigned int length) {

    digitalWrite(ESP8266_LED, !digitalRead(ESP8266_LED));
    Serial.println("[toggle]");

    // espMQTTClient.publish("/test/esp8266", topic, length);
    espMQTTClient.publish("/test/esp8266", payload, length);

    if (strcmp(topic, test_topic) == 0) {
        if (length >= 0 && (char) payload[0] == '1') {
            espMQTTClient.publish("/test/esp8266", "get payload 1");
        } else if (length >= 0 && (char) payload[0] == '0') {
            espMQTTClient.publish("/test/esp8266", "get payload 0");
        } else {
            espMQTTClient.publish("/test/esp8266", "unknown payload for topic /test/msg01");
        }

    }
}

void setup() {
    Serial.begin(SERIAL_BAUD);
    setup_wifi();
    setup_mqtt();
    pinMode(ESP8266_LED, OUTPUT);
}

String data_from_arduino = "";

void loop() {
    if (! espMQTTClient.connected()) reconnect();
    espMQTTClient.loop();
    while (Serial.available()) {
        char x = Serial.read();
        if (x == '\r')
            continue;
        data_from_arduino += x;
    }
    if (data_from_arduino != "") {
        espMQTTClient.publish("/test/arduino", data_from_arduino.c_str());
        data_from_arduino = "";
    }
    // espMQTTClient.publish("/test/esp8266", "hello from esp"); // this line works fine, so there is no connection problem
}

```

On atmega side:

```
#include <Arduino.h>

#define SERIAL_BAUD 115200

#define LED_PIN 13

String receivedCommand = "";
bool dataIn = false;

void setup()
{

    Serial.begin(SERIAL_BAUD); //same as ESP baud
    pinMode(LED_PIN, OUTPUT);
}

String msg_from_esp8266 = "";
bool start_receiving_msg = false;

void loop()
{
    while (Serial.available())
    {
        char c = Serial.read();

        if (c == '[')
        {
            start_receiving_msg = true;
            msg_from_esp8266 = "";
        } else if (start_receiving_msg && c != ']') {
            msg_from_esp8266 += c;
        } else if (start_receiving_msg && c == ']') {
            start_receiving_msg = false;
            if (msg_from_esp8266 == "toggle") {
                digitalWrite(LED_PIN, !digitalRead(LED_PIN));
                Serial.println("arduino toggle led");
            }
        }

    }
    delay(10);
}

```

Basically when you publish anything to topic /test/msg01 manually, it will try to toggle the esp8266's built in led. then esp8266 will publish a message to /test/esp8266 with the exact payload you publish to /test/msg01. Also, esp8266 will also send a serial message "\[toggle\]" to atmega. On the atmega side, it will check if it receives the "\[toggle\]" and toggle its built in LED, then it will send a message through serial. on the esp side, in the loop, it will receive that message from atmega and publish it to topic /test/arduino. This program is to test the communication between other mqtt client devices and the esp8266, as well as (communication between other mqtt client devices) and the atmega through esp8266 via serial. The code in if (strcmp(topic, test\_topic) == 0) is just some other additional test code.

Generally, you should expect the behaviour like this: once you publish any message to topic /test/msg01, you will see the same message being relayed to topic /test/esp8266. both esp8266 and atmega will toggle their LED on and off. And the message "arduino toggle led" will be published to topic /test/arduino.

However, neither LED toggles. And there is no message from /test/arduino. in topic /test/esp8266 I saw some garbage text instead of my original message.

I have already troubleshooted the connection, the board configuration and checked if the lED is broken. They are all good, and I am pretty sure that the problem is to do within the "callback" function.

Here are some screenshot with the mqtt message:

What I have published to /test/msg01:

What I get from /test/esp8266

And, there is no problem with the message in /test/msg01 as I was also subscribing to the topic and get the same message as I published.

I didn't receive any message from topic "/test/arduino", so seems like the Serial message didn't get to atmega.

And again no problem with XC4411 board configuration as I turn the button 1, 2 on after I done flashing the two chips, and the code compiled and was uploaded to both chip successfully.

Looks like the callback function just corrupted my message, and also just somehow skipped and ignored the line that sends the toggle message to arduino and the line that toggle esp8266's LED.

I am very new to these topic discussed in the question in general, so maybe there are some mechanism that I am not aware of. Thank you the answers in advance.

# Answer
> 2 votes
From the PubSubClient library documentation:

> Internally, the client uses the same buffer for both inbound and outbound messages. After the callback function returns, or if a call to either publish or subscribe is made from within the callback function, the topic and payload values passed to the function will be overwritten

---
Tags: arduino-uno, esp8266, atmega328, mqtt, arduino-uno-wifi
---