message:
Is it bad practice to multitask without timing constraints

Going through resources such as [several things at the same time][1] and with some greatly appreciated assistance on here I'm finally getting a grasp on how to multitask a microcontroller.

Most examples use the millis() approach to nonblocking programming. However, even in the link above the button state is being polled every loop (from what I understood).

So what confuses me is: is it bad practice to write functions, which poll sensor(s) and input(s) without timing constraints, i.e. at every iteration of loop?

Is this still consider nonblocking programming?

I've written some mock code to better illustrate what I mean. Thank you very much for reading through.

    void loop() {
        Button();
        Sensor();
        LED();
        // ...
    }

    void Button() {
      // Read button(s)
      button_state = digitalRead(button_pin);
      if (button_state == LOW) {
        // ...
      };
    };

    void Sensor() {
      // Read sensor
      int sensor_state = analogRead(sensor_pin);
      if (sensor_state >= 150) {
        // ...
      };
    };

  [1]: https://forum.arduino.cc/index.php?topic=223286.0

body:
Like often, the answer is: It depends.

Generally it is non-blocking programming, when you do only short things on each loop. What exactly can be considered short depends on the situation, meaning, what else you want to do.

For example: You are reading an analog value on every loop. The `analogRead()` will take about 100us ([reference][1]). I assume, that your sensor value is rather slow (so the time of signal above 150 would be rather long). Also you are reading a button with `digitalRead()`. The read takes about 3.6us ([reference][2]). So in total you have a loop of - lets say - 150us (with overhead and `loop()` iteration included). But the event, that you want to catch - the button press - will be in the ballpark of 100ms, which is a factor 667 greater, than the total time of your `loop()` (when no event happened). So in relation to the shortest event (the button press) all the reads can be considered non-blocking. (Though you could still get blocking through the code inside the if statements. Thats on you to investigate)

Non assume, that you don't have a button, but a digital signal, and you want to sense pulses down to 80us. Then your `analogRead()` would take too long and you could miss a pulse event. In this case `analogRead()` might be considered blocking.

So, to check if you are really using non-blocking code, you would need to ask yourself: Am I giving every code part enough time to execute right and to catch all the intended events? If yes, then you are non-blocking. If no, then you are blocking.

---

As a side note: Often polling is described as bad, but it really depends on the situation. In your case you poll the inputs sequentially, so every input gets polled at the same (total) rate at which your `loop()` runs. You are doing nothing else, so why should you lower the processing time by not use polling? The saved time cannot be used better on a microcontroller (in contrast to a PC, where the saved CPU time could be given to a different program).

  [1]: https://www.arduino.cc/en/Reference.AnalogRead
  [2]: https://forum.arduino.cc/index.php?topic=337578.0


sender: user

sender: assistant

body:
If you are running off battery, then you should consider having the
microcontroller sleep as much as possible, and not poll the sensors more
often than needed. AFAIK, the Arduino core library provides no facility
for managing sleep, but some third-party libraries are available for
that purpose.

If you project runs off mains power, then there is no point in adding
the complexity of sleep management. Unless your sensors are really slow,
polling them at each loop iteration is generally fine. Specifically, for
a push button, the documentation of the [Bounce2][] library states that
the button update method should be called on every loop iteration.

[Bounce2]: https://github.com/thomasfredericks/Bounce2


message:
random() Function isn't random at all

I'm using the `random()` to generate random coordinates for coins in a simple game console. The problem here is that the `random()` function is not generating random numbers, since the coin is at the same coordinates every single time I upload it. I am using the Adafruit GFX library with the [Adafruit 1.44" Color TFT LCD Display][1]. Here is my code (sorry, it's kind of long).

```
//necessary libraries
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library
#include <SPI.h>

//colors
#define BLACK    0x0000
#define BLUE     0x001F
#define RED      0xF800
#define GREEN    0x07E0
#define CYAN     0x07FF
#define MAGENTA  0xF81F
#define YELLOW   0xFFE0
#define WHITE    0xFFFF

//pins
#define TFT_CS  10
#define TFT_RST  9
#define TFT_DC   8

//joystick variables
const int VRxPin = A1;
const int VRyPin = A0;
const int SWPin  = 7;
bool mov = false;

//data read from joystick pins
int x = 0;
int y = 0;
int SW = 0;

// X and Y coords for entities
int playerx = 50;
int playery = 50;

long coinx;
long coiny;

//game variables
int score = 0;

//defining the tft class
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

//useful text function
void output(char *text, int x, int y, uint16_t color, bool wrap = 0){
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextWrap(wrap);
  tft.print(text);
}

//there is probably a better way to do this but im too lazy to find it
void num_output(int text, int x, int y, uint16_t color, bool wrap = 0){
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextWrap(wrap);
  tft.print(text);
}

//clears screen
void clear() {
  tft.fillScreen(BLACK);
}

//setup (lcd init & startup screen)
void setup() {
  Serial.begin(9600);
  pinMode(SWPin,INPUT_PULLUP);
  tft.initR(INITR_GREENTAB);

  long coinx = random(20, 100);
  long coiny = random(20, 100);

  clear();
  output("RAMBUTAN", 40, 60, RED);
  delay(1000);
  clear();
  tft.fillRect(playerx, playery, 5, 5, WHITE);
  tft.fillCircle(coinx, coiny, 5, YELLOW);
}

void loop() {
  //reads data from joystick pins every single tick
  int VRx = analogRead(VRxPin);
  int VRy = analogRead(VRyPin);
  int SW = digitalRead(SWPin);

  //converts joystick pin data into directions
  if (VRx > 250 && VRx < 750 && VRy > 250 && VRy < 750) {
    // middle
  } else if (VRx > 511.5 && VRy < 750 && VRy > 240) {
    // right
    playery -= 5;
    mov = true;
  } else if (VRx < 511.5 && VRy < 750 && VRy > 240) {
    // left
    playery += 5;
    mov = true;
  } else if (VRy > 511.5 && VRx < 750 && VRx > 240) {
    // up
    playerx += 5;
    mov = true;
  } else if (VRy < 511.5 && VRx < 750 && VRx > 240) {
    // down
    playerx -= 5;
    mov = true;
  } else {
    mov = false;
  }

  if (mov == true) {
    clear();
    tft.fillRect(playerx, playery, 5, 5, WHITE);
    num_output(score, 10, 10, WHITE);
    tft.fillCircle(coinx, coiny, 5, YELLOW);
    mov = false;
  }
  delay(100);
}
```

  [1]: http://-https://www.adafruit.com/product/2088

body:
You are correct, `random()` *isn't* random - it's *pseudo random*. It returns successive results from a mathematical formula which, to all intents and purposes, is random. It's also predictable, as you have seen.

The formula has a starting value, called the *seed*, which you can choose your self. Changing that *seed* gives you a different sequence of random-like numbers.

So the trick is to set the *seed* to something that is truly random. One common source of randomness, or *entropy*, is an unconnected ADC input:

```
randomSeed(analogRead(A3));
```

You can read more about the `randomSeed()` function [here](https://www.arduino.cc/reference/en/language/functions/random-numbers/randomseed/).


body: As an alternative to Majenko's answer, this is how I generate random n-bit-numbers: for each of the n bits I read the chip temperature (which is pretty noisy), take the least significant bit of the reading and assign it to the corresponding bit in the number. The results are sufficiently random for my purpose at least.


message:
Is it possible for the Arduino's digital pin mode to flip from OUTPUT to INPUT unexpectedly?

I have an Arduino project (data logger intended to sample 100 samples per second for months) with firmware that is too long to post. It mostly works as supposed to, but I have a confusing issue I can't figure out: rarely, the indicator LEDs (driven by digital pins) stop working. By rarely, I mean if I run 20 devices for two weeks, maybe one will develop the issue, so it's very hard to test empirically but it's frequent enough that it matters. I know it's not a hardware problem because they start again after a reset. The device apparently continues working fine apart from the LED issue when this happens.

I have three hypotheses:
 1. There's a logic problem in my firmware code. I'm skeptical because the relevant block of code is pretty simple.
 2. A memory overflow or some similar problem causes the program to fail at this one particular task but not others. I'm a little skeptical because the device reports free stack in the metadata every second and it's always over 40 bytes; I may be misunderstanding memory use though.
 3. Somehow, the digital pin (4) driving the LED gets flipped from OUTPUT to INPUT. There's definitely no `pinMode(4, INPUT)` command anywhere in my code though, so if this is happening it's not my code doing it.

Let's suppose it isn't #1. Considering #2: is it likely that a weird memory issue is causing a very specific failure while not affecting core functions of the device?

Considering #3, is there anyway the register setting a pin to INPUT or OUTPUT could be flipped unexpectedly? It sounds crazy to me but I want to rule it out.

The platform is similar to the Arduino Pro (3.3V, 8 MHz, ATMEGA328p) and I'm running the current IDE version (1.8.13). Thanks for any help.

body:
The fact that it is possible to set them incorrectly is why, in some projects where I'm concerned about this, I'll add a small series resistance to an inbound signal.  Should the pin become `OUTPUT` and driven in an opposing direction to the signal, the resistance serves to prevent a short through both devices.  The possibility is always there, whether you have an outright bug, or instability, or flash corruption.

With `pinMode` the opportunity to accidentally set your port to the wrong direction is maybe a bit worse than for code that directly manipulates the data direction register.  `pinMode` calls typically don't get inlined, because `pinMode` on the Arduino is a fairly complicated function at runtime for what it actually does.  So, there's this generic code that can be jumped to that will set various ports to either direction, as opposed to smaller chunks of code that contain instructions that set specific ports to specific settings.

`INPUT` roughly takes your digital pin out of the circuit.  And `INPUT_PULLUP` sort of does that, with the exception that internal to the AVR there's going to be 20k - 50k of resistance going to "5V".  Knowing that, you can test your hypothesis three.  When you find your project in the state where the LED isn't lit, take some some resistance (say 1K) and use it to pull the pin toward "5V".  Then pull it to GND.  Watch the voltage at the pin with a meter.  Based on what you have attached and what you see for a voltage, you can determine whether it has entered the `INPUT` or `INPUT_PULLUP` state.  You'll also be able to see if it's just being driven to whatever state you're calling "not working" ("off" I'm guessing).

You can take all the guess work out of what voltages to see in each scenario if you upload a sketch that sets the pin in question to the `INPUT`, `INPUT_PULLUP`, `OUTPUT`/`HIGH`, and `OUTPUT`/`LOW` states and measure the voltage at the pin when you pull it to each rail with your resistor.  Later you can consult the table you've built to see what has happened.

There's only so much to say about this, particularly your first two ideas, without seeing the code and other details.  Just that sometimes otherwise simple code has bugs in it.  In an ATMega328P project, 40 bytes is not a lot of free space at all.  To give you an idea what sort of problem this can trigger: The Arduino implementation of `new` that's in the 1.8.3 core will happily blow away your register file and whatever else it can get to after that, if the underlying `malloc` reports not enough memory.  Basically `new` continues to initialize the object it thinks was allocated even when the pointed returned is nullptr.  The `__malloc_margin` is 128 in the 1.8.3.  So if you try to `malloc` with 40 bytes distance between the stack and heap, you will trash your program state, perhaps even setting a data direction register in the process.


message:
How to read incoming HEX values from Serial.read() method?

