# Question
Title: WS2812B LED strip + Arduino First Pixel keeps dying/breaking
I am trying too hook up a WS2812B LED strip to an Arduino Nano. The current strip consists of 6 pixels, and the whole thing is powered by a 5.26 V PC power supply.

The problem is that the first pixel keeps dying after about 1 minute. This means I have to cut the strip and re-solder the connections. Before the failure, the strip runs the correct examples from the FastLED package.

As this happened I looked for solutions. Adafruit's neopixel guide suggested:

1. adding a 1000 µF capacitor between ground and +5 V to cancel power peaks
2. adding a 300-500 Ω resistor between the strip\_Data\_in and D5

I had no 1000 µF+ Capacitor, so I used what I had, 470 µF, and installed it with the resistor.

This did not solve the problem. Another recommendation was to place a diode between the data and +5 V. I think this is to remove any power spikes in the data connection. With a good power supply this should not be necessary I guess, but it couldn't hurt. Another tip was to add a 100 kΩ resistor between data and ground.

Putting all mentioned above together gives something like this:

But in the end nothing changed. I tried alot of variations of solutions:

* With and without condensator between ground and Vin.
* With and without resistor between data and Arduino, and varied it between 220 Ω to 1 kΩ.
* With and without the diodes. I tried connecting data with a diode to ground, +5 V, to both, and to none.
* I have tried using a 3.7 V power source to see whether I could avoid burning the pixel. The LEDs had too little power to light up.
* I have tried powering via the USB-\>Arduino-\>Arduino +5 V pin -\> strip +5 V

Any idea where I might be fucking up?

I have burnt 30 pixels so far, with all the same result: blinking, tripping, and eventually failure. Removing the first LED always fixed the problem. This brand of LED strip did work on some other premade controller.

Some of my own ideas, of causes:

* There really needs to be a 1000 µF capacitor. (I have never had trouble with voltage peaks with this powersupply, and this does not explain why the system fails after some time, instead of at plugin.)

EDIT 1: I did some additional tests.

* Raised the resistor before the data pin, from the recommended 470 Ω, as high as possible. I reached 8 kΩ (higher did not work). -\> Same result, burned pixel
* Lowered the voltage on the data input pin, with two resistances, one connected to ground. The LED strip only recognised data input when the 'Din\_High' was above 3.5 V. Running at a bit lower voltage stopped the LEDs from recognising data. Yet still, same result -\> burned pixel.
* Changing the power supply: I changed the PC power supply to a 5 V power bank for loading celphones. The voltage this device was regulated to was between 5.2 and 4.8 V. The behaviour was the same -\> burned pixel.

I would guess that IF:

* the 5 V is stable and within 5.5 and 4.5 V and
* The Din is within 0 and 5 V

The cable should be unable to break itself, right?

# Answer
> 2 votes
**I found (a part of) the problem:**

**The soldered pin connections at start of the ribbon had leaking current. This was due to the soldering flux remaining around the pins. Rinsing the connection with water carefully solved the problem.**

In earlier runs I soldered with flux and simply wiped it off afterwards. Also note that I am generous in flux usage. I do not know how people can make neat solderingwork without it. Just scraping, and wiping with tissues between the connections is apparently unreliable. The flux is water solutable, said the package, so I used tap water for cleaning, but I also tried alcohol at times. Of course by taking care not to make anything wet besides the connection, and drying careful afterwards.

Obviously I checked the look of my soldering earlier as well, and it looked quite neat in my opinion. Yet measuring resistance between pins gave varying results, also compared with unsoldered, which made me wonder why. Cleaning the area around the soldered pins seemed to remove this, which indicates that this may be due to the soldering flux that was remaining. I also heard that flux tends to start flowing again as it heats up under operation, which indicates why the connection seemed good right after soldering, but changed trough time. Perhaps this is why people use these ultrasonic cleaning baths or something.

About the led strips: They were one of the cheapest ones available.

About the power supplies: The first power supply is the 5v line from a PC power supply, which should be able to give quite some amps. ( i forgot how much exactly, but way more than I needed) The second power supply was a Lithion battery with regulator. The thing says it is able to supply 2 amps, but I stayed far away from this limit.

Thank you for your tips. You help me keep improving myself.

Any more tips on cleaning soldered connections are welcome.

# EDIT:

Oh boi! If it isn't the consequences of my own actions!

So this is what SN39 flux does to soldered wires in 2 years. This is a different object, soldered with the same acid based flux thats intended for copper piping, and not for electricals. I have quite some wonky soldering work to replace at my job. Don't be me lads, and only use flux thats intended for electricals.

# Answer
> 1 votes
To my understanding, anything connected to the `data` line (resistors, diodes, etc) is there to protect to data pin from either sourcing too much current to the LEDs or receive a too high voltage.

The capacitor, on the other hand, is there to provide a buffer and maintain the voltage at the right value when current absorption increases with a spike.

If your LEDS burn up and it's always the first one, assuming they are all programmed to lit up of the same color, the most reasonable reason IMHO is you are feeding too much current, in particular in the form of higher voltage through the resistors on the strip.

I suggest you double check the source voltage with no load and with a light load, then try a different power supply and, as last resort, try to lower the brightness intensity of the LEDS: set brightness to 50% and check if it takes like 3 or 4 times longer to burn the LED, which will be a confirmation about my statement.

The first LED is the one receiving the highest voltage in the strip as the strip itself has a non trivial resistance, especially the cheap ones. Lowering the brightness you are actually lowering the amount of time the LED is on and it should prolong the LED life in a non linear way.

If my assumption is correct, this also means you have already partially damaged all the LEDS on the strip, the closer to the power, the more damaged they are.

# Answer
> 1 votes
https://www.kitronik.co.uk/pdf/WS2812B-LED-datasheet.pdf

Check the power supply. It is likely too high a voltage. 5.3V is the absolute max. The resistor is only to prevent signal reflections on long wire runs. Neither it or the diodes are needed for your setup.

For comparison, here are 4 rings of 43 WS2812B each, with only a 0.1uF cap per chip, each ring driven from a different data pin on an Uno, which is off screen, and a 10A power supply (4 rings x 43 LEDs/ring * 60mA/LED = 10.3A max current). https://www.youtube.com/watch?v=CGOxbehyoM4 You can see the wires are much longer than yours. Unfortunately the camera doesn't self adjust to the brightness changes too well, so the video can be a bit glary at times.

# Answer
> 0 votes
While you've tried a 470µF capacitor, it might be worth getting a 1000µF capacitor, as recommended. Capacitors help stabilize the power supply, especially during sudden current spikes.

---
Tags: neopixel, led-strip
---


# Question
Title: Increase in power consumption after brown-out detection (BOD)
I'm working on a low-power energy harvesting project, where I'm considering using an ATtiny85 to perform some minor tasks. The ATtiny is put in Power Down mode most of the time and does not consume much power in this mode.

Since the power source is unstable, and/or could be absent from time to time, I've been enabling the internal brown-out detection (BOD) by setting the fuses. In this way, the ATtiny is reset when the voltage gets too low. This is to ensure that the microcontroller starts working properly again when sufficient power returns. This also seems to work, so that the chip starts running again when the voltage is above a certain threshold.

However, when the voltage drops below the BOD level, I notice a considerably larger power surge through the ATtiny, even when all peripherals are disconnected. It seems to me that some sort of gate is opened inside the chip when the BOD fires, and the current is limited by some sort of internal resistance. When the voltage increases somewhat above the BOD level, the large power surge stops.

I've been searching through the documentation/datasheet and forums online to find out why this happens but can't seem to find some sort of explanation or ways to prevent this from happening. Since this is a low-power energy harvesting project, it is important that the internal protection from low voltages does not contribute to the problem it detects.

Any useful input would be appreciated.

# Answer
> 0 votes
When the Vcc level is below the BOD activation voltage, the chip is held in a reset state...

...which uses significantly more current than the chip does in sleep state...

You are probably better off disabling the BOD and instead using an external Voltage Supervisor chip to turn the power on to the ATTINY when there is sufficient voltage and turn it off when there is not. There are many of these chips and they can use less than a microwatt when quiescent.

---
Tags: power, attiny, attiny85
---


# Question
Title: How to connect an Arduino Uno with an ESP-01 to the Arduino IoT cloud?
I have been trying to connect to the Arduino IoT cloud using my Arduino Uno and an ESP-01.

The Arduino IoT cloud does not recognize my device as genuine. Hence, I've been trying to create a `thing` and connecting it as a third-party device. I have an ESP-01 WiFi module that I want to use to connect to the IoT cloud.

I tried the following connection:

```
Arduino ----> ESP-01
3.3V  ------> 3v3
3.3V  ------> EN(CH_PD)
TX(1) ------> TX
RX(0) ------> RX
GND   ------> GND

```

I also tried to reverse the connections of the RX and TX pins. Still no success. I want to connect to the cloud and use some sensors to update the cloud variables. How do I do it? Any kind of help is highly appreciated.

Edit: I tried to upload the code that thd cloud editor provided and it throws and error saying:

```
fatal error: list: No such file or directory
 #include <list>

```

# Answer
> 1 votes
Arduino IoT Cloud doesn't support Arduino Uno, but it does support esp8266.

You have to do the communication with the IoT Cloud from a ESP-01 sketch with esp8266 Arduino Core. Then you can pass the values from/to a sketch in Uno over Serial.

There are ESP8266 development boards which can replace the Uno in many projects. Search for "Wemos D1 mini" or "NodeMCU" ESP8266 modules.

The ESP32 is even more capable MCU with WiFi and Arduino Core is available. It is too supported in Arduino Cloud and Arduino even has a new Nano ESP32 board.

---
Tags: arduino-uno, esp8266, arduino-iot-cloud
---


# Question
Title: How to change the direction of a stepper motor using the AccelStepper library?
I'm using a Nema 17 stepper motor (200 steps) and a DRV8825 motor driver. This is the configuration I am using:

I am using a 9 V power supply. The dirPin is connected to pin 3 on the Arduino board, and my stepPin to pin 2.

What I'm trying to do is move the motor 100 steps clockwise and then move it 100 steps anti-clockwise, so that it returns to the starting position. This is the code I am using:

```
#include <AccelStepper.h>

#define dirPin 3
#define stepPin 2
#define motorInterfaceType 1

int SPR = 200;

AccelStepper stepper(motorInterfaceType, stepPin, dirPin);

void setup() {
  pinMode(dirPin,OUTPUT);
  pinMode(stepPin,OUTPUT);
  // put your setup code here, to run once:
  stepper.setMaxSpeed(200);
  stepper.setAcceleration(30);
}

void loop() {
  // put your main code here, to run repeatedly:
  stepper.moveTo(100);

  stepper.runToPosition();
  delay(1000);

  stepper.moveTo(-100);

  stepper.runToPosition();
  delay(1000);
}

```

I have two issues:

1. Before moving the motor 100 steps, it moves a couple of steps (like 15°), and then it starts moving, first 100 steps, and then 200 steps. That would be the first iteration, and I don't understand why it moves those 200 steps. And then, in the following iterations, the motor just moves 200 steps.
2. It only moves in one direction. I can't get it to move anti-clockwise.