***Brief description about the problem History***

Communicating with a old VersaStat II used GPIB port but the GPIB ports PCI card stopped working but there was a another port ```25 pin rs232 Serial communication port``` but even now, too bad computers are abending the Serial port luckily there is still ```virtual Blutooth COM port``` which can be used with a modern laptop so ***ESP32*** microcontroller was selected to communicate with this device wirelessly (might later go for HC05 module etc.).

***Fixing the voltage difference problem***

Now there is a big problem the esp32 Serial uses ```+3.3 V``` or logic ```1``` &  ```0 V``` for logic ```0``` But in the rs232 port logic ```0``` is ``` +3 V ~ +12 V ``` and logic ```1``` is ```-3 V ~ -12 V ``` also ```± 3V ``` undefined region. To overcome this problem I have used the following circuit with ***optocouplers***.

Here is the circuit diagram

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

The following code was used to communicate with the device easy as seems

Code

```
#include "BluetoothSerial.h"

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;
int speedsend = 9600;

void setup() {
  Serial.begin(speedsend);
  Serial2.begin(speedsend);
  SerialBT.begin("ESP32SERIAL");
  delay(500);
}

void loop() {

  if (Serial2.available()) {
//incoming data from the device
    int i = Serial2.read();
    SerialBT.write(i);
    Serial.println(i); // To check what is coming as output
  }
  if (SerialBT.available()) {
    Serial2.write(SerialBT.read());
  }

}

```

But I see no meaningful characters in putty (Bluetooth COM port) in Arduino Serial I see some numbers in HEX representation. Is this the way old devices communicate?

This link show how HEX numbers correlate with ASCII characters

https://www.rapidtables.com/convert/number/hex-to-ascii.html

How to fix this issue am I doing something wrong in here the circuit parameters etc.

***Communication Example with device***

For a start the ```ID``` command should give a number as 2532 according to book after the conversion it gives me 32 32 34 32 0 0 , 2242 looking at the Arduino Serial numbers with the help of the converting web site shown in above url. That's how I noticed It gives me HEX numbers.

Here is the PDF rs232c Interface section PDF the original Book came with ID command page too.

https://drive.google.com/file/d/1BHhIsloF4voMxoFeSlz1GsjwfgHwgsPJ/view?usp=sharing

Another book looks same but not from the book came with

https://drive.google.com/file/d/1z0NUOe17SpVYTIBfEE8s0EKStfLKKv_-/view?usp=sharing

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

body:
Your problem is, that you try to provide a HEX value, but you are actually providing a decimal value.

When you just write a whole number like `32`, it will be interpreted by the compiler as a decimal number. The decimal number `32` is equal to HEX `20`, which is a space character in ASCII.

**Solution:** Write your number as decimal value like this:

    int i = 0x32;

The `0x` preceding the value will mark it as a hexadecimal representation.


body:
Firstly you don't need that really complex optocoupler circuit. You just need a run-of-the-mill MAX3232 chip (note the extra 3 in there: it's the 3.3V version), that's what they're designed for: RS232 to 3.3V logic level conversion. You can pick up breakout modules for pennies on your favourite marketplace (ali-express, ebay, etc).

As for your reading, your assumption that your numbers are hexadecimal is completely wrong. They're decimal, not hexadecimal.

You read the data from the remote device and store each byte in an integer variable. Then you print that integer variable using `Serial.println()`. That will always give you a decimal representation of the numeric integer variable.

Your response of `32 32 34 32 0 0 , 2242` to my trained eye looks like bad communication. Maybe caused by your optocoupler circuit (change that for a MAX3232 immediately), or maybe caused by a mismatch in your baud rate, bit count, or parity settings.


message:
Switching time of a multiple input switch

I basically have two switches
Both switches will be pressed simultaneously in different order
I want to know which switch was pressed first

body:
1. The simple version: check continuously for the state of the digital inputs the switches are connected to. When one is `HIGH` that is the switched pressed first.
2. The intermediate version: check the 'blink without delay' example to make sure you don't get too many false positives.
3. The advanced version: use interrupts when one of the two switches gets 'HIGH', using the 'blink without delay' to prevent false positives.

If you want to know if both are pressed at the same time, but one is pressed first, use variables to keep track on it.

like two variables:

    bool button1Pressed = false;
    bool button2Pressed = false;

Set them accordingly (depending on which of the 3 possibilities you use). Then when you know a button is changed, you can easily check the booleans to know which was already pressed.

Or you can use an enum that combines the state of both:

    enum EState { ALL_OFF, BUTTON_1_PRESSED, BUTTON_2_PRESSED, BOTH_BUTTONS_PRESSED };

    EState buttonState;


body:
Use External Interrupts is the short answer.

Longer version:

You probably want to make a buzzer system like what in family feud game show.
I assume you are using Arduino UNO/MEGA and or having experience with programming.

1/ Use INT0 and INT1 for button 1 and button 2.

When an interrupt is raised, the mcu jumps to a specific address to run the interrupt service routine. INT0 and INT1 vectors are pointing to two distinctive addresses to run 2 different functions. For this, mcu takes the least amount of CPU clock to capture which button press first.

2/ Use PCINT vectors which is PinChange Interrupt. But personally I prefer to call it PortChange Interrupt.

There are 3 PinChange interrupt vectors PCINT0, PCINT1, PCINT2 to run 3 distinctive service routines. But this kind of interrupt doesn't know which pin is changed.

So inside the interrupt service routine, you have to check for that specific pin. You can do this the arduino way `digitalRead(button1)` or capture the whole port register, ie. PORTB, PORTC or PORTD.

In a nutshell, PORTB holds values of digital pin 8 to 13 while port D hold values of digital pin 0 to 7 and PORC for A0 to A7.

You can shave off some CPU clocks (3-10 clocks probably) by put 2 buttons different PCINT vectors. So that each button still triggers distinctive function.

In 3 cpu clocks (or around 180 ns) a lot of things may change and you may not get the correct result.

3/ Polling in main loop()
This is the worst way to do it. Nevertheless, it still gives good result.

    if (digitalRead(button1)==LOW) {
    // do something
    }

    if (digitalRead(button2)==LOW) {
    // do something else
    }


message:
Portenta pinouts for ADC

I wanted to have your comments about one of my questions.

I am currently working on the sketch for the Arduino Portenta H7. However, due to my poor electrical background, I would like to ask your opinion about the pinouts.   Below you can find the pinout diagram from the document page 1 available at the below link.

https://content.arduino.cc/assets/Pinout-PortentaH7_latest.pdf

I am a bit confused about the analog pins. As the diagram and color-coding show ADC A0 ( available on the high-density connector)  and analog pin A0 both separately.   What can be the difference between them ? or maybe I am interpreting wrong.

Because, on an ordinary Arduino board ( as far as I found), we have the Analog pins which are used for the ADC too. However, here in the Portenta pinout diagram, we have ADC A0 and analog A0 separate?

I thank you for your time and opinion[![pinouts of portenta h7][1]][1].

[![High density connectors at bottom of portenta][2]][2]

  [1]: https://i.stack.imgur.com/TyBLq.png
  [2]: https://i.stack.imgur.com/0GGnQ.png

body: It is just the one pin that they marked two times as `A0`. I think they just wanted to make clear it's the same pin, maybe that people don't get confused, but in my opinion it's just more confusing.


body:
The "high density" connectors expose every pin of the MCU. The pins around the edge of the board duplicate just the immediately useful ones.

Every pin that is on the edge of the board is also on the high density connectors somewhere.

Why have the pin on both connectors? Simple: if you want to use it in a breadboard or with jumper wires then you want the useful pins on the edge. If you want to use a plug-in board then you don't want to have to connect to both the high density connectors *and* the breadboard connectors, that would just be really awkward (since both have completely different height profiles). So everything is on the high density connectors for plug-in boards, and the useful ones are also on the breadboard headers.

A0 is the Arduino name for the pin. ADC is the function of the pin. The A of ADC stands for Analog. It's a pin that Converts Analog to Digital. It's an Analog to Digital Conversion pin - ADC.


message:
I have a problem trying to limit motor speed to a certain RPM using a MOSFET trigger switch module

[![My Arduino motor speed controller setup][1]][1]

I am using the potentiometer to control the duty cycle of a PWM signal to the MOSFET trigger switch module, thus controlling the motor speed.

In my code, I have used the map function to utilize the full resolution of my potentiometer (0 - 1023) and thus create a proportional PWM signal using analogWrite function (0 - 255).

However, in my setup I want to limit the speed of the motor from going beyond a MAX_RPM value, despite any further increase in analog value input from the potentiometer.

This means I have to continously check the RPM value (the RPM code works fine, so I will not include it).

If the motor speed hits the MAX_RPM value, any further potentiometer input should be ignored. To achieve this, I figured I need to hold the analogWrite function value constant thus holding the speed constant.

In the event that I turn the potentiometer in the reverse direction, this should decrease the PWM value thus also decreasing the speed.

I have written the code to achieve the process described above to no avail i.e., increasing potentiometer input causes the speed to go beyond the MAX_RPM value which is undesired.

In this project, I am developing a **rev limiter** of sorts.

Please help me figure out the problem in my code.

```
#define MAX_RPM 500
 #define MAX_RPM_PWM_MAPPED_VALUE 15

 //In this case, I first ran the motor while monitoring the speed and the potentiometer value
 //While doing this, I noted the potentiometer value at which the MAX_RPM is obtained
 //I then defined this potentiometer value as MAX_RPM_PWM_MAPPED_VALUE
 //With MAX_RPM_PWM_MAPPED_VALUE, I would directly limit the value written to the analogWrite function
 //

 MOSFETMODULE = 4;
 potentiometer = AO;

 void setup()
 {
  pinMode(MOSFETMODULE, OUTPUT);
 }

 void loop()
 {
  val = analogRead(potentiometer);  //Read potentiometer value - represents accelerator input
  mappedValue = map(val, 0, 1023, 0, 255); //Map the 10 bit value to 8 bit equivalent

  if(RPM >= MAX_RPM)
  {
   analogWrite(MOSFETMODULE, MAX_RPM_PWM_MAPPED_VALUE);
  }
   else
   {
     mappedValue = constrain(mappedValue, 0, MAX_RPM_PWM_MAPPED_VALUE);
     analogWrite(MOSFETMODULE, mappedValue); //Output a PWM signal to the MOSFET trigger module
   }
 }
```

  [1]: https://i.stack.imgur.com/LDEk1.jpg

body:
Your problem is that you don't know what ADC value maps to the maximum RPM. If you did you wouldn't need to know the RPM.

What you have here is a "feedback loop", and what you need is some method of using the detected RPM to control the speed of the motor.

You need to decouple the potentiometer from the analogWrite completely - the potentiometer should be setting the desired RPM, not the value being sent to set the RPM.

So if you want an RPM range from, say, 0 to 100RPM you can `map()` the `analogRead()` to the values 0-100. Then you can examine the actual RPM and adjust the value you send to the PWM accordingly - if the motor is too fast then slow it down. If it's too slow then speed it up.

There's a special method that is used for this: PID. And there's a library that does it for you too:

* https://playground.arduino.cc/Code/PIDLibrary/

The potentiometer provides the "set point", the RPM detection provides the "input", and the PID library gives you the "output" to feed to the `analogWrite()`.  You need to then provide the special magic "tuning" parameters to give the best control over your motor.