# Answer
The `moveTo()` function takes absolute positions, so if you want to move in both directions, you should adjust the target positions accordingly.

You can modify your `loop()` function as follows:

```
void loop() {
  stepper.moveTo(100);
  stepper.runToPosition();
  delay(1000);

  stepper.moveTo(0); // Move back to the starting position
  stepper.runToPosition();
  delay(1000);
}

```
> 2 votes

---
Tags: arduino-uno, motor, library, stepper, stepper-motor
---


# Question
Title: Can't upload programs to Raspberry Pi Pico with Arduino
I am trying to use a RP2040 Pico with the Arduino IDE. This is a huge uphill battle. Initially I couldn't get the upload serial port to show up, then copied the "hello world" UF2 to the Pico folder (https://datasheets.raspberrypi.com/soft/hello\_world.uf2), after which the port showed up in the Arduino ISE 2.0.0 on Windows 10 - but I can't upload any programs. All I get is this error message:

```
    Traceback (most recent call last):
      File "C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.9.15/tools/uf2conv.py", line 380, in <module>
        main()
      File "C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.9.15/tools/uf2conv.py", line 360, in main
        drives = get_drives()
      File "C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.9.15/tools/uf2conv.py", line 233, in get_drives
        "FileSystem,", "DriveType"])
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 395, in check_output
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 472, in run
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 775, in __init__
      File "D:\obj\Windows-Release\37win32_Release\msi_python\zip_win32\subprocess.py", line 1178, in _execute_child
    FileNotFoundError: [WinError 2] The system cannot find the file specified
    Upload error: Failed uploading: uploading error: exit status 1

```

This is ultra-weird, because no such folders etc. exist on my drive D:, and I have no idea why it's looking for files on drive D:\ in the first place, because the Arduino IDE is installed on drive C:. And these folders also aren't present on C:.

Does anyone have any ideas on how to fix this? I've Googled everything I can find and have so far found nothing helpful. I'm about ready to give up and would REALLY appreciate any help you can give!

# Answer
> 1 votes
Installing a generic driver with https://zadig.akeo.ie/ while the PICO was plugged in solved the issue for me.

# Answer
> -1 votes
It took me two days to fix that mistake! Who would have thought that this is due to the missing file "C:\Windows\SysWOW64\framedynos.dll". When I put the file back in place, everything went back to normal.

UPD:

Turn on "Show verbose output" in Preferences and browse several last lines. There should be a line like this:

```
C:\Users\light\AppData\Local\Arduino15\packages\rp2040\tools\pqt-python3\1.0.1-base-3a57aed/python3 -I C:\Users\light\AppData\Local\Arduino15\packages\rp2040\hardware\rp2040\1.10.0/tools/uf2conv.py --serial COM5 --family RP2040 --deploy C:\Temp\arduino_build_214726/...

```

Copy and run that line in Terminal (Win-R). There may be bug reports to help you solve your problem.

---
Tags: uploading, raspberrypi-pico
---


# Question
Title: AT command validation does not appear on the serial monitor
I can't validate an AT command. Would anyone have any suggestions as to what I might be doing wrong? It should be printing **"Sending successful!** or **"Sending failed!"**, but it doesn't show any text.

```
if (httpReadResponse.indexOf("OK") != -1) {
  Serial.println("Envio bem-sucedido!");
} else {
  Serial.println("Falha no envio!");
}

```

My serial monitor is printing this:

```
AT+HTTPDATA=192,5000\
DOWNLOAD\
OK\
AT+HTTPACTION=0\
OK\
AT+HTTPREAD

```

Full function:

```
void sendHttpRequest(int distance_cm) {
  gsm_send_serial("AT+HTTPINIT");
  gsm_send_serial("AT+HTTPPARA=CID,1");
  gsm_send_serial("AT+HTTPSSL=1");
  gsm_send_serial("AT+HTTPPARA=URL," + url2 + "/" + distance_cm + "/" + id_cliente + "/" + id_caixa + "/" + ipadd1 + "/" + sinal + "/" + totalMilliLitres + "/" + vazao_atual + "/" + apikey);
  gsm_send_serial("AT+HTTPPARA=CONTENT,application/x-www-form-urlencoded");
  gsm_send_serial("AT+HTTPDATA=192,5000");
  gsm_send_serial("param=Aqualizar");
  gsm_send_serial("AT+HTTPACTION=0");

  String httpReadResponse = gsm_send_serial("AT+HTTPREAD");

  gsm_send_serial("AT+HTTPTERM");

  if (httpReadResponse.indexOf("OK") != -1) {
    Serial.println("Sending successful!");
  } else {
    Serial.println("Sending failed!");
  }
}

```

# Answer
> 0 votes
> AT+HTTPACTION=0

`AT+HTTPACTION=0` starts a GET session. Based on your code, you are supposed to create a POST session, which should be `AT+HTTPACTION=1`.

Read *SIM800 Series\_IP\_Application Note* which provides the examples for both GET and POST request based on the SIMCOM HTTP AT-command set. The application note can be found at SIMCOM's website (requires registration for free download) or simply google "SIM800 Series\_IP\_Application Note" as there are many sites that have the document available without the need for registration.

---
Tags: esp32, sim800
---


# Question
Title: Incremental Rotary Encoder sends data when shaft is untouched
I'm trying to build an Arduino project that counts pulses sent by an encoder.

I've bought an Omron E6B2-CWZ5B-2 2000P/R and face the issue of it sending pulses non-stop, even when I'm not touching it. The code I use is from this video.

I thought that the encoder itself was the problem and bought two encoders like in the video above (LPD3806-400BM-G5-24C), but I faced the exact same problem.

When I connect the encoder to the Arduino 5 V and GND ports, the encoder doesn't seem to work at all (in the video it does without any resistors, etc.). I had to use a different power source, which was a laboratory power supply, which I set to around 6 V.

I connected the A output to digital pin 2 and the B output to digital pin 3 of my Arduino Uno. The problem is - the values just start going up and down at an insane speed without me touching the encoder. If I only connect output A, they go like I'm spinning it hard left, if I connect only the B output, they go like I'm spinning it hard right. If I connect both of them, it's just a massacre of data, like I'm spinning it left and right insanely fast.

The other thing I noticed - if I power up my Laboratory power supply to 12 V and more it seems that the encoder sends even more data per sec.

I only managed to get it working properly once and can not repeat it now. I did the following:

I powered the LPD3806 with 5.5 V externally (lab power supply), took the ground shield of encoder and held it really tight to Arduino Uno USB port. Data spam stopped and the encoder worked properly when I'm twisting the shaft. But I can't repeat this thing now.

It's clear the problem is with grounding, but I wonder how I can fix it to use it in an okay way. And I still wonder how the author of the video above got results with no use of the ground shield at all.

So the question is - how do I fix it and where did I go wrong?

Here are some schematics. I don't know how to do them properly, so I did them with Wokwi. So to read it keep in mind that:

* I marked A and B output cables of my LPD3806 encoder as CLK and DT on the rotary encoder from wokwi.com
* The VCC and GND symbols at the very top of some schemas here are + and - of my laboratory power supply
* I marked my ground shield as SW on the third schema to show where I held it to get it working.

Here's how I tried to power it from the Arduino itself. It just didn't start. No signal; nothing.

So I powered it from the lab power supply. Now the encoder started, but it was just spamming numbers. When I increased the voltage, the number-spamming got faster.

And here's how I got it working once by pulling the ground shield tight to the Arduino USB port (keep in mind in my schema I marked ground shield as SW on the encoder).

Here's the code I use:

```
volatile unsigned int temp, counter = 0; // This variable will increase or decrease depending on the rotation of encoder

void setup() {
  Serial.begin (9600);
  pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
  pinMode(3, INPUT_PULLUP); // internal pullup input pin 3
  // Setting up interrupt
  //A rising pulse from encoder activates ai0(). AttachInterrupt 0 is digital pin nr 2 on most Arduinos.

  attachInterrupt(0, ai0, RISING);

  // B rising pulse from encoder activates ai1(). AttachInterrupt 1 is digital pin nr 3 on most Arduinos.

  attachInterrupt(1, ai1, RISING);
}

void loop() {
  // Send the value of counter
  if (counter != temp) {
    Serial.println (counter);
    temp = counter;
  }
}

void ai0() {
  // ai0 is activated if digital pin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if (digitalRead(3)==LOW) {
    counter++;
  } else {
    counter--;
  }
}

void ai1() {
  // ai0 is activated if digital pin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if (digitalRead(2)==LOW) {
    counter--;
  } else {
   counter++;
  }
}

```

Looking forward for your answers and thanks in advance!

# Answer
> 0 votes
From the datasheet: the E6B2-CWZ5B 2000P/R 0.5M encoder has an output circuit which is described as PNP open collector. That is, the output swings from whatever voltage you are running the encoder at (12 V to 24 V) to high impedance:

You probably want to wire it to your (5 V?) Arduino in this manner. The resistor divider is balanced for ~12 V:

Your `loop()` could be better structured to avoid non-atomic reads because it appears that you are using an 8-bit Arduino and an int is 16-bit. There is, therefore, a risk that an ISR will corrupt the variable counter while you are attempting to read it in the `loop()`:

```
void loop() {
  // Send the value of counter
  noInterrupts() ;
  int counter_copy = counter ;
  interrupts() ;
  if (counter_copy != temp) {
    Serial.println (counter_copy);
    temp = counter_copy;
  }
}

```

---
Tags: arduino-uno, rotary-encoder
---


title: Why 0 devices, but not 1?

text:
# Question
Title: Why 0 devices, but not 1?
I have found a sketch in Wokwi where a MAX7219 LED matrix is used. The sketch subject is to display 0 using `<LedControl.h>`. I don't understand why it's nessesary to send 0 unlike 1 in fourth parameter in library-object initialization.

`LedControl(int dataPin, int clkPin, int csPin, int numDevices=1);`

It seems it should be 1 there, but the sketch isn't working in that way.

```
#include <LedControl.h>

int DIN = 12;
int CS =  11;
int CLK = 10;
LedControl lc=LedControl(DIN,CLK,CS,0);

void setup(){
  lc.shutdown(0,false);
  lc.setIntensity(0,15);
}

void loop(){
  byte zero[8]= {0x00,0x1c,0x22,0x22,0x22,0x22,0x22,0x1c};
  printByte(zero);
}

void printByte(byte character []) {
  int i = 0;
  for (i=0;i<8;i++) {
    lc.setRow(0,i,character[i]);
  }
}

```

# Answer
On this page it says: "The fourth argument to LedControl(dataPin,clockPin,csPin,numDevices) is the number of cascaded MAX72XX devices ... only values between 1..8 are allowed here.".

Examining the LedControl source code at GITHUB, we see in file LedControl.cpp in function LedControl() code which checks for unexpected values for the number of MAX7219 LED Matrix devices used:

```
LedControl::LedControl(int dataPin, int clkPin, int csPin, int numDevices) {
...
  if(numDevices<=0 || numDevices>8 )
    numDevices=8;

```

We can see if the number is less than or equal to 0 or is greater than 8 the code defaults to 8 devices. So when passing a 0 the code will detect an unexpected value and create 8 devices by default.
> 0 votes

---
Tags: library, led-matrix
---


title: Machine learning on Arduino Nano RP2040

text:
# Question
Title: Machine learning on Arduino Nano RP2040
I am trying to use the Arduino Nano RP2040 to recognize gestures using an IMU. This board has the possibility of machine learning core features provided by the LSM6DSOX.

I tested the example provided by the manufacturer and everything works fine. I now want to create a new ML model to recognize custom gestures.

I found this STM tutorial, which is very helpful, but I can't find the code presented at 5:48, to record the movements.

Does anyone know where I can find all the code or how I should do it?

# Answer
> 0 votes
I answer the question myself, for those who have the same problem as me.

Source code

```
#include "PluggableUSBMSD.h"
#include "FlashIAPBlockDevice.h"
#include "WiFiNINA.h"
#include "LSM6DSOXSensor.h"

#define INT_1 INT_IMU
#define SENSOR_ODR 104.0f // In Hertz
#define ACC_FS 2 // In g
#define GYR_FS 2000 // In dps
#define MEASUREMENT_TIME_INTERVAL (1000.0f/SENSOR_ODR) // In ms
#define FIFO_SAMPLE_THRESHOLD 199
#define FLASH_BUFF_LEN 8192

typedef enum {
  DATA_STORAGE_STATE,
  DATA_LOGGER_IDLE_STATE,
  DATA_LOGGER_RUNNING_STATE
} demo_state_e;

volatile demo_state_e demo_state = DATA_STORAGE_STATE;
volatile int mems_event = 0;
uint32_t file_count = 0;
unsigned long timestamp_count = 0;
bool acc_available = false;
bool gyr_available = false;
int32_t acc_value[3];
int32_t gyr_value[3];
char buff[FLASH_BUFF_LEN];
uint32_t pos = 0;

static FlashIAPBlockDevice bd(XIP_BASE + 0x100000, 0x100000);

LSM6DSOXSensor AccGyr(&Wire, LSM6DSOX_I2C_ADD_L);

USBMSD MassStorage(&bd);

rtos::Thread acquisition_th;

FILE *f = nullptr;

void INT1Event_cb()
{
  mems_event = 1;
}

void USBMSD::begin()
{
  int err = getFileSystem().mount(&bd);
  if (err) {
    err = getFileSystem().reformat(&bd);
  }
}

mbed::FATFileSystem &USBMSD::getFileSystem()
{
  static mbed::FATFileSystem fs("fs");
  return fs;
}

void led_green_thd()
{
  while (1) {
    if (demo_state == DATA_LOGGER_RUNNING_STATE) {
      digitalWrite(LEDG, HIGH);
      delay(100);
      digitalWrite(LEDG, LOW);
      delay(100);
    }
  }
}

void Read_FIFO_Data(uint16_t samples_to_read)
{
  uint16_t i;

  for (i = 0; i < samples_to_read; i++) {
    uint8_t tag;
    // Check the FIFO tag
    AccGyr.Get_FIFO_Tag(&tag);
    switch (tag) {
      // If we have a gyro tag, read the gyro data
      case LSM6DSOX_GYRO_NC_TAG: {
          AccGyr.Get_FIFO_G_Axes(gyr_value);
          gyr_available = true;
          break;
        }
      // If we have an acc tag, read the acc data
      case LSM6DSOX_XL_NC_TAG: {
          AccGyr.Get_FIFO_X_Axes(acc_value);
          acc_available = true;
          break;
        }
      // We can discard other tags
      default: {
          break;
        }
    }
    // If we have the measurements of both acc and gyro, we can store them with timestamp
    if (acc_available && gyr_available) {
      int num_bytes;
      num_bytes = snprintf(&buff[pos], (FLASH_BUFF_LEN - pos), "%lu %d %d %d %d %d %d\n", (unsigned long)((float)timestamp_count * MEASUREMENT_TIME_INTERVAL), (int)acc_value[0], (int)acc_value[1], (int)acc_value[2], (int)gyr_value[0], (int)gyr_value[1], (int)gyr_value[2]);
      pos += num_bytes;
      timestamp_count++;
      acc_available = false;
      gyr_available = false;
    }
  }
  // We can add the termination character to the string, so we are ready to save it in flash
  buff[pos] = '\0';
  pos = 0;
}

void setup()
{
  Serial.begin(115200);
  MassStorage.begin();
  pinMode(LEDB, OUTPUT);
  pinMode(LEDG, OUTPUT);
  digitalWrite(LEDB, LOW);
  digitalWrite(LEDG, LOW);

  // Initialize I2C bus.
  Wire.begin();
  Wire.setClock(400000);

  //Interrupts.
  attachInterrupt(INT_1, INT1Event_cb, RISING);

  // Initialize IMU.
  AccGyr.begin();
  AccGyr.Enable_X();
  AccGyr.Enable_G();
  // Configure ODR and FS of the acc and gyro
  AccGyr.Set_X_ODR(SENSOR_ODR);
  AccGyr.Set_X_FS(ACC_FS);
  AccGyr.Set_G_ODR(SENSOR_ODR);
  AccGyr.Set_G_FS(GYR_FS);
  // Enable the Double Tap event
  AccGyr.Enable_Double_Tap_Detection(LSM6DSOX_INT1_PIN);
  // Configure FIFO BDR for acc and gyro
  AccGyr.Set_FIFO_X_BDR(SENSOR_ODR);
  AccGyr.Set_FIFO_G_BDR(SENSOR_ODR);
  // Start Led blinking thread
  acquisition_th.start(led_green_thd);
}

void loop()
{
  if (mems_event) {
    mems_event = 0;
    LSM6DSOX_Event_Status_t status;
    AccGyr.Get_X_Event_Status(&status);
    if (status.DoubleTapStatus) {
      switch (demo_state) {
        case DATA_STORAGE_STATE: {
            // Go to DATA_LOGGER_IDLE_STATE state
            demo_state = DATA_LOGGER_IDLE_STATE;
            digitalWrite(LEDG, HIGH);
            Serial.println("From DATA_STORAGE_STATE To DATA_LOGGER_IDLE_STATE");
            break;
          }
        case DATA_LOGGER_IDLE_STATE: {
            char filename[32];
            // Go to DATA_LOGGER_RUNNING_STATE state
            snprintf(filename, 32, "/fs/data_%lu.txt", file_count);
            Serial.print("Start writing file ");
            Serial.println(filename);
            // open a file to write some data
            // w+ means overwrite, so every time the board is rebooted the file will be overwritten
            f = fopen(filename, "w+");
            if (f != nullptr) {
              // write header
              fprintf(f, "Timestamp[ms] A_X [mg] A_Y [mg] A_Z [mg] G_X [mdps] G_Y [mdps] G_Z [mdps]\n");
              fflush(f);
              Serial.println("From DATA_LOGGER_IDLE_STATE To DATA_LOGGER_RUNNING_STATE");
              demo_state = DATA_LOGGER_RUNNING_STATE;
              digitalWrite(LEDG, LOW);
              timestamp_count = 0;
              pos = 0;
              acc_available = false;
              gyr_available = false;
              // Set FIFO in Continuous mode
              AccGyr.Set_FIFO_Mode(LSM6DSOX_STREAM_MODE);
            }
            break;
          }
        case DATA_LOGGER_RUNNING_STATE: {
            // Empty the FIFO
            uint16_t fifo_samples;
            AccGyr.Get_FIFO_Num_Samples(&fifo_samples);
            Read_FIFO_Data(fifo_samples);
            // Store the string in flash
            fprintf(f, "%s", buff);
            fflush(f);

            // Close the log file and increase the counter
            fclose(f);
            file_count++;
            // Set FIFO in Bypass mode
            AccGyr.Set_FIFO_Mode(LSM6DSOX_BYPASS_MODE);
            // Go to DATA_LOGGER_IDLE_STATE state
            demo_state = DATA_LOGGER_IDLE_STATE;
            // Wait for the led thread ends the blinking
            delay(250);
            digitalWrite(LEDG, HIGH);
            Serial.println("From DATA_LOGGER_RUNNING_STATE To DATA_LOGGER_IDLE_STATE");
            break;
          }
        default:
          Serial.println("Error! Invalid state");
      }
    }
  }

  if (demo_state == DATA_LOGGER_RUNNING_STATE) {
    uint16_t fifo_samples;

    // Check the number of samples inside FIFO
    AccGyr.Get_FIFO_Num_Samples(&fifo_samples);

    // If we reach the threshold we can empty the FIFO
    if (fifo_samples > FIFO_SAMPLE_THRESHOLD) {
      // Empty the FIFO
      Read_FIFO_Data(fifo_samples);
      // Store the string in flash
      fprintf(f, "%s", buff);
      fflush(f);
    }
  }

  if (demo_state == DATA_STORAGE_STATE && millis() > 10000) {
    // Disable the sensor and go to Mass Storage mode
    AccGyr.Disable_Double_Tap_Detection();
    AccGyr.Disable_X();
    AccGyr.Disable_G();
    while (1) {
      digitalWrite(LEDB, HIGH);
      delay(100);
      digitalWrite(LEDB, LOW);
      delay(100);
    }
  }
}

```

---
Tags: imu, arduino-nano-rp2040
---


# Question
Title: How to connect nRF24L01+ with Arduino Giga R1?
I have bought 2 Arduino Giga R1, 2 nRF24L01+ modules and 2 nRF24L01+ adapters. I am using the Arduino SPI in order to connect it with nRF24L01+. And I am using the following code with this change in the code only:

```
RF24 radio(7, 10); // CE, CSN

```

This is the Arduino GIGA R1 SPI documentation, and this is the nRF24L01+ modules, and the related adapter (the links of the modules are from a random Google search, just to show you the images + the documentation of the modules).

However I don't see something working. I added the following command both in the Receiver and Transmitter codes:

```
SPI.begin();
SPI1.begin();

```

in order to activate both SPI of each Arduino, because I don't know which is which. The result: Nothing works on Arduino GIGA R1... The same code above works fine on Arduino MEGA 2560 R3, ***so all the modules and the code are fine***. The problem is on Arduino GIGA R1...

I supply the nRF24L01+ and the related adapters with 5V/1.5A power supply. I supply each Arduino GIGA R1 with 5V/1.5A power supply.

I have also tried this code, and I got this message:

> We have lost connection, preventing unwanted behavior

Does anyone has any idea how to make the 2 Arduino GIGA R1 communicate via the nRF24L01+ link?

# Answer
> 3 votes
Not sure if you found a solution but I had a similar problem and found a solution, which may work for you.

As you know, the Giga has two SPI buses. The default are the ones on the ICSP header, the second one is on pins 11-13.

The NRF24L01, by default, assumes that you want to use the default one - SPI in this case. If you want to use the other one (SPI1), all you need to do is call begin on SPI1 and pass that to the NRF begin function, as follows:

```
    SPI1.begin();
    radio.begin(&SPI1);

```

This worked for me, hopefully it will for you as well.

# Answer
> -1 votes
I just want to note that You Do Not Need An External Antenna module, because the Arduino Giga R1 has a micro UFL antenna connector, and an antenna is shipped with every arduino giga(sorry for you if they forgot to include it in your one), However It IS probably more for wifi porpuses than enclosed communication, still the nRF24L01+ is a great way to actually communicate between two mcu's, especially if an mcu doesnt come with a built in wifi or some sort of wireless communication