message:
ld.exe:linker_script.ld:138 cannot move location counter backwards | ArduinoFFT Error

Board: Arduino Nano 33 BLE Sense

I'm pulling PCM data from an onboard microphone and running it through the arduinoFFT library (version 1.5.6) to obtain a spectrogram. Since the arduinoFFT library requires the data be an array of doubles, I've converted the data from short to double, and started the FFT process. The FFT.Windowing() function worked fine, but I get the error at the FFT.Compute() function call (line 77). The error goes away when I remove the function call. The error:

    Found 25 compatible libraries
    Scanning dependencies...
    Dependency Graph
    |-- <arduinoFFT> 1.5.6
    |-- <PDM> 1.0
    Building in release mode
    Linking .pio\build\nano33ble\firmware.elf
    c:/users/benlu/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-
    eabi/8.2.1/../../../../arm-none-eabi/bin/ld.exe:linker_script.ld:138 cannot move location counter
    backwards (from 000000002004a470 t
    collect2.exe: error: ld returned 1 exit status
    *** [.pio\build\nano33ble\firmware.elf] Error 1

And the code:

    #include "Mic.h"
    #include <arduinoFFT.h>

    // FFT

    arduinoFFT FFT = arduinoFFT(); /* Create FFT object */
    /*
    These values can be changed in order to evaluate the functions
    */
    const uint16_t samples = 16128; //This value MUST ALWAYS be a power of 2
    const double signalFrequency = 16000;
    const double samplingFrequency = 16000;
    const uint8_t amplitude = 100;
    /*
    These are the input and output vectors
    Input vectors receive computed results from FFT
    */
    double vImag[samples] = {0};

    // buffer to read samples into, each sample is 16-bits
    short* sample_buffer;

    // number of samples read, read from Mic class on loop
    volatile int samples_read;

    // The length of the buffer to use. Currently set to 4 seconds.
    int buffer_size = 16000;
    double double_buffer[16384] = {};

    // Instantiate
    Mic mic;

    // DO NOT PRINT INSIDE THIS FUNCTION - Causes it to hang.
    void onPDMdata() {
      mic.sample();
    }

    void setup() {
      Serial.begin(115200);
      while (!Serial);
      PDM.onReceive(onPDMdata);
      PDM.setBufferSize(16128);

      Serial.println("3...");
      delay(1000);
      Serial.println("2...");
      delay(1000);
      Serial.println("1...");
      delay(1000);
      Serial.println("Listening!");

      mic.begin();
    }

    void loop() {

      // wait for samples to be read
      samples_read = mic.samples_read();

      // If desired buffer size is reached.
      if (samples_read >= buffer_size) {
        // Retrieves audio buffer
        sample_buffer = mic.sample_buffer();

          // print samples to the serial monitor or plotter
          for (int i = 0; i < samples_read; i++) {
            double_buffer[i] = (double)(sample_buffer[i]);
            Serial.println(double_buffer[i]);
          }

        Serial.println("---------- SAMPLE BREAK ----------");

        FFT.Windowing(double_buffer, samples, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
        FFT.Compute(double_buffer, vImag, samples, FFT_FORWARD); /* Compute FFT <--------------------- THIS LINE */
        // FFT.ComplexToMagnitude(double_buffer, vImag, samples); /* Compute magnitudes */

        // delay for data collection only, comment when not collecting
        delay(1000);
        Serial.println("Listening!");

        // clear the read count and resume recording
        mic.clear_buffer();
      }
    }

Where can I start to troubleshoot this issue? I've not had to deal with linker errors before, so any pointers would be greatly appreciated. Thanks in advanced!

body:
Short Version
-------------

The short answer is that you've exhausted RAM.

These two arrays alone:
```c++
const uint16_t samples = 16128;
double vImag[samples] = {0};
double double_buffer[16384] = {};
```

...are occupying (16128 + 16384) * 8 == 260096 bytes of memory.  There's only 262144 bytes of RAM in entirety.

The way the linker script is set up at least 1024 bytes are reserved for the stack, and there is no doubt at least another kByte in use somewhere.  In the Mbed OS and Arduino core files if nothing else.

As for why it fails only when you call `Compute`, that comes down to the compiler optimizer discovering that one (perhaps both) of your arrays are not actually used and so not entering into the mix when the linker is run.

Details
-------

In theory, you should have gotten a *somewhat* [nicer and easier to understand message from an `ASSERT`][1] in the [linker][2] script:

```None
ASSERT(. <= (ORIGIN(RAM) + LENGTH(RAM) - 1024), "heap region overflowed into stack");
```

So, you should have seen an error "heap region overflowed into stack" on your screen instead, which is maybe not the easiest thing for an Arduino user to decipher, but [heap][3] and [stack][4] are terms likely to be recognizable as memory-related sooner or later.

However, the linker executable shipped with the current version 1.3.2 of the [Arduino core][5] for [Mbed][6] ignores `ASSERT` statements completely; I have tested this (and tested my understanding of my test using an amd64 linker).  Presumably, there's a build option for the linker or a command-line or configuration file option that controls that, but I haven't found it yet.  In any case, it ignores a helpful `ASSERT` and instead proceeds to fail on [line 138][7] mentioned in the error message:

```None
 . = ORIGIN(RAM) + LENGTH(RAM) - 1024;
```

You can see it involves the same expression, just without a useful message if something goes wrong.  The ["location counter"][8] in the message is a linker related term that roughly means "where the next thing will be placed in memory" as it cobbles together your final executable from separately compiled chunks.  You've used so much RAM in your program that the location counter has been pushed past where the linker script wants to place the `__HeapLimit` symbol, 1K from the end of the MCU's RAM.  The location counter is supposed to increase monotonically.  So, evaluating this expression results in an erroneous attempt to "move location counter backwards".

  [1]: https://github.com/arduino/ArduinoCore-mbed/blob/1.3.2/variants/ARDUINO_NANO33BLE/linker_script.ld#L137
  [2]: https://en.wikipedia.org/wiki/Linker_(computing)
  [3]: https://en.wikipedia.org/wiki/Memory_management#HEAP
  [4]: https://en.wikipedia.org/wiki/Stack-based_memory_allocation
  [5]: https://github.com/arduino/ArduinoCore-mbed/
  [6]: https://en.wikipedia.org/wiki/Mbed
  [7]: https://github.com/arduino/ArduinoCore-mbed/blob/1.3.2/variants/ARDUINO_NANO33BLE/linker_script.ld#L138
  [8]: https://sourceware.org/binutils/docs/ld/Location-Counter.html


message:
Arduino with bmp280 sensor not entering void loop

I've been working on a project in which I need to know my altitude. For this purpose I've been using the BMP280 sensor. But I have an issue.

I've been trying to test if the sensor works with the program "bmp280_sensortest.ino", already included in the library. When I open the serial monitor the message "BMP280 Sensor event test" is displayed, indicating that there is a valid sensor on board. Below that the temperature, pressure and altitude data should be displayed, but nothing happens.

I've added a simple `Serial.print("hello")` at the start of `void loop()`, but not even that is displayed. The program doesn't seem to enter `void loop()` and I don't know why.

Here is the code:
```c++
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BMP280.h>

Adafruit_BMP280 bmp; // use I2C interface
Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();

void setup() {
  Serial.begin(9600);
  Serial.println(F("BMP280 Sensor event test"));

  if (!bmp.begin()) {
    Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
    while (1) delay(10);
  }

  /* Default settings from datasheet. */
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */

  bmp_temp->printSensorDetails();
}

void loop() {
  sensors_event_t temp_event, pressure_event;
  bmp_temp->getEvent(&temp_event);
  bmp_pressure->getEvent(&pressure_event);

  Serial.print("hello");
  Serial.print(F("Temperature = "));
  Serial.print(temp_event.temperature);
  Serial.println(" *C");

  Serial.print(F("Pressure = "));
  Serial.print(pressure_event.pressure);
  Serial.println(" hPa");

  Serial.println();
  delay(2000);
}
```
Any reply is greatly appreciated.
edit:

 if I remove
 ``` !bmp.begin() ```

from the if statement and replace it with a 1 it enters the void loop but it displays 0°C and 0pa

body:
It could be a faulty library/sensor, most likely the sensor, sometimes sensors can begin but then another connection could be faulty or the chip itself is faulty and so the Arduino might just be waiting forever for a response that will never come.

To see where it gets stuck, you can add Serial.println(F("1")); after bmp.setsampling then Serial.println(F("2"));  after bmp_temp->printSensorDetails to see where exactly it's getting stuck

One thing I also like to do is to buy two/three of a sensor, so that I can replace a sensor with another one. That way if a piece of code doesn't work for all three sensors then I can pretty sure it's a problem with the code and not the device. Not sure if you have a spare sensor to try that but I would recommend it in future


message:
How to close humidity sensor at specific humidity

[![enter image description here][1]][1]I am using dht humidity and temperature sensor on arduino and i would like to add relay and buzzer on the system. What I would like to do is to close it via buzzer and on 65% humidity run buzzer. The code i use is:

    /* DHT-22 sensor with 12c 16x2 LCD with Arduino uno
       Temperature and humidity sensor displayed in LCD
       based on: http://www.ardumotive.com/how-to-use-dht-22-sensor-en.html and
       https://www.ardumotive.com/i2clcden.html for the i2c LCD library by Michalis Vasilakis
       Recompile by adhitadhitadhit
       Notes: use LCD i2c Library from link above, i'm not sure why but new Liquidcristal library from Francisco Malpartida  isn't working for me
       other thing, check your */

    //Libraries
    #include <dht.h> // sensor library using lib from https://www.ardumotive.com/how-to-use-dht-22-sensor-en.html
    #include <LiquidCrystal_I2C.h> // LCD library using from  https://www.ardumotive.com/i2clcden.html for the i2c LCD library
    #include <Wire.h>
    dht DHT;

    //Constants
    #define DHT22_PIN 2     // DHT 22  (AM2302) - pin used for DHT22
    LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 after finding it from serial monitor (see comment above) for a 16 chars and 2 line display

    //Variables
    float hum;  //Stores humidity value
    float temp; //Stores temperature value

    void setup()
    {
        Serial.begin(9600);
        lcd.init();                      // initialize the lcd
      // Print a message to the LCD.
      lcd.backlight();
      lcd.setBacklight(HIGH);
    }

    void loop()
    {
        int chk = DHT.read22(DHT22_PIN);
        //Read data and store it to variables hum and temp
        hum = DHT.humidity;
        temp= DHT.temperature;
        //Print temp and humidity values to LCD
        lcd.setCursor(0,0);
        lcd.print("Humidity: ");
        lcd.print(hum);
        lcd.print("%");
        if (humidity <= 50)
    {
       digitalWrite(ledPin, HIGH);
       digitalWrite(buzzer, HIGH);

     }

     else

     {

     digitalWrite(ledPin, LOW); digitalWrite(buzzer, LOW);

        lcd.setCursor(0,1);
        lcd.print("Temp: ");
        lcd.print(temp);
        lcd.println("Celcius");
        delay(2000); //Delay 2 sec between temperature/humidity check.
    }

How to add relay and buzzer to close it with buzzer run on 65% humidity value?

  [1]: https://i.stack.imgur.com/0fjIV.jpg

body:
In this code:

    void loop()
    {
       sample temp and humidity;
       display temp;
       display humidity;

       if humidity <= 50
          LED on;
          buzzer on;
       else
          display temp
          wait 2 sec
       end

 - There is a missing '}' to to close the if/else.
 - Why do you display temp twice within the loop?
 - Where is the logic for the relay and the buzzer at 65%?
 - Pin numbers for the LED and the buzzer are undefined.
 - The LED and buzzer pins need to be set to OUTPUT mode in your setup() function.

If I understand your description, you probably need somethng like the following, in your loop function:

       if humidity <= 50
          LED on;
          buzzer on;
       else if hum >= 65%m
          close relay;
          buzzer on;
       end

When I have a problem with program logic that isn't obvious to me, I write it out in pseudo-code as I did above. Once I figure out the logic, then I'll type in C++ with proper syntax.
If I haven't understood your intentions in the above pseudo-code, I'd suggest you do the same thing, until you believe what you've written. Only then try to make it into working code.


message:
Driving 5V relay with ESP-01

I'm trying to drive a **5V relay** with **3.3V ESP-01** with schematic below. I programmed the ESP to start a portal through which I can derive the relay by triggering **GPIO-0** & **GPIO-2**. However when I power on the circuit I encounter the following scenarios:

 1. IF wire is plugged in to **GPIO-2**
   - **ESP blue led** turned on forever
   - **Relay** started buzzing sound forever
   - No WIFI network appears thus not working

 2. IF wire is plugged in to **GPIO-0**
   - No WIFI network appears thus not working

3. IF I only plug the wire after powering on the circuit then it works just fine as intended.

Would you please explain what is happening and how to fix it
[![enter image description here][1]][1]

    #include <ESP8266WiFi.h>
    #include <DNSServer.h>
    #include <ESP8266WebServer.h>

    const byte DNS_PORT = 53;
    IPAddress apIP(172, 217, 28, 1);
    DNSServer dnsServer;
    ESP8266WebServer webServer(80);

    //int ledPin = 2;
    #define ledPin0 0
    #define ledPin2 2

    int ledStatus0;
    int ledStatus2;

    void setup() {
    //  Serial.begin(9600);         // Start the Serial communication to send messages to the computer
    //  delay(10);
    //  Serial.println('\n');

      pinMode(ledPin0, OUTPUT);  ledStatus0 = digitalRead(ledPin0);  digitalWrite(ledPin0, HIGH); ledStatus0 = 1;
      pinMode(ledPin2, OUTPUT);  ledStatus2 = digitalRead(ledPin2);  digitalWrite(ledPin2, HIGH); ledStatus2 = 1;

      WiFi.mode(WIFI_AP);
      WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
      WiFi.softAP("Toggle Portal");

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

      // replay to all requests with same HTML
      webServer.onNotFound([]() {

        if (webServer.hasArg("led0")) {
          String status = webServer.arg("led0");
          if (status == "off") { digitalWrite(ledPin0, LOW); ledStatus0 = 1;  switchRelayOff(); }
          else if (status == "on") { digitalWrite(ledPin0, HIGH); ledStatus0 = 0; switchRelayOn(); }
        }
        if (webServer.hasArg("led2")) {
          String status = webServer.arg("led2");
          if (status == "off") { digitalWrite(ledPin2, LOW); ledStatus2 = 1;  switchRelayOff(); }
          else if (status == "on") { digitalWrite(ledPin2, HIGH); ledStatus2 = 0; switchRelayOn(); }
        }

        String content = "<!DOCTYPE HTML>";
        content += "";
        content += "";
        content += "  <title>ESP Web Server</title>";
        content += "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">";
        content += "  <link rel=\"icon\" href=\"data:,\">";
        content += "  ";
        content += "";
        content += "";
        content += "
ESP Web Server
";

        content += "
Output - GPIO 0
";
        if ( ledStatus0 == 0 ) {      content += "  <input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"0\" >";
        } else {      content += "  <input type=\"checkbox\" checked onchange=\"toggleCheckbox(this)\" id=\"0\" >";    }

        content += "
Output - GPIO 2
";
        if ( ledStatus2 == 0 ) {      content += "  <input type=\"checkbox\" onchange=\"toggleCheckbox2(this)\" id=\"2\" >";
        } else {      content += "  <input type=\"checkbox\" checked onchange=\"toggleCheckbox2(this)\" id=\"2\" >";    }

        content += "";
        content += "";
        content += "";
        webServer.send(200, "text/html", content);
      });
      webServer.begin();
    }

    void loop() {
      dnsServer.processNextRequest();
      webServer.handleClient();
    }

  [1]: https://i.stack.imgur.com/ZOoa4.jpg

body:
["Boot fails if pulled LOW"][1] - this applies to both GPIO 0 and 2. The 2N2222 pulls the GPIO down to one diode drop (0.7V) above GND, which actually is LOW. Instead of using a BJT, you need to control the relay module with a mosfet. Its high gate resistance will have negligible effect compared to the internal pullup resistor.

Chances are that the transistor on the relay module itself is a mosfet. If that's the case and if this mosfet works with 3.3V you can get rid of the 2N2222 at all. In general, using two transistors for this task does not make much sense, but in your case a BJT at the GPIO does not work.

You may notice that the onboard led is connected to GPIO 2, which is high at boot. So if you pull down GPIO 0 somehow, booting fails and GPIO 2 gets pulled HIGH ([ref][1]) - the onboard led will light up.

"*the question, how to use them?*" - once the ESP has booted into your sketch you should be fine to use the GPIOs like you would normaly do.

  [1]: https://randomnerdtutorials.com/esp8266-pinout-reference-gpios/


message:
Compiling Assembly Script in External EEPROM to Arduino Code

I'm working on a simple game console, and I'm planning to use a cartridge system using an EEPROM. I know that you can read and write data from an EEPROM, but can you compile the data into executable Arduino code, and vice versa? If the Arduino can do it, we can probably too, right?

Thanks in advance!

body: I would suggest you investigate a different micro with external addressing or one that loads its code from an external memory such as flash like the ESP32s do.


message:
converting an unsigned integer into a const char pointer

I know this is simple basic C stuff, but I can't quite figure it out or find a solution when searching and reading.

I have a method I want to call from a library that wants a const char pointer

```
someclass::send(const char *data)
```

And the value I want to send is actually an unsigned integer:

```
enum messageTypeEnum
{
  REGISTER_CLIENT = 0x04,
  CLIENT_REGISTERED,
  UPDATE_CREDENTIALS,
  ADD_BRICK,
  GAME_FRAME,
  ERROR
};

enum clientTypeEnum
{
  GAMEBOARD = 0x01,
  BRICK_CONTROLLER,
  PLAYER_CONTROLLER,
  TOUCH_CONTROLLER
};

uint16_t message = GAMEBOARD;
message <<= 8;
message += REGISTER_CLIENT;
```

So I want to convert it, but I can't quite figure it out.

I know fundamentally the char pointer is just a pointer to a memory address and that c strings are null terminated, so I should be able to create the pointer, add the enum's underlying bytes to the pointer array, and then add a 0 at the end to terminate it, but I don't know how I would do that exactly.

I tried doing it via casting:

```
const char *data = (char *)&message;
```

So here I'm saying (if I'm thinking about it correctly), is:
- `&message` take the memory address of `message`, our uint16
- `(char *) interpret it as a pointer for a character string
- `const char *` store that address in this const pointer

Even typing that out I feel like I'm misunderstanding parts.

This compiles, but it crashes my esp32 and I'm sure it's because I don't have a null terminator at the end, but I'm not sure how to add it (I tried to add it via array index but that failed).

What's the proper way of doing this (I'm sure there's a non-casting way that's probably easier)?

# Update

More detail re: PMF and Edgar's comments.

I definitely want to send the binary numbers behind the enums up. I'm building a websocket based interactive project where "controller" websocket clients can drive interactions on "gameboards". Websockets don't have a concept of differentiating between client types (I know socket.io does, but I'm wanting to write it all with regular websockets), so I built a registration system into the server that looks at the first two bytes of an array buffer or blob message to determine the client and message type (it seems overly complicated, but I'm building this to give a talk on binary operations and I'm doing it give functional examples of data parsing).

So yeah, all of that to say I definitely want to send the underlying number values from the enums.

The library I'm using is [ArduinoWebsockets](https://github.com/gilmaimon/ArduinoWebsockets) and they do have a client method called `sendBinary` that does have a signature like the `Serial.write`:

[![sendBinary signature][1]][1]

Though when I tried this with a non-null terminated c-string my esp32 crashed. That said, I was fumbling around in the code so it may have been something else that caused the crash.

When I follow the method calls down, the library ultimately uses `std::string` to pull the data out of the passed in c string and takes in the length (meaning it doesn't need to be null terminated(?)):

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

So maybe I can use the casting to turn my two byte number into a c string and pass in the length of 16?

  [1]: https://i.stack.imgur.com/DDJZp.png
  [2]: https://i.stack.imgur.com/rqE5Y.png

body:
# CORRECTED ANSWER

I dug back into my code after a comment from  Edgar and figured out some needed adjustments. My original solution was mostly correct, but there were some inaccuracies that I want to correct so I'm not goofing up anyone else in the future that may find this answer useful.

---

So I was overthinking things a bit. I still don't know that this is the best way of handling it, but it is working on the client side.

So, c-strings are just arrays of 8bit values with a null terminator at the end.

I want to end up my enum values, and my enums are define with byte enum-bases:

```
enum messageTypeEnum
{
  REGISTER_CLIENT = 0x04,
  CLIENT_REGISTERED,
  UPDATE_CREDENTIALS,
  ADD_BRICK,
  GAME_FRAME,
  ERROR
};

enum clientTypeEnum
{
  GAMEBOARD = 0x01,
  BRICK_CONTROLLER,
  PLAYER_CONTROLLER,
  TOUCH_CONTROLLER
};
```

So, to send up my bytes, I can just build a character array, set each byte in little endian order, and manually terminate it:

*NOTE: this is the original assembly that was incorrect.*
I put the null terminator at the beginning of the buffer thinking "oh, it's little endian so the terminator needs to be at the beginning". Classic sleepy brain mistake :|

<strike>
void registerAsAGameBoard()
{
  char buffer[3] = {0, GAMEBOARD, REGISTER_CLIENT};

  client.sendBinary((const char *)buffer, 3);
}
</strike>

```
void registerAsAGameBoard()
{
  char data[3] = {GAMEBOARD, REGISTER_CLIENT, 0};

  const char *buffer = data;
  size_t size = strlen(buffer);

  client.sendBinary(buffer, size);
}

```

Now when I call sendBinary with my byte array and the length of the buffer my esp32 doesn't crash (hurray!) and the server receives the buffer correctly!!

[![success!][1]][1]

I need to make a couple of adjustments on either the client and/or server side to account for the fact that the ESP32 is little endian and the server is already coded to receive payloads in big endian, but that shouldn't be too much of a lift.

  [1]: https://i.stack.imgur.com/W0yds.jpg


message:
Arduino Pico doesn't work with ST7735 screen

I am attempting to get the graphicstest example bundled with the Adafruit ST7735 library for the 0.96 inch LCD screen.

The example runs fine and serial communication is up and running. However, nothing outputs on the screen. I verified that the code works with other Arduino boards and that I have it properly wired -> SCK to SCL, MOSI to SDA, etc.

I'm not sure if I am doing something wrong, or if this is a limitation of the board.

Edit: I added the modified graphicstest code to the Internet, it can be found here: https://drive.google.com/file/d/1cFOgQXhhH1vou0KUrFzBDMp0iiIp1Yuy/view?usp=sharing

I also added a crude diagram of how the screen is wired up to the Pico. Note that the LCD is powered externally since the Pico cannot handle the current draw of powering the LCD.
https://drive.google.com/file/d/1RmZSHBcelwC9caLoQC9iE5Lb4eHG9S2O/view?usp=sharing

body:
I found out the problem. I was trying to connect to the SCK and MOSI pins on the back of the Pico. Later research shows that these are meant for programming and burning a bootloader onto the microprocessor.

The Adafruit library allowed me to define my own pins for SCK and MOSI.
Once I switched to using the `Adafruit_ST7735(int8_t cs, int8_t dc, int8_t mosi, int8_t sclk, int8_t rst)` constructor, it worked after that.


body:
From a comment on the question:

> I am going directly off of what's on their website.
> [mellbell.cc/products/pico][1] What they show on the link you provided is a
> prototype.

The "link you provided" refers to [this][2], which despite being described as for a "prototype", shows *correct* information with regard to the SPI related pins.

As it turns out **the documentation in the images you referenced at [mellbell.cc/products/pico][1] is incorrect**, both under the product shots and in the pin-outs section under "Documentation".  You can tell this by looking right at their image of their board and their diagram, and comparing that with the pinout of the ATMega32U4 itself:

[![Pico documentation compared with reality.][3]][3]

Interestingly, in the pinout on 8 of their [PDF][4] in the documentation section, they have it correct again and closer to the prototype:

[![From page 8 of PDF][5]][5]

Or at least it is with respect to the SPI signals.  The diode is in the wrong and orientation. In fact, the whole board seems to be left-right reversed.

Again, from the same comment:

> Additional research also shows that the SCK and MISO pins
> I'm connected to seem to be for programming only

It is true that these pins are used for ISP programming.  However, they also carry the data for the SPI bus peripheral when you're not doing ISP programming.  So they are "for programming" just not "only" for programming.  This is down to how the ATMega32U4 is, and not something tha the Pico makers have much control over.

This is also the case for UNO and basically all of the other popular AVR based Arduinos that can be programmed using the ISP method, as opposed to uPDI and others.  What *slightly* less common is to have these pins only available as unpopulated pads or only available on the ISP header.

I can see why you might want to not deal with those contacts because of the form factor of the Pico board.  However, because those pins are actually 32u4's SPI interface, and they should perform better than the bit-banging that Adafruit library would need to resort to in order to use other (non-SPI) pins.  So there is an incentive to use them.

So, your solution is a solution, but not for the reasons you think.  The pins you were previously trying to use will work when your efforts aren't being undermined by bad documentation, and you get them in the right order.

  [1]: https://mellbell.cc/products/pico
  [2]: https://create.arduino.cc/projecthub/mellbell-electronics/arduino-pico-the-world-s-smallest-arduino-board-24ee0e
  [3]: https://i.stack.imgur.com/PxKtY.jpg
  [4]: https://cdn.shopify.com/s/files/1/0005/5522/1039/files/PICO_V3.0_Documentation.docx.pdf?v=1603725878
  [5]: https://i.stack.imgur.com/Jk2R6.png


message:
Message parsing from MQTT server

I'm making a NodeMCU based home automation. I adapted code I found on internet for controlling a device (say LED) via MQTT broker hosted on a Raspberry Pi. It works fine. But when I try to scale it up for more than one device, I'm hitting a wall.

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

      const char* t_bedroom_light1 = "/home/bedroom/light1";

      Serial.print("Topic from MQTT broker is : ");
      Serial.print(topic);
      char p = payload[0];

      // if MQTT comes a 0 turn OFF pin D4
      if (topic == "/home/bedroom/light1" && p == '0')
      {
        digitalWrite(LIGHT_PIN, LOW);
        Serial.println(" Turn Light Off! ");
      }

      // if MQTT comes a 1, turn ON pin D4
      if (topic == "/home/bedroom/light1" && p == '1')
      {
        digitalWrite(LIGHT_PIN, HIGH);
        Serial.println(" Turn Light On! " );
      }
    }

Serial monitor receives and prints the topic correctly from MQTT server. But `topic == "/home/bedroom/light1"` never returns true. If I delete that part then `p =='0'` or `p=='1'` works fine by itself. I've tried comparing the topic with the locally declared char array, tried converting it into String and doing strcmp. Nothing. What am I doing wrong? Here is the Serial monitor output

    12:43:20.346 -> .......
    12:43:24.187 -> WiFi connected
    12:43:24.187 -> IP address:
    12:43:24.187 -> 192.168.1.5
    12:43:24.187 -> Attempting MQTT connection...connected
    12:43:30.752 -> Topic from MQTT broker is : /home/bedroom/light1

body:
That's not how you compare C strings.

When you write
```
if (topic == "/home/bedroom/light1")
```

you're comparing whether the character pointer `topic` is the same value as the address of the string `"/home/bedroom/light1"`, which of course it is not in this case.

To compare C strings, use the `strcmp()` function, which returns 0 if they're identical.
```
if (strcmp(topic, "/home/bedroom/light1") == 0 && p == '0')
```


message:
HobbyTronics UNO PRO Board Definition does not work in newer IDE versions

I have a HobbyTronics UNO PRO that replaces the UNO's 328P in DIP with an ATMega1284 on an adapter board:

[![HobbyTronics UNO PRO Board][1]][1]

I cannot link to the original page since it does not exist anymore.  But, it is [available through archive.org][2].

The original board definition, supplied by the distributor, stopped working after 1.8.10 and throws errors in 1.9.

The particular error when trying to compile:

    recipe.preproc.macros pattern is missing

It is not about a particular library or similar; I cannot compile at all (even an empty sketch).

**How can I migrate this board?** I'd really like to use a current version of the compiler & IDE.

  [1]: https://i.stack.imgur.com/fOsDr.png
  [2]: https://web.archive.org/web/20180227145214/https://www.hobbytronics.co.uk/arduino-uno-pro

body:
Making your board definition work
---------------------------------

What I did was slightly different from their directions, but:

Close any instances of the IDE you have running.

Create the directories along this path:
```none
<sketchbook>/hardware/uno_pro/avr/variants/uno_pro
```

Where `<sketchbook>` refers to to where your IDE is saving sketches by default.

Place the following slightly modified `boards.txt` at `<sketchbook>/hardware/uno_pro/avr/boards.txt`:

```properties
uno_pro.name=Arduino Uno*Pro

uno_pro.upload.tool=avrdude
uno_pro.upload.protocol=arduino
uno_pro.upload.maximum_size=130048
uno_pro.upload.maximum_data_size=16384
uno_pro.upload.speed=115200

uno_pro.bootloader.tool=avrdude
uno_pro.bootloader.low_fuses=0xFF
uno_pro.bootloader.high_fuses=0xDE
uno_pro.bootloader.extended_fuses=0xFD
uno_pro.bootloader.unlock_bits=0x3F
uno_pro.bootloader.lock_bits=0x0F
uno_pro.bootloader.file=optiboot/optiboot_atmega1284p.hex

uno_pro.build.mcu=atmega1284p
uno_pro.build.f_cpu=16000000L
uno_pro.build.board=AVR_UNO_PRO
uno_pro.build.core=arduino:arduino
uno_pro.build.variant=uno_pro
```

This is the original file with one important modification, and that's the addition of `arduino:` in the second to last line reading `uno_pro.build.core=arduino:arduino`

Place the following (unmodified from original) `pins_arduino.h` at `<sketchbook>/hardware/uno_pro/avr/variants/uno_pro/pins_arduino.h`:
```c
#ifndef Pins_Arduino_h
#define Pins_Arduino_h

#include <avr/pgmspace.h>

// ATMEL ATMEGA1284 on Hobbytronics UNO*Pro
//
//
// 2014-01-24 - Modified for Software Serial Library to work
//
//   ATMEGA1284 Pin  Arduino Mapping    Features
//    PA0                   D21  A7
//    PA1                   D20  A6
//    PA2                   D19  A5
//    PA3                   D18  A4
//    PA4                   D17  A3
//    PA5                   D16  A2
//    PA6                   D15  A1
//    PA7                   D14  A0
//
//    PB0                   D4
//    PB1                   D5
//    PB2                   D2
//    PB3                   D3               PWM
//    PB4                   D10     PWM  SS
//    PB5                   D11                   MOSI
//    PB6                   D12              PWM  MISO
//    PB7                   D13              PWM  SCK
//
//    PC0                   D22                   SCL
//    PC1                   D23                   SDA
//    PC2                   D24
//    PC3                   D25
//    PC4                   D26
//    PC5                   D27
//    PC6                   D28
//    PC7                   D29
//
//    PD0                   D0                    RX
//    PD1                   D1                    TX
//    PD2                   D6                    RX1
//    PD3                   D7                    TX1
//    PD4                   D30              PWM
//    PD5                   D8               PWM
//    PD6                   D9               PWM
//    PD7                   D31              PWM
//

static const uint8_t SS   = 10;
static const uint8_t MOSI = 11;
static const uint8_t MISO = 12;
static const uint8_t SCK  = 13;

static const uint8_t SDA = 23;
static const uint8_t SCL = 22;
static const uint8_t LED = 13;

static const uint8_t A0 = 0;
static const uint8_t A1 = 1;
static const uint8_t A2 = 2;
static const uint8_t A3 = 3;
static const uint8_t A4 = 4;
static const uint8_t A5 = 5;
static const uint8_t A6 = 6;
static const uint8_t A7 = 7;

#define NUM_DIGITAL_PINS            32
#define NUM_ANALOG_INPUTS           8

// Macros
#define analogInputToDigitalPin(p)  ((p < NUM_ANALOG_INPUTS) ? (p) + 14 : -1)
#define digitalPinToAnalogPin(p)    ((p) >= 14 && (p) <= 21 ? (p) - 14 : -1 )
#define analogPinToChannel(p)       ((p) < NUM_ANALOG_INPUTS ? NUM_ANALOG_INPUTS - (p) - 1: -1 )
#define digitalPinHasPWM(p)         ((p) == 3 || (p) == 8 || (p) == 9 || (p) == 10 || (p) == 12 || (p) == 13 || (p) == 30 || (p) == 31 )

#define ifpin(p,what,ifnot)     (((p) >= 0 && (p) < NUM_DIGITAL_PINS) ? (what) : (ifnot))

extern const uint8_t digital_pin_to_pcint[NUM_DIGITAL_PINS];

#define digitalPinToPCICR(p)    ifpin(p,(&PCICR),(uint8_t *)0)
#define digitalPinToPCICRbit(p) ifpin(p,(digital_pin_to_pcint[p] >> 3),0)
#define digitalPinToPCMSK(p)    (((p) <= 1) ? (&PCMSK3) : (((p) <= 5) ? (&PCMSK1) : (((p) <= 9) ? (&PCMSK3) : (((p) <= 13) ? (&PCMSK1) : (((p) <= 21) ? (&PCMSK0) : (((p) <= 29) ? (&PCMSK2) : (((p) <= 31) ? (&PCMSK3) : ((uint8_t *)0))))))))
#define digitalPinToPCMSKbit(p) ifpin(p,digital_pin_to_pcint[p] & 0x7,0)

#define digitalPinToInterrupt(p)  ((p) == 6 ? 0 : ((p) == 7 ? 1 : ((p) == 2 ? 2 : NOT_AN_INTERRUPT)))

#ifdef ARDUINO_MAIN

#define PA 1
#define PB 2
#define PC 3
#define PD 4

const uint8_t digital_pin_to_pcint[NUM_DIGITAL_PINS] =
{
  24, // D0  PD0
  25, // D1  PD1 1
  10, // D2  PB2
  11, // D3  PB3
  8,  // D4  PB0
  9,  // D5  PB1 5
  26, // D6  PD2
  27, // D7  PD3
  29, // D8  PD5
  30, // D9  PD6 9
  12, // D10 PB4
  13, // D11 PB5
  14, // D12 PB6
  15, // D13 PB7 13
  7,  // D14 PA7
  6,  // D15 PA6
  5,  // D16 PA5
  4,  // D17 PA4
  3,  // D18 PA3
  2,  // D19 PA2
  1,  // D20 PA1
  0,  // D21 PA0 21
  16, // D22 PC0
  17, // D23 PC1
  18, // D24 PC2
  19, // D25 PC3
  20, // D26 PC4
  21, // D27 PC5
  22, // D28 PC6
  23, // D29 PC7 29
  28, // D30 PD4
  31  // D31 PD7 31
};

// these arrays map port names (e.g. port B) to the
// appropriate addresses for various functions (e.g. reading
// and writing)
const uint16_t PROGMEM port_to_mode_PGM[] =
{
 NOT_A_PORT,
 (uint16_t) &DDRA,
 (uint16_t) &DDRB,
 (uint16_t) &DDRC,
 (uint16_t) &DDRD,
};

const uint16_t PROGMEM port_to_output_PGM[] =
{
 NOT_A_PORT,
 (uint16_t) &PORTA,
 (uint16_t) &PORTB,
 (uint16_t) &PORTC,
 (uint16_t) &PORTD,
};

const uint16_t PROGMEM port_to_input_PGM[] =
{
 NOT_A_PORT,
 (uint16_t) &PINA,
 (uint16_t) &PINB,
 (uint16_t) &PINC,
 (uint16_t) &PIND,
};

const uint8_t PROGMEM digital_pin_to_port_PGM[] =
{
  PD, // D0
  PD, // D1
  PB, // D2
  PB, // D3
  PB, // D4
  PB, // D5
  PD, // D6
  PD, // D7
  PD, // D8
  PD, // D9
  PB, // D10
  PB, // D11
  PB, // D12
  PB, // D13
  PA, // D14
  PA, // D15
  PA, // D16
  PA, // D17
  PA, // D18
  PA, // D19
  PA, // D20
  PA, // D21
  PC, // D22
  PC, // D23
  PC, // D24
  PC, // D25
  PC, // D26
  PC, // D27
  PC, // D28
  PC, // D29
  PD, // D30
  PD, // D31
};

const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] =
{
  _BV(0), // D0  PD0
  _BV(1), // D1  PD1
  _BV(2), // D2  PB2
  _BV(3), // D3  PB3
  _BV(0), // D4  PB0
  _BV(1), // D5  PB1
  _BV(2), // D6  PD2
  _BV(3), // D7  PD3
  _BV(5), // D8  PD5
  _BV(6), // D9  PD6
  _BV(4), // D10 PB4
  _BV(5), // D11 PB5
  _BV(6), // D12 PB6
  _BV(7), // D13 PB7
  _BV(7), // D14 PA7 (A0)
  _BV(6), // D15 PA6 (A1)
  _BV(5), // D16 PA5 (A2)
  _BV(4), // D17 PA4 (A3)
  _BV(3), // D18 PA3 (A4)
  _BV(2), // D19 PA2 (A5)
  _BV(1), // D20 PA1 (A6)
  _BV(0), // D21 PA0 (A7)
  _BV(0), // D22 PC0
  _BV(1), // D23 PC1
  _BV(2), // D24 PC2
  _BV(3), // D25 PC3
  _BV(4), // D26 PC4
  _BV(5), // D27 PC5
  _BV(6), // D28 PC6
  _BV(7), // D29 PC7
  _BV(4), // D30 PD4
  _BV(7), // D31 PD7
};

const uint8_t PROGMEM digital_pin_to_timer_PGM[] =
{
  NOT_ON_TIMER, // D0  PD0
  NOT_ON_TIMER, // D1  PD1
  NOT_ON_TIMER, // D3  PB2
  TIMER0A,      // D3  PB3
  NOT_ON_TIMER, // D4  PB0
  NOT_ON_TIMER, // D5  PB1
  NOT_ON_TIMER, // D6  PD2
  NOT_ON_TIMER, // D7  PD3
  TIMER1A,      // D8  PD5
  TIMER2B,      // D9  PD6
  TIMER0B,      // D10 PB4
  NOT_ON_TIMER, // D11 PB5
  TIMER3A,      // D12 PB6
  TIMER3B,      // D13 PB7
  NOT_ON_TIMER, // D14 PA0
  NOT_ON_TIMER, // D15 PA1
  NOT_ON_TIMER, // D16 PA2
  NOT_ON_TIMER, // D17 PA3
  NOT_ON_TIMER, // D18 PA4
  NOT_ON_TIMER, // D19 PA5
  NOT_ON_TIMER, // D20 PA6
  NOT_ON_TIMER, // D21 PA7
  NOT_ON_TIMER, // D22 PC0
  NOT_ON_TIMER, // D23 PC1
  NOT_ON_TIMER, // D24 PC2
  NOT_ON_TIMER, // D25 PC3
  NOT_ON_TIMER, // D26 PC4
  NOT_ON_TIMER, // D27 PC5
  NOT_ON_TIMER, // D28 PC6
  NOT_ON_TIMER, // D29 PC7
  TIMER1B,      // D30 PD4
  TIMER2A,      // D31 PD7
};

#endif // ARDUINO_MAIN

#endif // Pins_Arduino_h
// vim:ai:cin:sts=2 sw=2 ft=cpp
```

Open the IDE and your board should be listed.  It should compile with a blank sketch.  I did not test further than that.

MCUDude MightyCore
---------------------------------

Your board could also likely be made to work with [MCUdude MightyCore][1].  *However*, MightyCore will **not have your pin mapping**.  So, although you *could* use it, you would need to ignore the normal UNO pin labeling and instead of work out which pin number used by the chosen MightyCore variant routes to which pin on the UNO headers.  It would be annoying to do, but you could do that by comparing entries in your adapter's pins_arduino.h file with the entries in the chosen variant from the MightCore package.  But, the modifications above seem to work fine.  So, I don't necessarily suggest that route; I'm just saying it *could* be used that way also.

MightyCore could also be modified, but that works out to the same or more work than just using your board definition, I think.

  [1]: https://github.com/mcudude/MightyCore


message:
Having trouble with MPU6050 and AFE4404 printing together, potential conflict?

I am having trouble getting the two sensors to work together. There are a total of four sensors connected to the Arduino, and while the MPU and AFE individually work fine with the other two sensors, when the two are put together only the Serial Plotter for the AFE shows up while the MPU stays at zero. I initially assumed that there were address conflicts with the two, but their i2c addresses are different: the AFE at 0x58 and the MPU at 0x68 or 0x69. How can I resolve the issue so that I can get all four sensors' graphs printing?
Below is my Arduino code:
```
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

//int preValue = 0;
String str = "0, 0, 0, 0";
int mic = A0;
MPU6050 mpu;
int16_t ax, ay, az;

//PPG Stuff
#define NUM_REGISTERS       40
/* Pinbelegung */

int RESETZ = 4;
int CLK = 5;
int INT = 6;
//const int ocr1aval = 1; //||0 = 8MHz|| 1 = 4MHz|| 3 = 2MHZ ||7 = 1MHz||
const byte interruptPin = 2;

char LED2 = 0x2A; // LED2 on AFE4404

struct Register {
  uint8_t addr;
  uint32_t val;
};
/* Variablendeklaration */

//float befehl = 0;
bool Ready = 1;
int AFE_ADDR = 0x58;

unsigned long counter = 0;

/* AFE440X registers */

#define AFE_CONTROL0                0x00
#define AFE_LED2STC                 0x01
#define AFE_LED2ENDC                0x02
#define AFE_LED1LEDSTC              0x03
#define AFE_LED1LEDENDC             0x04
#define AFE_ALED2STC                0x05
#define AFE_ALED2ENDC               0x06
#define AFE_LED1STC                 0x07
#define AFE_LED1ENDC                0x08
#define AFE_LED2LEDSTC              0x09
#define AFE_LED2LEDENDC             0x0A
#define AFE_ALED1STC                0x0B
#define AFE_ALED1ENDC               0x0C
#define AFE_LED2CONVST              0x0D
#define AFE_LED2CONVEND             0x0E
#define AFE_ALED2CONVST             0x0F
#define AFE_ALED2CONVEND            0x10
#define AFE_LED1CONVST              0x11
#define AFE_LED1CONVEND             0x12
#define AFE_ALED1CONVST             0x13
#define AFE_ALED1CONVEND            0x14
#define AFE_ADCRSTSTCT0             0x15
#define AFE_ADCRSTENDCT0            0x16
#define AFE_ADCRSTSTCT1             0x17
#define AFE_ADCRSTENDCT1            0x18
#define AFE_ADCRSTSTCT2             0x19
#define AFE_ADCRSTENDCT2            0x1A
#define AFE_ADCRSTSTCT3             0x1B
#define AFE_ADCRSTENDCT3            0x1C
#define AFE_PRPCOUNT                0x1D
#define AFE_CONTROL1                0x1E
#define AFE_TIA_GAIN_SEP            0x20
#define AFE_TIA_GAIN                0x21
#define AFE_LEDCNTRL                0x22
#define AFE_CONTROL2                0x23
#define AFE_ALARM                   0x29
#define AFE_LED2VAL                 0x2A
#define AFE_ALED2VAL                0x2B
#define AFE_LED1VAL                 0x2C
#define AFE_ALED1VAL                0x2D
#define AFE_LED2_ALED2VAL           0x2E
#define AFE_LED1_ALED1VAL           0x2F
#define AFE_CONTROL3                0x31
#define AFE_PDNCYCLESTC             0x32
#define AFE_PDNCYCLEENDC            0x33
#define AFE_PROG_TG_STC             0x34
#define AFE_PROG_TG_ENDC            0x35
#define AFE_LED3LEDSTC              0x36
#define AFE_LED3LEDENDC             0x37
#define AFE_CLKDIV_PRF              0x39
#define AFE_OFFDAC                  0x3A
#define AFE_DEC                     0x3D
#define AFE_AVG_LED2_ALED2VAL       0x3F
#define AFE_AVG_LED1_ALED1VAL       0x40

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

  //ECG
  pinMode(10, INPUT); // Setup for leads off detection LO +
  pinMode(11, INPUT); // Setup for leads off detection LO -

  //PCG
  /*none needed*/

  //PPG
  pinMode(RESETZ, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(INT, INPUT);
  AFE_Init();

  //SCG
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
  #endif
  // initialize device
  mpu.initialize();
}

void PCG_Init()
{
  double micOut;
  const int sampleTime = 50;
  double preValue = 0;
}

void loop() {
  // put your main code here, to run repeatedly:
  String ECG = "0";
  //String SCG = "0";

  int PCG_val;
  String PCG;
  PCG_val = PCG_loop();
  PCG = String(PCG_val);

  int PPG_val;
  String PPG;
  PPG_val = PPG_loop() * -1;
  PPG = String(PPG_val);

//  int ECG_val;
//  String ECG;
//  ECG_val = ECG_loop();
//  ECG = String(ECG_val);

  int SCG_val;
  String SCG;
  SCG_val = SCG_loop();
  SCG = String(SCG_val);

  str = PCG + "," + PPG + "," + ECG + "," + SCG;
  Serial.println(str);
  delay(10);
}

//ECG Loop
int ECG_loop() {
  // put your main code here, to run repeatedly:
  if((digitalRead(10) == 1)||(digitalRead(11) == 1)){
  Serial.println('!');
  }
  else{
  // send the value of analog input 0:
  Serial.println(analogRead(A1));
  }
  //Wait for a bit to keep serial data from saturating
  delay(1);
  //delay (30);
}

//SCG Loop
int SCG_loop() {
    mpu.getAcceleration(&ax, &ay, &az);
    Serial.println(az/(pow(2,9)*1.0));
}

//PCG Loop
int PCG_loop() {
  //switch
  //case 1:
  int returnfill;
   double micOutput = findPTPAmp();
   returnfill = VUMeter(micOutput);
   return returnfill;
}

// Find the Peak-to-Peak Amplitude Function
double findPTPAmp(){
// Time variables to find the peak-to-peak amplitude
   unsigned long startTime= millis();  // Start of sample window
   /*unsigned int*/ double PTPAmp = 0;

// Signal variables to find the peak-to-peak amplitude
   /*unsigned int*/ double maxAmp = 0;
   /*unsigned int*/ double minAmp = 1023;

// Find the max and min of the mic output within the 50 ms timeframe
   while(millis() - startTime < sampleTime)
   {
      micOut = analogRead(mic);
      if( micOut < 1023) //prevent erroneous readings
      {
        if (micOut > maxAmp)
        {
          maxAmp = micOut; //save only the max reading
        }
        else if (micOut < minAmp)
        {
          minAmp = micOut; //save only the min reading
        }
      }
   }

  PTPAmp = maxAmp - minAmp; // (max amp) - (min amp) = peak-to-peak amplitude
  double micOut_Volts = (PTPAmp * 3.3) / 1024; // Convert ADC into voltage
  return PTPAmp;
}

// Volume Unit Meter function: map the PTP amplitude to a volume unit between 0 and 10.
int VUMeter(double micAmp){
  double fill = map(micAmp, 23, 750, 0, 10);
  while(fill != preValue)
  {
    preValue = fill;
  }
  return fill;
}

//PPG Loop
signed long val = 0;
void readADC()
{
  {
    val = AFE_Reg_Read(LED2);
    Ready = 1;
  }
}

int PPG_loop() {
  if (digitalRead(INT))
  {
    val = AFE_Reg_Read(LED2);
  }
  return val;
}

//More PPG Stuff
void AFE_Init()
{
  AFE_RESETZ_Init();
  AFE_Enable_HWPDN();
  AFE_Disable_HWPDN();
  AFE_Trigger_HWReset();
  Wire.begin();
  Wire.beginTransmission (AFE_ADDR);
  Serial.println("Initializing AFE4404...");
  if (Wire.endTransmission () == 0)
  {
    AFE_Enable_Write (); // enable to writting to registers
    AFE_Reg_Init();
    AFE_CLK_Init();
    AFE_Enable_Read ();  // enable to reading from registers
    Serial.println("Initialized Success!");
  }
  else
    Serial.println("Initialized Fail!");

}

/**********************************************************************************************************/
/*                              AFE4404_Registerinitialisierung                                           */
/**********************************************************************************************************/
void AFE_Reg_Init()
{
  //AFE_Reg_Write(34, 0x0033C3);
  AFEinitRegisters();
}

/**********************************************************************************************************/
/*                              AFE4404_Enable_Read                                                       */
/**********************************************************************************************************/
void AFE_Enable_Read ()         //Prohibit writing to registers
{
  byte configData[3];
  configData[0] = 0x00;
  configData[1] = 0x00;
  configData[2] = 0x01;// 0x01
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                              AFE4404_Disable_Read                                                      */
/**********************************************************************************************************/
void AFE_Enable_Write ()        //Permitt writing to registers
{
  byte configData[3];
  configData[0] = 0x00;
  configData[1] = 0x00;
  configData[2] = 0x00; //0x00
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                  RESETZ des AFE4404 wird Initialisiert                                                 */
/**********************************************************************************************************/
void AFE_RESETZ_Init()
{
  digitalWrite(RESETZ, HIGH);
  delayMicroseconds(30);
}

/**********************************************************************************************************/
/*                  Reset internal registers by setting RESETZ = LOW for 25 - 50 us                       */
/**********************************************************************************************************/
void AFE_Trigger_HWReset()
{
  digitalWrite(RESETZ, LOW);              //Sets Arduino pins 22-29 LOW
  delayMicroseconds(30); //30
  digitalWrite(RESETZ, HIGH);              //Sets Arduino pins 22-29 HIGH
  delay(10); // 10
}

/**********************************************************************************************************/
/*                             AFE4404 Power Down                                                         */
/**********************************************************************************************************/
void  AFE_Enable_HWPDN()
{
  digitalWrite(RESETZ, LOW);                  //Power Down by setting the RESETZ pin to LOW for more than 200 us
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Power Up                                                        */
/**********************************************************************************************************/
void  AFE_Disable_HWPDN()
{
  digitalWrite(RESETZ, HIGH);                  //Power Up the AFE by setting the RESETZ pin to HIGH
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Set Clock Mode to Internal                                      */
/**********************************************************************************************************/

void AFE_CLK_Init()
{
  AFE_Reg_Write(35, 0x104218);        //Set CLK Mode to internal clock (default Wert: 124218 mit interner CLK)
  AFE_Reg_Write(41, 0x2);             //Don´t set the internal clock to the CLK pin for outside usage
  AFE_Reg_Write(49, 0x000021);        //Division ratio for external clock mode set to fit the Arduino Mega 16MHz
  AFE_Reg_Write(57, 0);               //Set the lowes sampling rate to 61Hz (~17 ms)
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Write                                                   */
/*********************************************************************************************************/
void AFE_Reg_Write (int reg_address, unsigned long data)
{
  byte configData[3];
  configData[0] = (byte)(data >> 16);
  configData[1] = (byte)(((data & 0x00FFFF) >> 8));
  configData[2] = (byte)(((data & 0x0000FF)));
  I2C_write(AFE_ADDR, reg_address, configData, 3);
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Read                                                    */
/*********************************************************************************************************/
signed long AFE_Reg_Read(int reg_address)
{
  byte configData[3];
  signed long retVal;
  I2C_read (AFE_ADDR, reg_address, configData, 3);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  if (reg_address >= 0x2A && reg_address <= 0x2F)
  {
    if (retVal & 0x00200000)  // check if the ADC value is positive or negative
    {
      retVal &= 0x003FFFFF;   // convert it to a 22 bit value
      return (retVal ^ 0xFFC00000);
    }
  }
  return retVal;
}

/**********************************************************************************************************/
/*                              Write to AFE on I2C                                                       */
/**********************************************************************************************************/
char I2C_write (int slave_address, int reg_address, byte configData[], int byteCount)
{
  int trans_end = 0;
  signed long retVal;

  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Serial.print(configData[0]);
  Serial.print(",");
  Serial.print(configData[1]);
  Serial.print(",");
  Serial.println(configData[2]);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  Serial.println(retVal);
  Serial.println(reg_address);
  Wire.write(configData, 3);
  Serial.println("test");
  Wire.endTransmission();
  return (trans_end);

  /* while(1)
    {
     if(byteCount == 0)
     {
       Wire.endTransmission();
       Serial.println("test");
       return (trans_end);
     }else{
       //unsigned int reg_data = (unsigned int) *write_data++;
       Wire.write(configData, 3);
       byteCount--;
     }
    }*/
}

/**********************************************************************************************************/
/*                              Read Data of AFE on I2C                                                   */
/**********************************************************************************************************/
char I2C_read(int slave_address, int reg_address, byte *read_Data, int byteCount)
{
  int trans_end = 0;

  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Wire.endTransmission();
  Wire.requestFrom(slave_address, 3);
  while (Wire.available() && (byteCount != 0))
  {
    *read_Data++ = Wire.read();
    byteCount--;
  }
  return (trans_end);
}

void AFEinitRegisters(void) {

  unsigned char i;
  struct Register reg[NUM_REGISTERS];
  reg[0].addr = 0x01; reg[0].val = 0x000050;
  reg[1].addr = 0x02; reg[1].val = 0x00018F;
  reg[2].addr = 0x03; reg[2].val = 0x000320;
  reg[3].addr = 0x04; reg[3].val = 0x0004AF;
  reg[4].addr = 0x05; reg[4].val = 0x0001E0;
  reg[5].addr = 0x06; reg[5].val = 0x00031F;
  reg[6].addr = 0x07; reg[6].val = 0x000370;
  reg[7].addr = 0x08; reg[7].val = 0x0004AF;
  reg[8].addr = 0x09; reg[8].val = 0x000000;
  reg[9].addr = 0x0A; reg[9].val = 0x00018F;
  reg[10].addr = 0x0B; reg[10].val = 0x0004FF;
  reg[11].addr = 0x0C; reg[11].val = 0x00063E;
  reg[12].addr = 0x0D; reg[12].val = 0x000198;
  reg[13].addr = 0x0E; reg[13].val = 0x0005BB;
  reg[14].addr = 0x0F; reg[14].val = 0x0005C4;
  reg[15].addr = 0x10; reg[15].val = 0x0009E7;
  reg[16].addr = 0x11; reg[16].val = 0x0009F0;
  reg[17].addr = 0x12; reg[17].val = 0x000E13;
  reg[18].addr = 0x13; reg[18].val = 0x000E1C;
  reg[19].addr = 0x14; reg[19].val = 0x00123F;
  reg[20].addr = 0x15; reg[20].val = 0x000191;
  reg[21].addr = 0x16; reg[21].val = 0x000197;
  reg[22].addr = 0x17; reg[22].val = 0x0005BD;
  reg[23].addr = 0x18; reg[23].val = 0x0005C3;
  reg[24].addr = 0x19; reg[24].val = 0x0009E9;
  reg[25].addr = 0x1A; reg[25].val = 0x0009EF;
  reg[26].addr = 0x1B; reg[26].val = 0x000E15;
  reg[27].addr = 0x1C; reg[27].val = 0x000E1B;
  reg[28].addr = 0x1D; reg[28].val = 0x009C3F;
  reg[29].addr = 0x1E; reg[29].val = 0x000103;
  reg[30].addr = 0x20; reg[30].val = 0x008025; //0x008003
  reg[31].addr = 0x21; reg[31].val = 0x000125;//0x000003 //bit8: PROG_TG_EN
  reg[32].addr = 0x22; reg[32].val = 0x000100;//ILED2 = 32
  reg[33].addr = 0x23; reg[33].val = 0x000000;
  reg[34].addr = 0x32; reg[34].val = 0x00155F;
  reg[35].addr = 0x33; reg[35].val = 0x00991F;
  reg[36].addr = 0x36; reg[36].val = 0x000190;
  reg[37].addr = 0x37; reg[37].val = 0x00031F;
  reg[38].addr = 0x34; reg[38].val = 0x001563;
  reg[39].addr = 0x35; reg[39].val = 0x00991F;

  for (i = 0; i < NUM_REGISTERS; i++)
    AFE_Reg_Write(reg[i].addr, reg[i].val);

}
```
I am plotting each of the four sensors on LabView. Any help would be much appreciated!

body:
Troubleshooting I2C issues can be frustrating.  In order to figure out the problem, I recommend you construct the simplest possible Arduino sketch, using just the two sensors that seem to have a problem working together.  You should be able to write a very simple program that does nothing but acquire a simple value from each sensor, say 2 times/second.

Once you have the simplest possible program running, you should be able to figure it out.  Right now all your program complexity is making it harder than it needs to be.

Good luck!

Frank


message:
esp32s: error: 'WDT_TIMEOUT' was not declared in this scope

I am trying to initialize the watchdog timer.

I have installed

    arduino-esp32-master.zip

I have

    #include <esp_task_wdt.h>

set but it is not highlighted red indicating the IDE knows about it.

The error indicates that a major function is not present.

full error:

    Arduino: 1.8.13 (Linux), TD: 1.53, Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 115200, None"

    /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino: In function 'void setup()':
    esp32s-infrared-ac-wifi-server-v4:229:23: error: 'WDT_TIMEOUT' was not declared in this scope
         esp_task_wdt_init(WDT_TIMEOUT, true); //enable panic so ESP32 restarts
                           ^
    Multiple libraries were found for "IRremote.h"
     Used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/Arduino-IRremote-master
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote-2.8.1
    Multiple libraries were found for "WiFi.h"
     Used: /home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WiFi
     Not used: /home/brad/Downloads/arduino-1.8.13/libraries/WiFi
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT
    exit status 1
    'WDT_TIMEOUT' was not declared in this scope

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

What library did I fail to install to get the watchdog timer initialized?

UPDATE:

My additional boards URLs

    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,http://arduino.esp8266.com/stable/package_esp8266com_index.json

After following recommendations for poster, I got past that error and hit another one right away.

    Arduino: 1.8.13 (Linux), TD: 1.53, Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 115200, None"

    In file included from /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino:24:0:
    /home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WebServer/src/WebServer.h: In member function 'virtual size_t WebServer::_currentClientWrite_P(const char*, size_t)':
    /home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WebServer/src/WebServer.h:144:83: error: 'class WiFiClient' has no member named 'write_P'
       virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); }
                                                                                ^
    /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino: In function 'void setup()':
    esp32s-infrared-ac-wifi-server-v4:246:10: error: 'class WiFiClass' has no member named 'mode'
         WiFi.mode(WIFI_STA);
              ^
    esp32s-infrared-ac-wifi-server-v4:246:15: error: 'WIFI_STA' was not declared in this scope
         WiFi.mode(WIFI_STA);
                   ^
    esp32s-infrared-ac-wifi-server-v4:251:73: error: no matching function for call to 'WiFiClass::config(IPAddress&, IPAddress&, IPAddress&, IPAddress&, IPAddress&)'
         if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
                                                                             ^
    In file included from /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino:22:0:
    /home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT/src/WiFi.h:72:8: note: candidate: bool WiFiClass::config(IPAddress, IPAddress, IPAddress, IPAddress)
       bool config(IPAddress local_ip, IPAddress dns_server = INADDR_NONE, IPAddress gateway = INADDR_NONE, IPAddress subnet = INADDR_NONE);
            ^
    /home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT/src/WiFi.h:72:8: note:   candidate expects 4 arguments, 5 provided
    Multiple libraries were found for "IRremote.h"
     Used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote-2.8.1
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/Arduino-IRremote-master
    exit status 1
    'class WiFiClass' has no member named 'mode'

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

I have some library mixed up still

body: There is no such macro in the ESP32 core. That parameter is just the number of seconds before a timeout occurs. Just pick a reasonable value. 5 seconds seems to be a commonly used (and appears to be used in the core) value.


message:
MAX471 giving too high current readings

I want to measure current using the MAX471 sensor that outputs voltage proportional to the current (1V/A according to the [datasheet](https://datasheets.maximintegrated.com/en/ds/MAX471-MAX472.pdf)). To test the module, I connected a 330 ohm resistor to the sensor and powered it from 3.3V arduino. Using ohms law, I was expecting an output voltage of around 10 mV (for ~ 10 mA) in my circuit. However, I am getting an output of around 2.17 volts which seems wrong.

Does anyone see any mistake in my circuit or how I am trying to measure the current?

Here is my circuit:

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

My Code:

    #include <Arduino.h>

    void setup()
    {
      Serial.begin(115200);
    }

    void loop()
    {
      int adc_val = analogRead(A5);
      float vol = 3.2 / 4095 * adc_val; // using a 12 bit adc

      Serial.println(vol);
      delay(3000);
    }

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

body:
Do you have the same operating circuit that is shown on page 1 of the datasheet? do you have the 2K resistor they specifically from OUT to ground? Also, it may be worth adding the 1 uF capacitor they recommend from OUT to ground too

The other thing to consider is the actual voltage over the resistor. Check an see if the voltage over the resistor is 3.3 and that there isn't a voltage drop from the chip

If the voltage is fine, there may be a problem with the chip or the arduino


body:
I've got a few MAX471 modules and instead of current readings i get around 90% of input voltage on all of them.

With increasing load the output voltage decreases a bit and the MAX471 chip gets very hot (for example 12V 0mAh = 10V, 12V 200mAh = 9,6V).

I guess we are just "lucky" to get a bad batch or counterfeit chips...


message:
Stepper motor won't change directions!

I am driving a bipolar stepper motor with an a4988 driver using the AccelStepper library. My goal is to press a button and the motor moves CW, then another button for CCW.

I have looked at another post with a very similar issue, but the solution does not seem to apply well to the AccelStepper library, which I would really like to use given its versatility.

Currently, whichever button I press, the motor moves CCW. Any help would be greatly appreciated!

```c++
#include <AccelStepper.h>
AccelStepper stepperX(1, 3, 2);

void setup() {
  pinMode(8, INPUT)
  pinMode(9, INPUT);

  stepperX.setMaxSpeed(100.0);
  stepperX.setAcceleration(100.0);
}

int moveRight = 1000;              //arbitrarily high number
int moveLeft = -1000;              //arbitrarily low number

void loop() {
  while (digitalRead(8) == HIGH) { //when d8 button is pressed move left
    stepperX.moveTo(moveLeft);     //set move
    if (digitalRead(8) == LOW) {   //if not pressed, kill loop
      stepperX.stop();
      break;
    }
    stepperX.run();
  }

  while (digitalRead(9) == HIGH) { //when d9 button is pressed move right
    stepperX.moveTo(moveRight);    //set move
    if (digitalRead(9) == LOW) {   //if not pressed, kill loop
      stepperX.stop();
      break;
    }
    stepperX.run();
  }
}
```

body:
You work with accelleration and absolute positions. Are you aware of that?
This Library is not made for running permanently in the same direction. It let you define a position where the movement should end, an acceleration or speed and the controller moves the motor to that position.

The run method must be called permanently, It triggers the steps. So, I put it directly into the `loop()` method.

The following prog should hopefully move the motor towards position 1000 if you press the 8-button, towards position -1000 if you press the 9-button and stops if both buttons are off. I have not the hardware available at the moment, you it's just blind programming. Use it as an idea.

    #include <AccelStepper.h>
    AccelStepper stepperX(1, 3, 2);

    void setup()
    {
      pinMode(8, INPUT)
      pinMode(9, INPUT);

      stepperX.setMaxSpeed(100.0);
      stepperX.setAcceleration(3.0);
    }

    int positivePosition = 1000;
    int negativePosition = -1000;

    void loop()
    {
      if ( digitalRead(8) == HIGH )
      {
        stepperX.moveTo(positivePosition);
      }
      else if (digitalRead(9) == HIGH)
      {
        stepperX.moveTo(negativePosition);
      }
      else
      {
        stepperX.stop();
      }
      stepperX.run();
    }


message:
Convert a char array to Flash string

I would like to pass a formatted string to a method that accepts a __FlashStringHelper. Here is the method signature:

    void myMethod(const __FlashStringHelper *str);

I have been using snprintf to format my string:

    char cmd[30];
    snprintf(cmd, 30, "There are %d seconds in a minute", 60);
    myMethod(F(&cmd[0]));

Clearly the above doesn't work but how can I format a Flash String?

EDIT: I need to include an integer variable in my flash string. In the example above, '60' is a variable.

    uint8_t nSeconds = 60;
    char cmd[30];
    snprintf(cmd, 30, "There are %d seconds in a minute", nSeconds);
    myMethod(F(&cmd[0]));

body:
Direct answer
-------------

`F()` takes *immutable* string literals, that are known at *compile* time, and places them into flash ("PROGMEM") instead of RAM.  `snprintf()` creates strings at *runtime* and places them into a *mutable* array.  The two things are fundamentally incompatible.

Limited compile-time concatenation
----------------------------------

A *very limited* form of what you're trying to do could probably done like this:

```c++
#define MY_STRINGIZE(x) #x

myMethod(F("There are " MY_STRINGIZE(60) " seconds in a minute"));
```

This expands to:

```c++
myMethod(F("There are " "60" " seconds in a minute"));
```

Adjacent string literals are concatenated together, which makes this:

```c++
myMethod(F("There are 60 seconds in a minute"));
```

All that said, you could just write 60 in there directly.  And there's none of `snprintf`'s formatting capabilities possible here.

There is not a compile-time version of `snprintf` available in Arduino.  And I don't think the features of the C++ (or C) language are there to support the creation of one either.  Odds are there is a better way of achieving what you really want to do.

Working around this altogether
------------------------------

Often it's not necessary to concatenate strings at all, particularly if you're just to turn around and write them to a `Stream`, or more generally `Print` subclass, e.g. `Serial`, `LCD`, `SDFile`, `SoftwareSerial`, etc.  Concatenating things for you is a large part of what these do.  It is not necessarily to do it yourself in advance.

If you have a string literal and constant (or variable) and want to keep as much of it out of RAM as possible, using two separate `.print()`/`.println()` helps you do this:

```c++
printCapableThing.print(F("AT+CIPSTAT="));
printCapableThing.println(index);
```

* `F()` places `"AT+CIPSTAT="` into flash.
* If index is a constant it will also wind not being resident in RAM.

Side note
---------

I realize you're asking about, getting as much into flash as possible, but I also can't help but point out this same basic technique applies to this otherwise awful idea, for somewhat different reasons:
```c++
Serial.println(String(F("Key ")) + keyname + " : " + value);
```
This creates a horrific mess of allocations and deallocations and unnecessary copying, where if you just let the Stream/Print object do its job by calling `print()`/`println()` multiple times.  The result code is more reliable, smaller, and where not I/O-bound, faster when you do.