---
Tags: nrf24l01+
---


title: How to avoid MQTT reconnect Loop

text:
# Question
Title: How to avoid MQTT reconnect Loop
I have the following code designed to allow me to control my device from my website using **mqtt broker** while internet is available. I also built in a **local webserver** to control the device in case of internet outage given I'm still connected to the same router my device is connected to.

```
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

int ledPin = 2;

const char* ssid = "SSID";
const char* password = "PASS";
const char* mqtt_server = "MQTTSERVER";
const char* mqtt_user = "MQTTUSER";
const char* mqtt_pass = "MQTTPASS";
const char* mqtt_topic = "topic";
String mqttpayload;

WiFiServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);  pinMode(ledPin, OUTPUT);  digitalWrite(ledPin, LOW);

  WiFi.begin(ssid, password);

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

  Serial.print("Connected to WiFi");

  client.setServer(mqtt_server, 1883);    server.begin();
}

void loop() {
  client.setCallback(callback);
  reconnect();
  if ( mqttpayload == "OFF" ) {   digitalWrite(ledPin, HIGH); Serial.println("Switced OFF"); }
  if ( mqttpayload == "ON" ) {   digitalWrite(ledPin, LOW);  Serial.println("Switced ON"); }
  mqttpayload = "";

  WiFiClient cclient = server.available();
  if (!cclient) {  return;  }  while(!cclient.available()){  }
  String request = cclient.readStringUntil('\r');  Serial.println(request);  cclient.flush();

  int value = HIGH;
  if (request.indexOf("/LED=ON") != -1)   {
    digitalWrite(ledPin, LOW);    value = LOW;      Serial.println("Publish message: ON");    reconnect();  client.publish(mqtt_topic, "ON", true);
  }
  if (request.indexOf("/LED=OFF") != -1)  {
    digitalWrite(ledPin, HIGH);   value = HIGH;     Serial.println("Publish message: OFF");    reconnect(); client.publish(mqtt_topic, "OFF", true);
  }

  cclient.println("HTTP/1.1 200 OK");
  cclient.println("Content-Type: text/html");
  cclient.println("");
  cclient.println("<!DOCTYPE HTML>");
  cclient.println("<html>");
  cclient.print("LED status: ");

  if(value == HIGH) {    cclient.print("OFF");  } else {    cclient.print("ON");  }
  cclient.println("<br><br>");
  cclient.println("Turn <a href=\"/LED=ON\">ON</a><br>");
  cclient.println("Turn <a href=\"/LED=OFF\">OFF</a><br>");
  cclient.println("</html>");
  Serial.println("");
}

void callback(char* topic, byte* payload, unsigned int length) {
  for (int i = 0; i < length; i++) {     mqttpayload += (char)payload[i]; }
}

void reconnect() {
  if (!client.connected()) {
    while (!client.connected()) {
      Serial.print("MQTT..");
      if (client.connect("2021", mqtt_user, mqtt_pass)) {
        Serial.println("MQTT connected");        client.subscribe(mqtt_topic);
      } else { error(); }
    }
  }
  client.loop();
}

void error() {  Serial.print("failed, rc=");      Serial.print(client.state());      Serial.println(" try again in 5 seconds");      delay(5000);   }

```

The problem lies when I test it while connected to my router with **no internet**. The code loops trying to connect to MQTT server and get stuck which doesn't allow me to send local HTTP requests.

I tried modifying the MQTT reconnect loop to the one below, which solves the problem but introduces another issue which is delaying the HTTP requests up to 6-9 seconds.

```
void reconnect() {
 if (client.connect("2021", mqtt_user, mqtt_pass)) {
  Serial.println("MQTT connected");
  client.subscribe(mqtt_topic);
 } else { error(); }
 client.loop();
}

```

So the question here, **what should I do to get around this issue?**

# Answer
> 0 votes
In the loop, check the network first, you can also ping to internet to make sure the internet is available. If negative, just skip reconnecting and try to check the internet connection or try another way to connect to MQTT or esp.

---
Tags: web-server, mqtt
---


# Question
Title: Fixing a pedestrian traffic light sequence pattern in a cycle using millis and without delay
I was emulating the pedestrian traffic light cyclic pattern (red, green, green flashing) in the next Arduino code. But when I run this code with my ESP8266 Wemos D1 mini controller, it appears the pattern (red, red and (green flashing) at the same time, green). I do not know why this strange pattern appeared and I was trying to fix it, but I did not get anything. How to fix this code to replicate the (red, green, green flashing) sequence pattern?

```
// Define pin assignments
const int redLED = D1;
const int greenLED = D2;
const int pedestrianButton = D3;
const int potentiometer = A0;

// Define variables
unsigned long lastStateChangeTime = 0;
unsigned long greenFlashingDuration = 3000; // 3 seconds
unsigned long redGreenDuration = 5000; // Initial duration
bool pedestrianRequest = false;

void setup() {
  // Initialize pins
  pinMode(greenLED, OUTPUT);
  pinMode(redLED, OUTPUT);
  pinMode(pedestrianButton, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pedestrianButton), pedestrianInterrupt, FALLING);
}

void loop() {
  updateTiming(); // Read potentiometer/LDR and update timings
  manageTrafficLights(); // Manage traffic light states
}

void manageTrafficLights() {
  unsigned long currentTime = millis();

  if (pedestrianRequest==true) {
    // Pedestrian request prioritized
    digitalWrite(greenLED, HIGH);
    digitalWrite(redLED, LOW);

    pedestrianRequest = false;
  }

  // Determine the state based on the timing

  if ( (currentTime-lastStateChangeTime) >= (2 * redGreenDuration) ) {
    lastStateChangeTime = currentTime; // Reset cycle
  }
  else {
    if ( (currentTime-lastStateChangeTime) < redGreenDuration ) {
      digitalWrite(greenLED, LOW);
      digitalWrite(redLED, HIGH); // Red state
    } else if ( (currentTime-lastStateChangeTime) < (2*redGreenDuration-greenFlashingDuration) ) {
      digitalWrite(redLED, LOW);
      digitalWrite(greenLED, HIGH); // Green state
    } else {
      digitalWrite(redLED, LOW);

      if ( ( (currentTime-lastStateChangeTime) >= (2*redGreenDuration-greenFlashingDuration) )
      && ( (currentTime-lastStateChangeTime) % (greenFlashingDuration/3) < (greenFlashingDuration/6) ) ){
        digitalWrite(greenLED, LOW);
      } else {
        digitalWrite(greenLED, HIGH);
      }

    }
  }

}

void updateTiming() {
  // Read potentiometer/LDR values and map to timings
  // Update redGreenDuration and greenFlashingDuration accordingly
  redGreenDuration = map(analogRead(potentiometer), 0, 1023, 5000, 10000);
}

void pedestrianInterrupt() {
  pedestrianRequest = true;
  // Quickly change to green if in red state
  if (digitalRead(redLED) == HIGH) {
    digitalWrite(greenLED, HIGH);
    digitalWrite(redLED, LOW);
    lastStateChangeTime = millis(); // Reset the cycle
  }

}

```

# Answer
Here is some simplified example code that might be useful to you.

It keeps the logic and the LED control separated by the use of flags.

Simulation is at https://wokwi.com/projects/389132610627050497

```

// https://arduino.stackexchange.com/questions/95476/fixing-a-pedestrian-traffic-light-sequence-pattern-in-a-cycle-using-millis-and-w

// for simulation, see https://wokwi.com/projects/389127817478781953

const int redLED   = 2;
const int greenLED = 3;

unsigned int timeInterval  [4] = {  5,  3,  4,  0};             // timers reload with these values
unsigned int timeCounter   [4] = {  0,  0,  0,  0};             // these are the actual timers

//boolean    reloadable    [4] = {true, true, false, false};    // this determines if the timer will restart upon reaching end
                                                                // put value in <timeCounter> for oneshot event
                                                                // 3rd and 4th timers are not used in this example sketch

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

boolean       red       = false;
boolean       green     = false;
boolean       blink     = false;

unsigned long previousMillis = 0;

void setup() {

  Serial.begin(115200);

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

  green = true;                                                  // start with green
  timeCounter[0] = 1;                                            // load the first counter

}

void loop() {

  unsigned long currentMillis = millis();

// -------------------------------------------------------------------

  if (currentMillis - previousMillis >= 500) {                    // 0.5 s tick
    previousMillis = currentMillis;
    subTick = !subTick;                                           // alternate the value

    if (subTick) {
      mainTick = true;                                            // 1 s tick

  //  Serial.println("tick");                                     // debugging code

      for (int i = 0; i < 4; i++) {                               // keep track of 4 time intervals

        timeCounter[i]-- ;                                        // decrement counter

        if (timeCounter[i] == 0) {
  //      if (reloadable[i])  timeCounter[i] = timeInterval[i];   // reached zero, reload counter if it is reloadable
          tick[i] = true;                                         // emit a "tick"
        }
      }
    }
  }

// -------------------------------------------------------------------

  if (mainTick) {                                         // 1 s tick
  }

// -------------------------------------------------------------------

  if (tick[0]) {                                          //
    tick[0] = false;
    timeCounter[1] = timeInterval[1];                     // setup the next tick

    red   = false;                                        // setup flags
    green = true;
    blink = false;
  }

// -------------------------------------------------------------------

  if (tick[1]) {                                          //
    tick[1] = false;                                      // clear flag so that code runs only once every tick
    timeCounter[2] = timeInterval[2];                     // setup the next tick

    red   = true;
    green = false;
    blink = false;
  }

// -------------------------------------------------------------------

  if (tick[2]) {                                          //
    tick[2] = false;                                      // clear flag so that code runs only once every tick
    timeCounter[0] = timeInterval[0];                     // setup the next tick

    red   = false;
    green = false;
    blink = true;
  }

// -------------------------------------------------------------------

  if (mainTick) {                                         // can have multiples of these
    mainTick = false;                                     // clear the flag in the last one
  }

// -------------------------------------------------------------------

  digitalWrite(redLED  , red             ? HIGH:LOW);     // C++ ternary operator
  digitalWrite(greenLED, green           ? HIGH:LOW);
  digitalWrite(redLED  , blink && subTick? HIGH:LOW);     // subTick changes every 500 ms
}

```
> 2 votes

---
Tags: esp8266, interrupt, time, millis
---


# Question
Title: Arduino works indefinitely without PC contact
I'm studying H-Bridge for DC motors. I have a 9V battery, DC motor (9v), Arduino Nano and L293D. I'm following Jeremy Bloom's book about Arduino. Well, the system works perfectly with a PC connected. When I turn off the PC and connect the battery only, it doesn't work at all. The system should work only with a 9V battery.

const uint8_t MC1 = 8;
const uint8_t MC2 = 7;
const uint8_t POT = 0;

uint16_t velocity = 0;
uint16_t PWM = 0;

void forward(uint16_t);
void reverse(uint16_t);
void brake();

void setup(){
  Serial.begin(9600);
  pinMode(EN, OUTPUT);
  pinMode(MC1, OUTPUT);
  pinMode(MC2, OUTPUT);
  brake();
}

void loop(){
  Serial.println(PWM);
  PWM = analogRead(POT);
    if (PWM > 562){
    velocity = map(PWM, 563, 1023, 0, 255);
    forward(velocity);
  }
  if (PWM < 462){
    velocity = map(PWM, 461, 0, 0, 255);
    reverse(velocity);
  }
}

void forward(uint16_t speedValue){
  digitalWrite(EN, LOW);
  digitalWrite(MC1, HIGH);
  digitalWrite(MC2, LOW);
  analogWrite(EN, speedValue);
}

void reverse(uint16_t speedValue){
  digitalWrite(EN, LOW);
  digitalWrite(MC1, LOW);
  digitalWrite(MC2, HIGH);
  analogWrite(EN, speedValue);
}

void brake(){
  digitalWrite(EN, LOW);
  digitalWrite(MC1, LOW);
  digitalWrite(MC2, LOW);
  digitalWrite(EN, HIGH);
}```

The A0 pin is used to rotate the sensor (PWM).

[![The circuit][1]][1]

  [1]: https://i.stack.imgur.com/GliSw.png

# Answer
> 0 votes
> Well, I connected 7.4V 1500mAh Li-ion battery and... it's working. Could you explain why??

The PP3 batteries (rectangular 9v battery with snap-on terminals) can supply only a very limited amount of current; barely enough to run an Arduino at all, and none left over to run a motor or other higher current devices.
The best application for PP3s is in low-current, standby devices like smoke detectors, which need very little current under normal circumstances (no smoke) but can draw enough current to make a lot of noise for long enough to wake you up and alert you to the danger, when they detect smoke.

For your application you need a larger capacity battery that can supply more current. Carbon, Alkaline, and nickel chemistries could all work, provided the battery is large enough to supply the current you need; the PP3's form factor is its limitation. Li-ion's big advantage over the other chemistries is, of course, it's rechargeability, and with less degradation than Nickel-based rechargeables.

---
Tags: arduino-nano, h-bridge, l293d
---


# Question
Title: Updating multiple Arduino Nanos with same INO file
BTW - I have, unsuccessfully, searched for an answer before posting.

I have an NodeMCU connected to a bunch of Arduino Nanos over the I2C bus. The WiFi-enabled NodeMCU has the capability to do OTA updates on itself, which I've mastered but I want to update the same code into all of the slave Nano devices.

Is this possible? If so, what is the easiest way? The devices will be installed on a wall, so I don't want a bunch of USB cables trailing out of it.

Can I use/share the WiFi connection on the NodeMCU, with the Nanos, via the I2C bus? Or is there a better way?

PS - I have read about compiling the .INO file into a hex or bin file but still don't understand the process properly.

PPS - updating .INO files OTA on an ESP8266/WiFi enabled NodeMCU is great but they are bigger (wider) that a Nano and would cost a lot of money as I would need about 30 or so.

# Answer
> 2 votes
The compilation and linking process turns the .INO file into a .HEX file which is basically the machine-code that gets loaded into the processor. It is easy enough to get hold of that file as part of the compilation process.

To update the firmware in your Nanos, you basically need to replace the existing bootloader (which updates via the serial interface) with one which updates via I2C.

I see such a bootloader exists here on Github.

> Is this possible?

Sounds like it.

> If so, what is the easiest way?

Depends what you mean by "easiest". If the devices are mounted on a wall, that may be the easiest way.

What you might do is, after booting up, each device would query the master to see if an update was available\*. If it was, they would take turns to get the update supplied to them via I2C. If the update failed half-way through it might be hard to recover. You might want to have some sort of system where the bootloader checks if the main code is valid (eg. by a sumcheck) and if not, request another update.

I think it could be done, the mechanics could provide an interesting challenge. Have fun with it!

---

* One possibility would be for the master to make an I2C broadcast (maybe every 10 minutes) of what the current software version is, and if the slave finds that it doesn't have the latest version, request an update. If the master was busy (perhaps because it was updating another slave) the slave might wait 5 minutes and try again.

---
Tags: i2c, nodemcu
---


# Question
Title: Why doesn't this code for an 8x8 LED matrix work properly?
There's an Arduino Uno (Keyestudio KS0078) and a 788BS 8x8 LED matrix. I built the circuit as on the image and ran this program:

```
#define MY_PERIOD 200

int displayColumn = 0;
uint32_t tmr1;

unsigned char Text[] = { 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c };

void Draw_point(unsigned char x, unsigned char y) {
  clear();
  digitalWrite(x + 2, HIGH);
  digitalWrite(y + 10, LOW);
  delay(1);
}

void show_num(void) {
  unsigned char i, j, data;
  for (i = 0; i < 8; i++) {
    data = Text[i];
    data <<= displayColumn;
    for (j = 0; j < 8; j++) {
      if (data & 0x01) {
        Draw_point(j, i);
      }
      data >>= 1;
    }
  }
}

void setup() {
  Serial.begin(9600);
  int i = 0;
  for (i = 2; i < 18; i++) {
    pinMode(i, OUTPUT);
  }
  clear();
}

void loop() {
  show_num();
  if (millis() - tmr1 >= MY_PERIOD) {
    tmr1 = millis();
    displayColumn++;
    if (displayColumn > 7) {
      displayColumn = 0;
    }
  }
}

void clear() {
  for (int i = 2; i < 10; i++)
    digitalWrite(i, LOW);
  for (int i = 10; i < 18; i++)
    digitalWrite(i, HIGH);
}

```

I got the code from the Keyestudio examples wiki and added a part with `displayColumn` and shifting to the left every 0.2 sec. But instead of fading out fully on the 7th step, one LED (x=0, y=6) stays on. Even if I stop executing `show_num` when `displayColumn > 7` it stays on as long as there is power. Why?

UPD: I removed dynamic shifting in `loop` and set `displayColumn` in 5, 6 and 7 - the display showed correct result and was empty when `displayColumn` was equal to 7. Obviously the bug hides between "transitions".

UPD2: If I try the programm with other symbol, the bug on the step 7 always repeats with other LED which was the last lighted one on the step 6.

UPD3: Debug data by request of @thebusybee (repeated blocks removed)

```
x,y:2,1 x,y:3,1 x,y:4,1
x,y:1,2 x,y:5,2
x,y:1,3 x,y:5,3
x,y:1,4 x,y:5,4
x,y:1,5 x,y:5,5
x,y:1,6 x,y:5,6
x,y:2,7 x,y:3,7 x,y:4,7
displayColumn: 1
x,y:3,1 x,y:4,1 x,y:5,1
x,y:2,2 x,y:6,2
x,y:2,3 x,y:6,3
x,y:2,4 x,y:6,4
x,y:2,5 x,y:6,5
x,y:2,6 x,y:6,6
x,y:3,7 x,y:4,7 x,y:5,7
displayColumn: 2
x,y:4,1 x,y:5,1 x,y:6,1
x,y:3,2 x,y:7,2
x,y:3,3 x,y:7,3
x,y:3,4 x,y:7,4
x,y:3,5 x,y:7,5
x,y:3,6 x,y:7,6
x,y:4,7 x,y:5,7 x,y:6,7
displayColumn: 3
x,y:5,1 x,y:6,1 x,y:7,1
x,y:4,2
x,y:4,3
x,y:4,4
x,y:4,5
x,y:4,6
x,y:5,7 x,y:6,7 x,y:7,7
displayColumn: 4
x,y:6,1 x,y:7,1
x,y:5,2
x,y:5,3
x,y:5,4
x,y:5,5
x,y:5,6
x,y:6,7 x,y:7,7
displayColumn: 5
x,y:7,1
x,y:6,2
x,y:6,3
x,y:6,4
x,y:6,5
x,y:6,6
x,y:7,7
displayColumn: 6

x,y:7,2
x,y:7,3
x,y:7,4
x,y:7,5
x,y:7,6

displayColumn: 7

//many many empty strings
displayColumn: 8

```

# Answer
As found out during the discussion, the display must be cleaned before drawing any new row. And since the `clear()` calling was at the beginning of the `Draw_point()` and this function was not used in the last step, cleaning was not executed before the last step. This is correct for static rendering but for scrolling it will be correct to move the `clear()` to the end of the `Draw_point()` then the project works correctly.

```
#define MY_PERIOD 200

int displayColumn = 0;
uint32_t tmr1;

unsigned char Text[] = { 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c };

void Draw_point(unsigned char x, unsigned char y) {
  digitalWrite(x + 2, HIGH);
  digitalWrite(y + 10, LOW);
  delay(1);
  clear();
}

void show_num(void) {
  unsigned char i, j, data;
  for (i = 0; i < 8; i++) {
    data = Text[i];
    data <<= displayColumn;
    for (j = 0; j < 8; j++) {
      if (data & 0x01) {
        Draw_point(j, i);
      }
      data >>= 1;
    }
  }
}

void setup() {
  Serial.begin(9600);
  int i = 0;
  for (i = 2; i < 18; i++) {
    pinMode(i, OUTPUT);
  }
}

void loop() {
  show_num();
  if (millis() - tmr1 >= MY_PERIOD) {
    tmr1 = millis();
    displayColumn++;
    if (displayColumn > 7) {
      displayColumn = 0;
    }
  }
}

void clear() {
  for (int i = 2; i < 10; i++)
    digitalWrite(i, LOW);
  for (int i = 10; i < 18; i++)
    digitalWrite(i, HIGH);
}

```

Thanks to users @6v6gt and @thebusybee for their help in finding the solution.
> 2 votes

# Answer
As an addition to your answer, this is for future visitors who want to learn more.

#### 1. Programming by Accident

Your analysis is correct, mine in an early comment is wrong.

The last LED of the second last "picture" is not cleared when the last "picture" is drawn. This is because you clear the matrix **only, if you switch on an LED.**

This is your original code:

```
void Draw_point(unsigned char x, unsigned char y) {
  clear();
  digitalWrite(x + 2, HIGH);
  digitalWrite(y + 10, LOW);
  delay(1);
}

```

In your solution you clear the complete matrix after the delay, which results in the expected effect.

However, you did not analyze the underlying to the end. You changed something after a random suggestion, and it "works." I have seen this so many times.

We know that `Draw_point()` handles only **one** LED. So we do not need to reset **all** pins to their respective off levels, 14 of the 16 are already fine. It suffices to do this for the single LED just switched on.

```
void Draw_point(unsigned char x, unsigned char y) {
  digitalWrite(x + 2, HIGH);
  digitalWrite(y + 10, LOW);
  delay(1);
  digitalWrite(x + 2, LOW);
  digitalWrite(y + 10, HIGH);
}

```

#### 2. Driving the LEDs in Reverse

As I mentioned in a comment, you drive the LEDs of the matrix in reverse, when they are off. We all know that comments will not be read, mostly. So I add this here. ;-)

Most LEDs stand some voltage in reverse. According to the 788BS' data sheet it has 5V as **absolute maximum** rating. I would not dare to apply that really.

All professionals drive their LED matrices such that only forward current is applied. All other LEDs are not driven at all.

The solution here is to change the pin mode of the pins.

```
#define MY_PERIOD 200

int displayColumn = 0;
uint32_t tmr1;

unsigned char Text[] = { 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c };

void Draw_point(unsigned char x, unsigned char y) {
  pinMode(x + 2, OUTPUT);
  digitalWrite(x + 2, HIGH);
  pinMode(y + 10, OUTPUT);
  digitalWrite(y + 10, LOW);
  delay(1);
  pinMode(x + 2, INPUT);
  pinMode(y + 10, INPUT);
}

void show_num(void) {
  unsigned char i, j, data;
  for (i = 0; i < 8; i++) {
    data = Text[i];
    data <<= displayColumn;
    for (j = 0; j < 8; j++) {
      if (data & 0x01) {
        Draw_point(j, i);
      }
      data >>= 1;
    }
  }
}

void setup() {
}

void loop() {
  show_num();
  if (millis() - tmr1 >= MY_PERIOD) {
    tmr1 = millis();
    displayColumn++;
    if (displayColumn > 7) {
      displayColumn = 0;
    }
  }
}

```

You don't need to `clear()` in `setup()`, because all pins are initially in "input" mode already.

#### 3. About Flicker

You tried with no `delay()` and see only a dim display. This is correct as the time the LED is on is short compared to the time of the rest of the program.

With `delay(2)` you experience flicker. Let's think about the timing here.

There are different "pictures" during the scroll, with the listed number of LEDs switch on:

| `displayColumn` | Number of LEDs switched on |
| --- | --- |
| 0 | 16 |
| 1 | 16 |
| 2 | 16 |
| 3 | 11 |
| 4 | 9 |
| 5 | 7 |
| 6 | 5 |
| 7 | 0 |

Because the Arduino is quite fast, we came approximate the calculations by neglecting the rest of the program.

Each single LED is shown for 2 ms according to `delay(2)`, so a complete picture sums up to repetition periods between (nearly) 0 ms (`displayColumn` = 7) and 32 ms (`displayColumn` = 0 to 2). The reciprocal gives us the display frequency, many know the term "frames per second" or frame rate. The lowest frame rate is with the longest period: 1 / 0.032 s = 31.25 Hz. Our eyes see this as flickering. BTW, as soon as the "picture" has fewer LEDs, the display will stop flickering.

Commonly human eyes see no flicker if the frame rate exceeds about 50 to 60 Hz. With `delay(1)` the periods are only half as long as with `delay(2)`, of course. The lowest frame rate is therefore 62.5 Hz, good enough for no flicker experience.

Please be aware that the frame rate drops with the number of LEDs switched on. If you want to have at least 50 Hz with `delay(1)`, you cannot have more than 20 LEDs: 1 / 50 Hz = 20 ms, which corresponds to 20 LEDs.

The solution here is to show a complete row at the same time. Because then there are just 8 rows to sequence, you can raise to `delay(2)` again: 8 rows * 2 ms \< 20 ms. The specific code is left as an exercise to the reader. Please be aware that you need to take electrical maximum ratings into account. The MCU of the Arduino has limits to the sourced current.

#### 4. Final Note

You might wonder why the linked resource (the Keyestudio examples wiki) shows this "not-so-perfect" source code. Well, as we can see from the bad formatting of the example, it was hacked down in a hurry and without being aware that beginners will be misguided.

Take all such resources with a lot of caution. Unfortunately, this is absolutely necessary. *(This includes my answer here, too.)*
> 1 votes

---
Tags: arduino-uno, led-matrix
---


# Question
Title: Issue with uploading Arduino sketch on Ubuntu 20.04
I'm encountering an issue while attempting to upload an Arduino sketch on my Ubuntu 20.04 system. Despite ensuring that the correct board is selected and the USB port is recognized properly, I consistently encounter the following error message:

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

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00
Failed uploading: uploading error: exit status 1

```

I have tried various troubleshooting steps, including changing the board, reinstalling the IDE, and resetting the settings, but none of them have resolved the issue.

Could anyone please provide guidance on how to troubleshoot and resolve this problem? Any assistance would be greatly appreciated.

# Answer
> 0 votes
When I have this problem, holding down reset on the board until uploading starts often works

---
Tags: arduino-uno, arduino-nano, uploading, avrdude, ubuntu
---


# Question
Title: Unable to find PCA9685 module when using the I2CScanner library: no servo movement
I am trying to use an Adafruit PCA9685 servo driver module with an ELEGOO Mega 2560 board.

I am supplying the servo driver board with 5 V and tested all the wires to make sure. I tested the servo without the board and it works fine.

I2CScanner code:

```
#include "I2CScanner.h"

I2CScanner scanner;

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

    scanner.Init();
}

void loop()
{
    scanner.Scan();
    delay(5000);
}

```

# Answer
The I2C bus needs a set of pull up resistors. When buying assembled I2C devices, the designer may include I2C pull up resistors but not connect them. This is because, according to this sparkfun.com tutorial, you only need about 4.7K Ohms of pull up resistance. Adding multiple I2C boards to the same bus all with their own pull up resistors will lower this resistance and may damage I2C drivers. So, it is up to the end-user to decide which I2C board to connect the pull up resistors on.
> 0 votes

---
Tags: arduino-mega, i2c, servo, pwm
---


# Question
Title: ESP32 cam and MB code uploaded but nothing in Serial Monitor
The code works successfully but nothing happens in the serial monitor, what do I do as I've tried almost everything.

# Answer
## No longer an issue.

**Any fully released version of the 2.X IDE including the original 2.0.0 release should work. If you're having a problem these days it is probably because you've selected the wrong board causing problems as explained below.**

At the time the original answer was given the 2.0-rc9.1 release candidate was current. IDE version 2.0-rc9.3 bundled arduino-cli version 0.27.0-rc.1 which contains code to make the relevant settings work. So every version form the official 2.0.0 release to current (version 2.1.1 as of this update).

## Original Answer

**In short, use the 1.X series IDE instead of the 2.X series IDE. As of writing, this would be IDE version 1.8.19.**

---

In version 1.8.4 support for a board properties called `.serial.disableDTR` and `.serial.disableRTS` were added.

Certain boards, like the ESP32-CAM combined with the ESP32-CAM-MB require this feature in order for the Serial Monitor to see traffic (actually it's worse than that, which I'll explain below). The current 2.X series IDE (2.0-rc9.1 as of writing), which has a completely different code base, appears not to have re-implemented this feature. Presumably they will eventually.

**When you install the 1.X series IDE, make sure you test the Serial Monitor with the ESP32-CAM selected.** It may be counterintuitive that testing an Arduino UNO as your selected board wouldn't just work, given that you're *only* using the Serial Monitor and not actually compiling or uploading. But it will, no kidding, fail to work as this board's definition does not specify these `.serial.disableDTR` and `.serial.disableRTS` properties that the ESP32-CAM board description does.

In case you're wondering, ESP32 upload tool controls DTR and RTS itself irrespective of these board definition properties that affect the Serial Monitor and Serial Plotter. That's why your uploading works but your Serial Monitor fails under the current IDE 2.0 release candidate.

Without going into detail on what DTR and RTS are supposed to do, and what they can be made to do, etc, typical operating configurations for a serial port are such that when the port is open these signals are going to go active. The ESP32-CAM-MB board design is such that having both active DTR and RTS both active is effectively pushing down both the GPIO0 and rather crucially the EN/RESET buttons. In other words, without this additional fiddling that the 1.X series IDEs (*with* correct board selected) and esptool do, opening the serial port has the effect of holding your ESP32-CAM in reset (or NOT-enabling it if you like). So not only are you not getting any serial traffic, the board is simply not executing any code at all.

---

You have other options also, but each kind of requires an explanation in its own right. But, I can give you hints as to what they are:

It is possible to continue using the 2.0 IDE to do your development and upload but use something else instead of the 2.0 IDE's Serial Monitor. But it will introduce complexity, confusion, and annoyance into your setup. Whatever that "something else" is must allow for the disabling for DTR and RTS. *Note that disabling DTR and RTS is **not** merely turning off flow control; that will not manipulate them and it will ignore their counterpart signals, but it will also leave them in the wrong state.* One candidate is IDE 1.x's Serial Monitor. Another is RealTerm, which will allow you to clear DTR and RTS (in that order) to then work as a serial monitor. In any case you will need to close the serial connection yourself prior to each upload as the 2.0 IDE will be unable to do that on your behalf as it would normally do its own internal monitor.

You can also interrupt the DTR an RTS signals in hardware before the get to the ESP32-CAM board. Having done that, it no longer matters whether any software controls DTR and RTS, but you then need to manually operate GPIO0 and EN/RESET yourself to enter the bootloader. To accomplish that you'll either need to use a mess of jumpers and the ESP32-CAM-MB (or any other 3.3V serial transceiver) not mounted to the ESP32-CAM and construct push button circuits for GPIO0 and EN/RESET. Alternately you can physically modify the ESP32-CAM-MB in a way that interrupts DTR and RTS from the transceiver but keeps operational buttons. This can be done by desoldering a pair of diodes or cutting the traces on the way to the buttons and headers.

It may also only take a few well placed lines in one of the 2.0 IDE's javascript/typescript to crudely hack in a disabling of DTR and RTS, if you don't care what else it breaks. If I get bored maybe I'll look into that. Doing it properly in response to the correct board properties is a more involved project though.
> 4 votes

# Answer
If you use the command line, you can use this command to open a serial console to the esp32:

```
arduino-cli monitor -p /dev/ttyUSB0 --discovery-timeout 60s --config 'rts=off' --config 'dtr=off' --config 'baudrate=115200'

```

If you use the IDE, see the answer of timemage.
> 3 votes

# Answer
I'm using platformIO and had the same issue. Disabling the RTS and DTR solved my problem too!

```
monitor_dtr = 0
monitor_rts = 0

```
> 2 votes

---
Tags: esp32
---


# Question
Title: Multiple symbol definition related to USART_RX_vect from Serial
When trying to compile the sketch below, I get this error when using either the IDE or the CLI:

```
HardwareSerial0.cpp.o (symbol from plugin):
In function `Serial':
(.text+0x0): multiple definition of `__vector_18'

```

This seems to have something to do with multiple definitions of `USART_RX_vect`.

Since I'm not using any extra libraries, that doesn't seem to be the source of the problem (though library conflicts are the source of many similar problems I've seen on here and elsewhere). Any suggestions on how to fix this?

Sketch:

```
// Listen to the Serial Port for Instructions and Print Register Values

volatile boolean start = false;  // flag to start register inspection; global

void setup() {
  Serial.begin(9600);
  if (Serial) {
    Serial.println("Arduino listening...");
    Serial.println("Enter g or s at any time");  // g = go, s = stop
  }
}

void loop() {
  while (start) {
    // print the values of some ADC registers
    Serial.print("ADMUX  register: ");
    print_bin(ADMUX);
    Serial.print("ADCSRA register: ");
    print_bin(ADCSRA);
    Serial.println(" ");
    delay(1000);
  }
}

ISR(USART_RX_vect) {
  unsigned char data;
  data = UDR0;
  if (data == 'g') {
    start = true;
  }
  if (data == 's') {
    start = false;
  }
}

void print_bin(byte aByte) {
  for (int8_t aBit = 7; aBit >= 0; aBit--) {
    if (aBit == 3) {
      Serial.print(" ");
    }
    Serial.print(bitRead(aByte, aBit) ? '1' : '0');
  }
  Serial.println(" ");
}

```

Using the Arduino IDE as follows:
Version: 2.3.0
Date: 2024-02-07T13:40:21.377Z
CLI Version: 0.35.2

# Answer
`USART_RX_vect` is defined by the Arduino core library. It is part of the implementation of the `Serial` object. Your sketch has a second definition of the same ISR, thus the conflict.

Basically you have two choices: either you write your own code to handle the serial port at the I/O register level (like in your ISR above), or you rely on the `Serial` implementation of the Arduino core (`Serial.available()` and `Serial.read()` to read data). You cannot mix the approaches like you are trying to do here.
> 2 votes

---
Tags: serial
---


# Question
Title: Can't get serial port's attention once sketch is running
This sketch is supposed to listen for a single character sent to the serial port, as a means of starting and stopping data collection (which in this example is mocked by printing some register values). It reacts to the first character sent (`g`), and the `while` loop begins executing. But it doesn't react to a subsequent `s` character, it seems I can't get Arduino's attention.

Perhaps this is related to this answer but I'm not sure. If that's the problem, I could use some general suggestions about how to work around the limitations. If it's something else, well obviously I need a suggestion for that as well!

```
// Listen to the Serial Port for Instructions and Print Register Values

volatile boolean start = false;  // flag to start register inspection; global

void setup() {
  Serial.begin(9600);
  if (Serial) {
    Serial.println("Arduino listening...");
    Serial.println("Enter g or s at any time");  // g = go, s = stop
  }
}

void loop() {
  unsigned char data;
  if (Serial.available()) {
    data = Serial.read();
    Serial.println(data); // only for troubleshooting
    if (data == 'g') {
      start = true;
    }
    else  if (data == 's') {
      start = false;
    }
  }

  while (start) {
    // print the values of some ADC registers
    Serial.print("ADMUX  register: ");
    print_bin(ADMUX);
    Serial.print("ADCSRA register: ");
    print_bin(ADCSRA);
    Serial.println(" ");
    delay(1000);
  }
}

void print_bin(byte aByte) {
  for (int8_t aBit = 7; aBit >= 0; aBit--) {
    if (aBit == 3) {
      Serial.print(" ");
    }
    Serial.print(bitRead(aByte, aBit) ? '1' : '0');
  }
  Serial.println(" ");
}

```

Environment: Version: 2.3.0 Date: 2024-02-07T13:40:21.377Z CLI Version: 0.35.2

# Answer
> 2 votes
There is nothing in your `while (start) {` loop that would allow `start` to become `false`.

```
  while (start) {
    // print the values of some ADC registers
    Serial.print("ADMUX  register: ");
    print_bin(ADMUX);
    Serial.print("ADCSRA register: ");
    print_bin(ADCSRA);
    Serial.println(" ");
    delay(1000);
  }

```

...and so your loop continues while data is piling up in `Serial`'s input buffer.

`loop()` is already a functional loop. Changing `while (start) {` to `if (start) {` seems to be what you're looking for.

```
void loop() { // <-- existing loop
  unsigned char data;
  if (Serial.available()) {
    // stuff that can change start
  }

  if (start) {
    // stuff that happens if start is true
  }
}

```

You may want to look at the blink without delay example for handling your `delay(1000)` differently.

---
Tags: arduino-uno, serial
---


# Question
Title: ESP32 with static IP address acting as client connecting to ESP32 acting as access point
I have an ESP32 board as a client with a static IP address. The client with the static IP address connects to a second ESP32 that is acting as an access point. The connection is established and the access point recognizes the new connected device.

The problem is, with the client having a static IP address the access point displays the client IP as 0.0.0.0. If the client does not have the IP address set as static, the access point displays the correct IP address.

The code for the client:

```
#include <WiFi.h>

const char* ssid = "ESP32-AP";
const char* password = "123456789";
IPAddress ip(192, 168, 0, 101);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  // Configure the static IP address
  WiFi.config(ip, gateway, subnet);

  WiFi.begin(ssid, password);

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

  Serial.println("");
  Serial.println("Connected to WiFi network");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {
  static long general_t1 = 0;

  if (millis() - general_t1 > 2000) {
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    general_t1 = millis();
  }
}

```

The code for the access point:

```
#include <Arduino.h>
#include <WiFi.h>
#include "esp_wifi.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

const char *ssid = "ESP32-AP";      // SSID Name
const char *password = "123456789"; // SSID Password - Set to NULL to have an open AP
const int channel = 10;             // WiFi Channel number between 1 and 13
const bool hide_SSID = false;       // To disable SSID broadcast -> SSID will not appear in a basic WiFi scan
const int max_connection = 5;       // Maximum simultaneous connected clients on the AP

IPAddress local_ip(192, 168, 0, 1);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

//*** void display_connected_devices() **************************************************************
void display_connected_devices() {
  wifi_sta_list_t wifi_sta_list;
  tcpip_adapter_sta_list_t adapter_sta_list;
  esp_wifi_ap_get_sta_list(&wifi_sta_list);
  tcpip_adapter_get_sta_list(&wifi_sta_list, &adapter_sta_list);
  String deviceInfo = "";

  if (adapter_sta_list.num == 0) {
    deviceInfo = "No Device connected";
  }
  else {
    for (int i = 0; i < adapter_sta_list.num; i++) {
      tcpip_adapter_sta_info_t station = adapter_sta_list.sta[i];
      deviceInfo += "Device " + String(i) + " = ";
      deviceInfo += IPAddress((&station.ip)->addr).toString();
      deviceInfo += "\n";
    }
  }

  // Display accumulated device information
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);
  display.println("AP IP: " + WiFi.softAPIP().toString());
  display.setCursor(0, 20);
  display.println(deviceInfo);
  display.display();
  display.clearDisplay();
}

//***********************************************************************************************
//**                                   void setup()
//***********************************************************************************************
void setup() {
  Serial.begin(115200);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }

  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(25, 10);
  display.println(F("ESP-32"));
  display.setCursor(25, 30);
  display.println(F("Router"));
  display.display();
  delay(2000);

  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  WiFi.softAP(ssid, password, channel, hide_SSID, max_connection);
  Serial.print("[+] AP Created with IP Gateway ");
  Serial.println(WiFi.softAPIP());
}

//***********************************************************************************************
//**                                  void loop()
//***********************************************************************************************
void loop() {
  display_connected_devices();
  delay(5000);
}

```

# Answer
Not digging deep in API, as @Jurai says, it lists IP from DHCP server on AP, which know nothing about static IPs.

1. As you set static IP to "Client" - just use it (192.168.0.101) (KISS rule)
2. On AP implement web API which allow client to register itself
3. Use mDNS (aka Avahi, aka Bonjour) multicast discovery espressif-skd doc arduino-esp32 ESPmDNS library

What is Your goal in using static IP on Client?
> 1 votes

---
Tags: esp32, tcpip
---


title: Problem installing RPLidar library

text:
# Question
Title: Problem installing RPLidar library
I'm trying to add the RPLidar library. I've already checked this solution, but it's not working for me, I get this error :

`Error: 13 INTERNAL: Library install failed: extracting archive: Not a supported archive`

Do you have a solution ?

# Answer
Are you trying to install this library through the Arduino IDE? Then maybe it doesn't work, because this library doesn't conform to the normal library structure for Arduino.

You can install it manually.

* Download the library from Github
    + either by downloading the ZIP-file and extracting it
    + or by using `git clone` on your machine, if you have git installed.
* Move the folder `RPLidarDriver` into the libraries folder. You can normally find this in `Arduino/libraries` in your home directory. If you cannot find it, look in the Arduino IDE in the preferences dialog. There the sketchbook location should be mentioned. `libraries` is a folder inside the sketchbook location.

Then you should be able to compile your code. I've tested this with the examples provided by the library.
> 1 votes

---
Tags: library
---


title: Generation of TTL Signal

text:
# Question
Title: Generation of TTL Signal
I would like to generate a TTL signal using an Arduino.

As far as I understand, a TTL signal is just a predefined controlled signal that repeats at a certain interval (e.g. 2 μs).

An Arduino circuit arguably has a very fast clock (e.g. 16 MHz), so what I thought is I can basically just draw a square signal for whatever desirable interval (important to be down to the microsecond).

I used the following code, choosing a pin and changing its signal state between 0 and 1 and then using `Serial.println` to draw the signal out. Everything is inside a while loop that times everything to be generated exactly within 1 second.

```
#include <arduino-timer.h>

// Variables
unsigned long v = -1;
int freq = 100.0; // Hz
unsigned long d = floor(1.0/freq*1000000.0) ; // us
Timer<1, micros> timer; // create a timer with 1 task and microsecond resolution

void setup() {
  unsigned long repeatEvery = 5000000; // Microseconds
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  timer.every(repeatEvery, func1); // XXXXX microsec
}

void func1() {
  unsigned long uSec = 1000000; // Microseconds (= 1 sec)

  PORTD = B00000000;
  v = digitalRead(3);

  unsigned long counter = 0, i = 0;

  auto currentTime = micros();
  auto prevTime = currentTime;
  d = 0; // no delay to check the speed of the execution

  do {
    PORTD = B00001000;
    v = digitalRead(3);
    // Serial.println(v);
    PORTD = B00001000;
    v = digitalRead(3);
    // Serial.println(v);
    delayMicroseconds(d); // first frame

    PORTD = B00000000;
    v = digitalRead(3);
    // Serial.println(v);
    PORTD = B00000000;
    v = digitalRead(3);
    // Serial.println(v);
    delayMicroseconds(d); // second frame

    currentTime = micros();
    i = (unsigned long)(currentTime - prevTime);
    counter++;
  } while(i < uSec);

  Serial.print(">>>Counter:");
  Serial.println(counter);
  Serial.print(">>>delay (ms):");
  Serial.println(d);
}

void loop() {
  timer.tick();
}

```

The code above will give output as `counter = 47620 // how many times the instructions were repeated` and if the `Serial.println` lines were uncommented to draw the signal then the execution time slows down to `counter = 86`

I am not sure if the whole train of thought is wrong and I should do something else or use a different circuit.

Any hint or help would be highly appreciated.

PS: my Arduino by the way is a UNIROI that is supposed to be the same as an Arduino R3.

# Answer
> 1 votes
The 1u/2us are pretty fast - you have 16 or 32 instruction cycles @16MHz.

And now you have digitalRead that usually takes around 70 instruction cycles (several times), after that 32b arithmetics (hundreds instructios).

When you uncomment Serial.printlns that starts being blocking after the internal buffer is filled plus you even use 9600bauds speed (960 characters per second max speed), each println means 3 characters and it's there 4 times -\> 960/12 = around 80 loops per second. Do you see the pattern?

The only way to generate jitter free signals are timers (probably fast PWM with prescaler=1 and top value according to your desired period).

---
Tags: signal-processing
---


# Question
Title: How to create and edit fonts for the Adafruit GFX library?
I noticed that the `TomThumb.h` font included in the Adafruit GFX library has characters that have different widths, which is a problem for me because I'm doing text processing that requires characters to have the same dimensions (width and height).

I also noticed that the `TomThumb.h` font misses some characters (such as `'`). I need a way to create/edit fonts for the Adafruit GFX (where I'm using the Adafruit\_ST7735 on a 1.8" TFT display). I've looked around the internet but I couldn't find anything decent.

# Answer
I found an online editor that can parse Adafruit GFX font headers, modify, and export the result to create a new font header. It works very well. May be a bit late to help OP, but for anyone else looking...

It uses regexes to extract info from the header files, so it's pretty strict on following the layout of GFX font headers provided by Adafruit.

webpage: https://tchapi.github.io/Adafruit-GFX-Font-Customiser/
github: https://github.com/tchapi/Adafruit-GFX-Font-Customiser
> 1 votes

# Answer
One possible solution you might already have: There’s a small utility called `fontconvert` that’s part of the Adafruit GFX library. The source code is installed by default together with the Adafruit GFX library in `Arduino/libraries/Adafruit_GFX_Library/fontconvert` You need Linux to compile it from the provided source code. It also compiles and runs on a Raspberry Pi.

It takes care of converting TrueType fonts (completely or partially) to Adafruit GFX format. There’s some documentation on compiling and using it in the fontconvert directory.
> 0 votes

# Answer
I have used this website to generate various fonts, sizes, etc. with success.

http://oleddisplay.squix.ch/#/home
> 0 votes

# Answer
I have used truetype2gfx - Converting fonts from TrueType to Adafruit GFX.

It can make various sizes to a complete standard font.
> 0 votes

---
Tags: adafruit, tft
---


# Question
Title: Sketch halts if button is pressed on boot
I have a KY-040 rotary encoder with a push button wired to an ESP8266. My objective is to be able to detect if the button is pressed or not on boot.

In the below code, if I hold the button down and power on the ESP8266, neither "IT'S STARTED" or "IT'S LOOPING" is printed in the serial monitor, even if I release the button. If I don't press the button, the code works as expected and prints "IT'S STARTED" followed by "IT'S LOOPING". It's as though the code gets stuck/halted if I press the button on boot.

Can someone explain why this is happening?

I would also appreciate suggestions on how I can detect the status (pressed/not pressed) of the button when the ESP8266 is powered up.

Here is my code:

```
void setup() {
  pinMode(D3, INPUT_PULLUP);
  Serial.begin(115200);
  Serial.println("IT'S STARTED");
}

void loop() {
  Serial.println("IT'S LOOPING");
  delay(1000);
}

```

# Answer
Description of pin D3 from this ESP8266 pinout reference:

> connected to FLASH button, boot fails if pulled LOW

So you cannot pull this pin to LOW during boot, as it will keep the ESP in flash mode. You need to use a pin, that doesn't have this limitation, like D1, D2, D5, D6 or D7.
> 4 votes

---
Tags: serial, esp8266, button, pull-up, pinmode
---


# Question
Title: Physically passing through a pin to access another
I would like to know about physically passing through a pin in order to get to another. For instance, if I have a sensor on one side of an ATMEGA328P or ESP8266 (Wemos D1 Mini) yet need to connect to a pin on the other side, would I be able to simply go through an unused pin instead of worrying about going around or using a jumper wire? If so, would I need to set the unused pin in a certain way, for example as an input (with or without pull-up)?

PS: The diagram of the first answer illustrates my question exactly and the answer has been accepted as the solution.

# Answer
Let me see if I understand what you are asking. You want to connect **both** the relevant pin and an unrelated one, like in this DIP footprint:

If this is the case, the answer is yes, provided that the pass-through pin is always held in a high-impedance (i.e. `INPUT`) state.
> 0 votes

# Answer
Make sure that the unused pin isn't configured for any conflicting functions like SPI, I2C, or UART communication, as this could interfere with the signal you're routing.
> 0 votes

---
Tags: esp8266, atmega328, pins
---


# Question
Title: Difficulties acquiring angle values from MPU6050
I'm attempting to acquire angle values from an MPU6050 IMU sensor using an ESP32-DevKitM-1 microcontroller.

My setup contains the ESP32 board, the MPU6050 board, and an SD card reader to save the readings from the sensor:

I'm using the Arduino IDE v2.3.0.

I adapted the following testing code excerpt from another post about sensor, using the newer Adafruit\_MPU6050 library and the SD functions:

```
#include <Wire.h>
#include "SPI.h"

#include <Adafruit_Sensor.h>
#include <Adafruit_MPU6050.h>

#include "SD.h"

const int PIN_IMU_SCL = 22;
const int PIN_IMU_SDA = 21;
const int PIN_SD_CS = 23;
const int PIN_SD_MISO = 10;
const int PIN_SD_MOSI = 18;
const int PIN_SD_CLK = 5;

const int IMU_GyroScale = 131;

Adafruit_MPU6050 IMU;
double IMU_Time;
double IMU_TimePrev = -1;
double IMU_GyroRotX;
double IMU_GyroRotY;
double IMU_GyroRotZ;

File DataFile;

void IMU_GetData(double& angleX, double& angleY, double& angleZ, double& temp)
{
  bool firstTime = false;

  if (IMU_TimePrev == -1)
    firstTime = true;

  // Calculating the elapsed time...
  IMU_TimePrev = IMU_Time;
  IMU_Time = millis();
  double timeDelta = (IMU_Time - IMU_TimePrev) / 1000;

  // Acquiring the readings from the accelerometer & gyroscope...
  sensors_event_t accelData;
  sensors_event_t gyroData;
  sensors_event_t tempData;
  IMU.getEvent(&accelData, &gyroData, &tempData);

  // Calculating the accelerometer angle...
  double accelRotX = (180 / PI) * atan(accelData.acceleration.x / sqrt(pow(accelData.acceleration.y, 2) + pow(accelData.acceleration.z, 2)));
  double accelRotY = (180 / PI) * atan(accelData.acceleration.y / sqrt(pow(accelData.acceleration.x, 2) + pow(accelData.acceleration.z, 2)));
  double accelRotZ = (180 / PI) * atan(sqrt(pow(accelData.acceleration.x, 2) + pow(accelData.acceleration.y, 2)) / accelData.acceleration.z);

  // Calculating the gyroscope angle...
  double gyroRotX = (gyroData.gyro.x / IMU_GyroScale);
  double gyroRotY = (gyroData.gyro.y / IMU_GyroScale);
  double gyroRotZ = (gyroData.gyro.z / IMU_GyroScale);

  // Combining the two (complementary filter)...
  if (firstTime)
  {
    IMU_GyroRotX = accelRotX;
    IMU_GyroRotY = accelRotY;
    IMU_GyroRotZ = accelRotZ;
  }
  else
  {
    IMU_GyroRotX += timeDelta * gyroRotX;
    IMU_GyroRotY += timeDelta * gyroRotY;
    IMU_GyroRotZ += timeDelta * gyroRotZ;
  }

  angleX = (0.96 * accelRotX) + (0.04 * IMU_GyroRotX);
  angleY = (0.96 * accelRotY) + (0.04 * IMU_GyroRotY);
  angleZ = (0.96 * accelRotZ) + (0.04 * IMU_GyroRotZ);

  temp = tempData.temperature;
}

bool IMU_Init()
{
  bool status = IMU.begin();

  if (status)
  {
    IMU.setAccelerometerRange(MPU6050_RANGE_8_G);
    IMU.setGyroRange(MPU6050_RANGE_500_DEG);
    IMU.setFilterBandwidth(MPU6050_BAND_21_HZ);
  }

  IMU_Time = millis();

  delay(100);

  return status;
}

void setup()
{
  Serial.begin(9600);
  Serial.println("Initializing...");

  Wire.begin(PIN_IMU_SDA, PIN_IMU_SCL);
  IMU_Init();

  SPI.begin(PIN_SD_CLK, PIN_SD_MISO, PIN_SD_MOSI, PIN_SD_CS);

  while (!SD.begin(PIN_SD_CS))
  {
    Serial.println("Unable to open SD!");
    delay(500);
  }

  DataFile = SD.open("/angles.txt", FILE_WRITE);
  DataFile.close();

  delay(100);
  Serial.println("Initialized!");
}

void loop()
{
  double angleX;
  double angleY;
  double angleZ;
  double temp;
  IMU_GetData(angleX, angleY, angleZ, temp);
  String anglesStr = String(angleX) + ":" + String(angleY) + ":" + String(angleZ);

  DataFile = SD.open("/angles.txt", FILE_APPEND);
  DataFile.println(anglesStr);
  DataFile.close();

  Serial.println(anglesStr);

  delay(200);
}

```

Where `IMU_GetData` is the function responsible for acquiring the angle data from the gyroscope and the accelerator sensors on the MPU6050 board, and implementing a filter to attain a set of filtered angle values.

I then simply save the filtered angle values to the SD card. I communicate with the sensor using the Wire I2C library, and with the SD card using the SPI library.

The main issue I'm running into is the fact that the resultant angle values do not appear to accurately represent the rotation of the sensor.

As a test, I rotated the sensor 360° slowly around each one of the 3 axes, and saved the continuous angle readings during each rotation:

The time interval between each reading in the plots above is ~0.2 s.

The first issue is that a rotation about the Z-axis visible in the last graph above appears to not cause any appreciable change in any of the angle readings.

I initally assumed that could be caused by the value of the `IMU_GyroScale` constant that the gyroscope angle values get multiplied by during the calculations carried out in the `IMU_GetData` function. I assumed that all MPU6050 chips will use that same scaling factor, but then I tried several of the other listed scaling factors listed in the datasheet, with no appreciable difference.

Is there something visibly wrong in my code with the angle calculations for the Z-axis? Could this be a sign of a defective sensor board?

The second thing I was curious about was the format of the filtered angle values.

I initially assumed that the filtered angle values I would be getting from the sensor would be the Euler angles; Roll, Pitch & Yaw. However, these appear to not represent those.

In fact, one of the main sources listed in the original posting that describes in detail the process of calculating the filtered angle values, also provides a visualization of the angle values acquired from the sensor:

Are these "tilt" values related to Euler angles? Is it possible to convert between the two?

# Answer
> 2 votes
The formulas you are using look plain wrong. There are a few issues that stick out:

* Rotating along *z* has no effect on the accelerometers. Any formula that pretends to give you the three Euler angles out of accelerometer data can only be wrong. You need a magnetic compass to get the yaw angle, otherwise you would have to rely solely on the gyros, which are prone to long-term drift.
* The formulas for updating angles from gyro data are awfully complex. You don't want to do that. You want to instead keep track of you attitude using quaternions, which give much nicer maths.
* If you look at the formulas that update `IMU_GyroRot*`, you should notice that they are prone to unbounded drift, which is then inherited by `angle*`. Obviously, the author of these formulas completely missed the point of a complementary filter.

I suggest you look at this old answer to a very similar question.

# Answer
> 0 votes
Make sure that the sensor is correctly orientated and calibrated, verify gyro scaling and range settings, and consider the application requirements when choosing between tilt angles and Euler angles. If Euler angles are necessary, you'll need to implement a different algorithm to calculate them accurately.

---
Tags: esp32, mpu6050, accelerometer, gyroscope
---