text:
How to make an Arduino act reliably as an SPI slave?
I want two Arduino Nanos to communicate with each other using SPI, ideally at around 2MHz or faster.
I have two standard Nanos running at 16MHz on 5V.

The master uses SPI.transfer() to send an array across the wire.¹ For ease of troubleshooting, the array alternately contains a bunch of zeroes or a bunch of 255s; but never both.

The slave simply returns decimal 66 for every byte. This was chosen because it's easy to spot on a logic trace.

The master checks the responses, and if there are any values that aren't 66, it prints the array to the UART.

Even at 125Kbit, which is the slowest available speed, I'm regularly getting corrupted bytes. Interestingly, most of the time (but not always!) the corrupted byte is either 0 or 255 - in other words, exactly the same as the byte sent from the master! This strikes me as a very unlikely coincidence.
I have inspected the traffic with a logic analyser, and it seems that the slave just occasionally decides not to operate as instructed; and instead it just sends the input straight out again. As in, the byte going out on MISO is exactly the same as the byte coming in on MOSI. But only sometimes.
What is happening here? Why doesn't it work? And what can I do about it?

Master sketch:
#define MOSI    12
#define SCK     13

#include <SPI.h>
#include "pins_arduino.h"
#include <avr/wdt.h>

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

    digitalWrite(SS, HIGH);
    pinMode(SS, OUTPUT);
    digitalWrite(SCK, HIGH);
    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);

    SPI.setClockDivider(SPI_CLOCK_DIV128);      // 125KHz
    SPI.begin();

    Serial.println("\n\nSTARTING...\n");
}

void do_transfer(byte attempt, byte payload) {

    // packet size of 200
    byte buffer[200];

    // initialise packet
    for (byte count = 0; count < sizeof(buffer); count++)
        buffer[count] = payload;

    // perform transfer
    digitalWrite(SS, LOW);
    SPI.transfer(buffer, sizeof(buffer));
    digitalWrite(SS, HIGH);    // SS is pin 10

    // tally results
    byte successes = 0, failures = 0;
    for (byte index = 0; index < sizeof(buffer); index++)
        if (buffer[index] == 66) successes++; else failures++;

    // print results
    Serial.print("Attempt ");
    Serial.print(attempt);
    Serial.print(" with payload ");
    Serial.print(payload);
    Serial.print(": ");
    if (failures == 0)
        Serial.print("SUCCESS");
    else {
        Serial.print(successes);
        Serial.print(" correct bytes, ");
        Serial.print(failures);
        Serial.print(" incorrect bytes");
        for (byte index = 0; index < sizeof(buffer); index++) {
            if (index % 10 == 0)
                Serial.print("\n\t");
            if (buffer[index] == 66)
                Serial.print("-");
            else
                Serial.print(buffer[index]);
            if (index < sizeof(buffer) - 1)
                Serial.print("\t");
        }
    }
    Serial.println();
    Serial.println();
}

void loop(void) {
    delay(800);                                                         // give the slave time to be ready

    for (byte attempt = 1; attempt <= 10; attempt+=2) {
        do_transfer(attempt, 0x00);
        do_transfer(attempt+1, 0xFF);
        wdt_reset();
    }
    while(true);                                                        // end of program
}

Slave sketch:
#include "pins_arduino.h"

void setup(void) {
    pinMode(MISO, OUTPUT);          // MISO needs to be an output
    SPCR |= _BV(SPE);               // enable SPI in slave mode
    SPCR |= _BV(SPIE);              // enable interrupts
    SPDR = 66;
}

ISR (SPI_STC_vect) { SPDR = 66; }   // just send 66 until the cows come home

void loop (void) { }

Connections: The following pins on both Arduinos are connected together:

SS (pin 10)
MISO (pin 11)
MOSI (pin 12)
SCK (pin 13)
GND

¹ The problem also happens if I send one byte at a time using SPI.transfer(), unless (maybe) if I insert a 1ms delay between each byte. Which of course is ridiculous.

What happens with smaller delays between the bytes (like microsecond range)? For me it sounds like in the error cases a new byte gets clocked by the master before the ISR can run on the slave (which replaces the last received byte with the new answer byte). This can happen, when another ISR is currently running. You could also try to disable the Timer0 interrupts in the slave sketch, since Timer0 is used for time keeping in the Arduino core. Functions like millis(), micros() and delay() won't work anymore then.

@chrisl your suggestion of disabling the timer worked. Mostly. But while it now works up to 250KHz, I get many many errors at 500KHz. Many of the MISO bytes are delayed by one bit.

I'm getting erroneous '33' bytes returned when I send the zeroes, and I'm getting erroneous '161' and '194' bytes returned when I send 255s. This seems very specific. Any ideas?

Honestly I doubt that you will get much faster. The bottleneck is clearly that you cannot write the buffer fast enough. The Nano is just too slow. Others on this site can surely give you a good estimate of the needed time for the interrupt by counting the needed cycles.

About the specific error values: I'm currently not sure if the SPI data register is a buffered one. If not it is pssible that your code writes that register and in the middle of that the SPI hardware already sends the half written data out. Not sure about that

The datasheet says "when the SPI is configured as Slave, the SPI is only guaranteed to work at fosc/4 or lower." So I don't think that's the issue. Also, according to the datasheet, the SPI register is "double buffered in the receive direction".

Your problem here is timing. I tried your setup, and found that I did indeed get occasional errors at 125 kHz. Disabling Timer 0 (as suggested by Chrisl) fixed that:
  power_timer0_disable();

But while it now works up to 250KHz, I get many many errors at 500KHz.

OK, the time between clock pulses is now 2 µs, however as I document here the time taken to execute an ISR like SPI_STC_vect is 2.625 µs, therefore it can't keep up with having to put the data there every 2 s.
You actually have slightly more time than 2 µs because the critical time is the time between the end of the first byte (which is when the ISR is called) and the time before the start of the second byte, which is when the master will start sampling your response.
See screenshot below with the critical time boxed in yellow.

That time is 2.45 µs and the ISR takes 2.625 µs. Now some of that is the ISR epilogue which won't really matter that much, but you can see that things are tight. It's hard to know exactly at what point the processor starts calling the ISR after the last bit arrives, and the length of the instruction it is currently executing could be an influencing factor.
I got your sketches to work running at 250 kHz with these amendments to the slave:
#include "pins_arduino.h"
#include <avr/power.h>
#include <avr/sleep.h>

void setup(void) {
  pinMode(MISO, OUTPUT);          // MISO needs to be an output
  SPCR |= _BV(SPE);               // enable SPI in slave mode
  SPCR |= _BV(SPIE);              // enable interrupts
  SPDR = 66;
  power_timer0_disable();
  set_sleep_mode (SLEEP_MODE_IDLE);
}

ISR (SPI_STC_vect) { SPDR = 66; }   // just send 66 until the cows come home

void loop (void)
 {
 sleep_mode ();
 }

The sleeping in idle mode makes sure that the processor is not half-way through an instruction when the interrupt is raised.
As expected (for the reasons above) it did not work at 500 kHz.
If you want to transfer data reliably you need to allow, in the master, for the time it takes the slave to do stuff. Every line of code in the slave means that the master has to wait for that to be executed.
I mention that in my page about SPI where I build in a delay in the master, if I want the slave to do calculations or something.

But the datasheet says that speeds of Fosc/4 are possible in slave mode, which would be 4MHz in this case. Would that be achievable if I removed the ISR and just used a busy loop?

Well, yes the datasheet has an example of doing a busy loop:
char SPI_SlaveReceive(void)
{
/* Wait for reception complete */
while(!(SPSR & (1<<SPIF)))
;
/* Return Data Register */
return SPDR;
}

Regardless of what they claim, what you intend has to be physically possible. So with Fosc/4, assuming a 16 MHz clock, you have 2 µs for a byte to arrive (250 ns * 8). So the hardware may well be able to receive one byte in that time, and you may just have enough clock cycles to notice it arriving and plonk it into memory somewhere (although things could be tight) but you won't have time to send a different response after each incoming byte, because you only have around 250 ns to do it in, and the loop that detects the interrupt will probably use up most or all of that.
After a bit of mucking around, I got it to work at 250 kHz where the objective was just for the slave to return some data (after all, I presume that is what the slave is supposed to do).
Master
#define MOSI    12
#define SCK     13

#include <SPI.h>
#include "pins_arduino.h"
#include <avr/wdt.h>

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

    digitalWrite(SS, HIGH);
    pinMode(SS, OUTPUT);
    digitalWrite(SS, HIGH);

    digitalWrite(SCK, HIGH);
    pinMode(SCK, OUTPUT);
    pinMode(MOSI, OUTPUT);

    SPI.begin();
    SPI.setClockDivider(SPI_CLOCK_DIV64);

    Serial.println("\n\nSTARTING...\n");

}

void do_transfer(byte attempt, byte payload) {

    // packet size of 200
    byte buffer[200];

    // perform transfer
    digitalWrite(SS, LOW);
    delay (1);    // give slave time to react
    SPI.transfer(buffer, sizeof(buffer));
    digitalWrite(SS, HIGH);    // SS is pin 10

    // tally results
    byte successes = 0, failures = 0;
    for (byte index = 0; index < sizeof(buffer); index++)
        if (buffer[index] == index) successes++; else failures++;

    // print results
    Serial.print("Attempt ");
    Serial.print(attempt);
    Serial.print(" with payload ");
    Serial.print(payload);
    Serial.print(": ");
    if (failures == 0)
        Serial.print("SUCCESS");
    else {
        Serial.print(successes);
        Serial.print(" correct bytes, ");
        Serial.print(failures);
        Serial.print(" incorrect bytes");
        for (byte index = 0; index < sizeof(buffer); index++) {
            if (index % 10 == 0)
                Serial.print("\n\t");
            if (buffer[index] == index)
                Serial.print("-");
            else
                Serial.print(buffer[index]);
            if (index < sizeof(buffer) - 1)
                Serial.print("\t");
        }
    }
    Serial.println();
    Serial.println();
}

void loop(void) {
    delay(800);                                                         // give the slave time to be ready

    for (byte attempt = 1; attempt <= 10; attempt+=2) {
        do_transfer(attempt, 0x00);
        do_transfer(attempt+1, 0xFF);
        wdt_reset();
    }
    while(true);                                                        // end of program
}

Slave
#include "pins_arduino.h"
#include <avr/power.h>
#include <avr/sleep.h>

const int TEST_SIZE = 200;

volatile byte my_data [TEST_SIZE];

volatile byte dummy;

ISR (PCINT0_vect)
 {
 // handle pin change interrupt for D8 to D13 here

  // ignore transition to HIGH
  if (digitalRead (SS) == HIGH)
    return;

  SPDR = 0;

  for (byte i = 0; i < TEST_SIZE; i++)
    {
    SPDR = my_data [i];
    while(!(SPSR & (1<<SPIF)))
      {
      // if SS went high, give up
      if (PINB & (1 << 2))
        return;
      }
    } // end of for loop

 }  // end of PCINT0_vect

void setup(void) {
  pinMode(MISO, OUTPUT);          // MISO needs to be an output
  SPCR |= _BV(SPE);               // enable SPI in slave mode
  power_timer0_disable();
  for (int i = 0; i < TEST_SIZE; i++)
    my_data [i] = i;

  // pin change interrupt for D10
  PCMSK0 |= bit (PCINT2);  // want pin 10
  PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE0);   // enable pin change interrupts for D8 to D13

  SPDR = 0;

  set_sleep_mode (SLEEP_MODE_IDLE);

}

void loop (void)
  {
  sleep_mode ();
  }

At the next clock divisor (SPI_CLOCK_DIV32) I started getting occasional errors. After all, Fclk/32 is only 2 µs per clock pulse and 16 µs per byte, and the necessary stuff in the inner loop must be taking that long — I didn't calculate the individual instruction times, you are welcome to do that. :)
I was hoping to get better performance than that, but then I realised that even with a tight sending loop in the slave, you can't afford to send before the master has acknowledged the previous byte (ie. that it has read it) so you still have the tight interval between the end of one byte and the start of the next, which is the time in which you have to prepare the next byte for sending.
It's not as bad if you are the master, because you control when the byte starts, so you can take as long as you want between bytes.

I see. But the datasheet says that speeds of Fosc/4 are possible in slave mode, which would be 4MHz in this case. Would that be achievable if I removed the ISR and just used a busy loop?

See expanded reply above.

Yes, this looks like the way to go. I made a few modifications to the code and increased the crystal to 20MHz, and managed to achieve 1.5Mbps - although admittedly without any actual processing taking place, not even storing the value. So probably 1Mbps will be achievable. Thanks for the help!

Honestly, I never thought of putting the busyloop inside an interrupt. It's a great idea.

My conclusion from Nick's excellent explanations, reading the specifications and based on my own experience (a two-slave system is running without problems since more than a year):
The hardware of an Arduino can reliably send and receive a single byte at 4MHz SPI clock, because dedicated hardware is used.
One can expect that SPI.transfer(bytes, size) can reliably send the bytes at full hardware speed, and even receive reliably the same amout of bytes. It is not specified what the maximum speed is in this case, what the maximum size is, and whether other interrupts are disabled. The library may even disable all and use polling to check for the end of a transfer. So a very long transfer may disturb your system upto failure.
Receiving a block of bytes requires that the slave can process the data at SPI byte speed. If hardware shift registers are used (e.g. in an SD card), you may send many bytes reliably at full speed.
But your Arduino slave has a hardware buffer of 8 Bits only, and the time when the interrupt routine is run is NOT when the last bit of a byte has been sent, but some time later. To predict this time reliably is not trivial. Determining it by experiment is not reliable per se.
Thus, when you want to use SPI block transfers, you need to slow down the SPI speed drastically to give the receiver time to process the data during the time of 8 bits.
You may still use full SPI speed, if you send single bytes (without returning SS) and wait the time required by the slave including any interrupt handling delays.
Or you restrict yourself to single byte transfers at full speed, and use a handshake protocol. This may be quicker than the simple block transfer on the sender's side. Unless you can put operation code and data into 8 bits, you have to maintain state information on both sides.
Conclusion: You may receive single bytes at full SPI speed. The function SPI.transfer(block, bytes) sends more than byte, but does not imply that any SPI slave can collect them. In particular, this function is not appropriate for sending data to an Arduino slave.


text:
ESP32 ADC <-> WiFi issue
I'm using the ESP32's ADC1 (not ADC2, which conflicts with WiFi functionality) to capture some analog data received at IO36 (an ADC1 port).
As soon as I uncomment the WiFi.mode(WIFI_AP_STA) line (even when the WiFi.begin() line is still commented out), analog readings go crazy!
Some side notes:

The hardware that processes the input signal to make it suitable for the ESP32 analog input uses the same power source as the ESP32 module.
A 100 μF SMD capacitor is connected to the source line of the ESP32 module just beside it to lessen the impact of its power consumption ripples on other devices.
I tried adc1_get_raw, which made no difference.
I tried this code on another ESP32 module; it also showed a huge difference in ADC1 readings before and after uncommenting WiFi.mode(WIFI_AP_STA).
Using root APIs such as esp_wifi_init & esp_wifi_set_mode & esp_wifi_start instead of Arduino wrappers like WiFi.mode didn't help.

New clue: Apparently the issue is with the WiFi Access Point mode (i.e. WIFI_AP), because setting Wi-Fi to Station mode (i.e. WIFI_STA) doesn't cause this issue.
In general anything related to WiFi causes the ADC to get unstable. No matter which ESP32 board you use, you could simply serial plot any ADC1 channel before and after the WiFi initialization command, even with floating ADC1 pins you can see the difference.

#include <WiFi.h>
float R = 0;

void setup() {
  Serial.begin(500000);
  // WiFi.mode(WIFI_AP_STA);
  // uncommenting this line analogread goes crazy, even while the following line is still commented out
  // WiFi.begin();
  analogSetAttenuation(ADC_0db);
}

void loop() {
  R = analogRead(36);
  Serial.println(R/12.21);
}

THANKS FOR ALL THOSE COMMENTS AND ELABORATIONS !!! I think I have found the answer HERE

I've just had the same problem. I just put all of the WIFI connecting code into a function, read the ADC2 data then called the function to send, ending with WIFI.mode(WIFI_OFF) to shut down the WIFI, read the data then started it all over again. I'm using ESPNOW so don't have to panic about hooking up to my network which would obviously take longer. With ESPNOW, the data is sent regardless and I have it sending every few seconds which is fine for me. I did try putting the connection code into loop, but it kept restarting the board. I've seen plenty of other stuff online about that. Putting it into a function seems to get around that.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Using 1 ms delay() in a for loop to check inputs.. Bad?
So first off, I know millis() exists. Just asking out of curiosity. Say you have a button you wanna check for during a delay.. Maybe a 10 second delay. So you make a for loop that checks for input and delays 1 ms... 10,000 times. What's bad about this?
 int pin = 13;
    bool button = false;

    void setup()
    {
      pinMode(pin, INPUT);
    }

    void loop()
    {

     while(button == false) {
     for(int i = 0; i<10000; i++) {
     if(digitalRead(pin,HIGH){
     button = true;
}
     delay(1);

    }
  }
}

Guess why loop() is called loop.
Your code becomes simpler, if you don't nest other waiting loops inside.
Simpler is Better.

You can do this, for quite simple sketches. It starts to become ugly if you add more features and conditions.
Therefore, the "correctTM" (read: professional) way is to implement a state machine. See in the IDE the non-delay blink example.
const unsigned long DELAY_MS = 1000;

int pin = 13;

enum State {
    WAITING, WORKING,
};

State state;

unsigned long startTime;

void setup()
{
    pinMode(pin, INPUT);
    state = WAITING;
    startTime = millis();
}

void loop()
{
    switch (state) {
    case WAITING:
        // You can put both conditions in one "if" with an "||" operator.
        // But it will look less clear.
        if (millis() - startTime > DELAY_MS) {
            state = WORKING;
        } else if (digitalRead(pin)) {
            state = WORKING;
        }
        break;
    case WORKING:
        // anything to do after the delay or the button
        break;
    default:
        // any error handling you see fit
        break;
    }
}

The function loop() is designed to be called endlessly in repetition. Use this to your advantage.

What's bad about this?

It looks a bit clunky but I suppose there is nothing particularly bad about it (apart from your typo of digitalWrite rather than digitalRead).
I would do it more like:
unsigned long now = millis ();
button = LOW;

while ((millis () - now < 10000) && (button == LOW))
  button = digitalRead (pin);

but then, if would work too in loop()

I know millis() exists

Ok, millis is always the best way...

Say you have a button you wanna check for during a delay..
So you make a for loop that checks for input and delays 1 ms... 10,000 times.

Your code is not really doing what you want. Your while loop never ends until button is pressed so 10s delay has no sense. I suppose your code should exit after 10 seconds or if button is pressed.

Just asking out of curiosity

You're code, without millis(), should be
bool button = false;
...
...
void loop() {
  uint16_t ms2wait = 10000;
  while (button == false && --ms2wait > 0) {
    if(digitalRead(pin,HIGH)
      button = true;
    delay(1);
  }
}

In my case I don't want the while loop to end until a button is pressed. I'm also trying to bring forth discussion on why millis() is better than delaying 1ms 10,000 times.

You should ask "Would my code do something else while it's waiting for an event?". If the answer is YES your code should use a millis() approach if it's NO you can use delay(). I said millis is the best way because YES is on 99,99% the right answer. In your example, 10 seconds is a huge amount of time and it's quite obvious your MCU should do something else in the meanwhile. In general checking if 10000ms are elapsed or freezing your MCU for 1ms 10000 times is quite the same.

I say quite because using1msx10000 you don't consider the time spent to run the code inside the for loop and this could increase the real delay after 10000 cycles.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
String to unsigned 16-bit integer
I'm currently working on a project with a 4DSystems Display. Im talking to the Display over SoftwareSerial with an ESP32. As soon as I want to use a Unicode character it requires me to convert my whole String to a uint16_t. Can somebody help me I have no idea how I should go on with this?
  #include <genieArduino.h>
  void loop() {
    uint16_t tn[] = { 0x2126,0 }; // Ω
    genie.WriteStrU(0, tn);
  }

This works but how could I inset a variable into the uint16_t?

Please provide the code that you have, error messages that you got and links to the used parts and libraries.

Which Arduino is this for?

I haven't seen that display library before, but probably it would be easier to only write the actual unicode characters via the unicode function and the rest with the normal write functions. Or is there a specific reason why you want to put another (probably numeric) variable inside that unicode string? From the documentation of the library it is unclear what encoding actually is used there. Maybe it would also work to just write the normal ASCII data in your unicode string, just casted to uint16_t (leaving the high byte empty).

As mentioned by chrisl in a comment, your best option is to to use the
regular WriteStr() method to print variables, and use WriteStrU() to
print Unicode string constants. For example:
float R = 12.34;  // dummy resistance value.
genie.WriteStr(0, "R = ");
genie.WriteStr(0, R);
genie.WriteStrU(0, (uint16_t *) u" Ω");

should print:
R = 12.34 Ω

Note the use of the u string prefix to write UTF-16-encoded strings in
the source code.

Edit: You wrote

the WriteStr always replaces the text inside a String object instead
of adding on.

This makes things more complicated. The only option I see is to format
the whole message as UTF-16 beforehand, then send it with WriteStrU().
Here is a class that does simple UTF-16 formatting. It inherits from the
Print class, meaning you can print() to it anything you could print
to Serial. In addition, it can print UTF-16 strings:
template <size_t max_length>
class UTF16Writer : public Print {
public:
    // Convert ASCII to UTF-16.
    size_t write(uint8_t c) {
        if (length >= max_length)
            return 0;  // buffer full
        buffer[length++] = c;
        buffer[length] = 0;  // terminate string
        return 1;
    }
    // Record UTF-16 data.
    size_t print(const char16_t *s) {
        size_t chars_written = 0;
        while (*s && length < max_length) {
            buffer[length++] = *s++;
            chars_written++;
        }
        buffer[length] = 0;  // terminate string
        return chars_written;
    }
    using Print::print;
    uint16_t buffer[max_length + 1];
private:
    size_t length = 0;
};

The template parameter is the capacity of the buffer. Once you have
written the whole message as UTF-16 using this class, you can pass its
buffer member to WriteStrU(). For example:
float R = 12.34;  // dummy resistance value.
UTF16Writer<16> writer;
writer.print("R = ");
writer.print(R);
writer.print(u" Ω");
genie.WriteStrU(0, writer.buffer);

Note: Do not forget the u prefix in the Unicode string, otherwise
the bytes of the string (UTF-8 in the source) would be interpreted as
latin1 by UTF16Writer::print(const char*). A message such as "martine écrit en UTF-8" would then be displayed as “martine Ã©crit en UTF-8”.


text:
Simulating a button press using the Serial Monitor to run a Servo
I'm kind of new to Arduino and C, and I was having trouble with this sketch. I'm working on a project to control 6 servos using virtual buttons. When I hold down the button, the servo moves forward smoothly to a certain fixed point, and when I release it, it comes back to a fixed point. I initially tested this with a single servo and an actual button on my breadboard using the following sketch.
#include<Servo.h>
int switch1;
float switch1Smoothed;
float switch1Prev;
Servo myservo1;
float a=1200.0; //lower angle limit

void setup() {

  Serial.begin(115200);
  pinMode(A1,INPUT_PULLUP);
  myservo1.attach(9);
  myservo1.writeMicroseconds(a);
  switch1Prev=a;
}

void loop() {
//Motor 1
  switch1 = digitalRead(A1);// read switch | will return 1 or 0 continuously
  //Serial.println(switch1);
  switch1 = switch1 * 2400;        // multiply by angle limit

  // *** smoothing ***

  switch1Smoothed = (switch1 * 0.05) + (switch1Prev * 0.95);
  if(switch1Smoothed>=a){
  switch1Prev = switch1Smoothed;
  }
  else{
    switch1Prev = a;
  }
  // *** end of smoothing ***

//  Serial.print(switch1);                  // print to serial terminal/plotter
//  Serial.print(" , ");
//  Serial.println(switch1Smoothed);
    myservo1.writeMicroseconds(switch1Smoothed) ;
    delay(10);                               // repeat loop 100 times per second
}

This works out just fine. Now, I'm working with NodeRed, a low code JavaScript flow creator, which is where my virtual button is, and I've set it up to send 0s or 1s as strings based on whether the button is pressed or not via serial communication. This is the config of the Serial Node on NodeRed:

And I wrote a short function on Arduino to parse the incoming string from the serial connection, convert it back to an integer, and then use that as my "button" input. However, it seems that either my logic is flawed, or my code is because my servo does not behave the same way it does with the physical button.
Here's the modified sketch:
#include <Servo.h>
int switch1;
float switch1Smoothed;
float switch1Prev;
Servo myservo1;
float a=1200.0;
String readString, mot1, mot2;

void setup() {
  Serial.begin(9600);
  myservo1.attach(9);
  myservo1.writeMicroseconds(a);
  switch1Prev=a;
}

void captureChar(int& n1){ //using reference to pass the value

  while (Serial.available()) {
    delay(3);  //delay to allow buffer to fill
    if (Serial.available() >0) {
      char c = Serial.read();  //gets one byte from serial buffer
      readString += c; //makes the string readString
    }
  }

  if (readString.length() >0) {

      mot1 = readString.substring(0,1);
      mot2 = readString.substring(1,2);
      n1 = mot1.toInt();
      //n2 = mot2.toInt();
    readString="";

  }
}

void loop(){
  captureChar(switch1);
  switch1 = switch1 * 2400;        // multiply by maximum angle limit

  // *** smoothing ***

  switch1Smoothed = (switch1 * 0.05) + (switch1Prev * 0.95);
  if(switch1Smoothed>=a){
  switch1Prev = switch1Smoothed;
  }
  else{
    switch1Prev = a;
  }
  // *** end of smoothing ***

//  Serial.print(switch1);                  // print to serial terminal/plotter
//  Serial.print(" , ");
//  Serial.println(switch1Smoothed);
  myservo1.writeMicroseconds(switch1Smoothed);
  delay(15);
}

When I load this sketch and hold down the virtual button, i.e., send a continuous stream of string "1", the motor simply goes back and forth really fast, rather than slowly moving to the set maximum position and stopping there while the button is held.

first thing, insert a layer of separation between the button press and the servo activation ... a button press sets a buttonPressed flag and releasing a button sets a buttonReleased flag ... no other action is done ... the servo motion part of the program moves the servo only in response to the two flags ... it does not respond to anything else ... when that works correctly  then add code that sets the flags in response to the data received from serial

I will try this and get back to you ASAP. If I'm being completely honest, I'm way out of my depth here, and I appreciate any feedback. It took me a week just to come up with what I have now.

There may be a problem with your smoothing logic, which is quite
convoluted. However, if the first code works fine, you can keep it
almost as-is, and only replace digitalRead() with a version that
reads the virtual button. It looks like that is what captureChar()
attempts to achieve. This function, however, has a couple of problems:

it has a loop and a delay, thus breaking the timing of the original
code
its interface is very different from the one of digitalRead(), and
thus cannot be used as a drop-in replacement.

Here is what I would propose as a digitalRead() replacement. It has
the same signature as the original digitalRead(), and can be used as a
drop-in replacement:
int virtual_switch_reading = LOW;

int virtualDigitalRead(uint8_t /* pin number ignored */) {
    int c = Serial.read();
    if (c == '0')
        virtual_switch_reading = LOW;
    else if (c == '1')
        virtual_switch_reading = HIGH;
    return virtual_switch_reading;
}

Note that calling Serial.available() is not useful: if no data is
available, Serial.read() returns -1, which is neither equal to '0'
nor equal to '1'.

Edit: addressing the requirement to have six virtual switches.
As stated in a comment, I suggest you encode the states of all the
switches, within NodeRed, as a single byte, with one bit per switch. You
would then send this byte to the Arduino, either periodically or
whenever any switch changes state.
On the Arduino, in order to simulate digitalRead() on a virtual
switch, you first have to map the pin numbers to the virtual switches:
// Map a pin number to a virtual switch.
const uint8_t virtual_switch_masks[NUM_DIGITAL_PINS] = {
    0,     // pin 0: not virtual
    0,     // pin 1: not virtual
    1<<0,  // pin 2: virtual switch 0
    1<<1,  // pin 3: virtual switch 1
    // etc...
};

Note that this table doesn't store switch numbers. It instead stores
bit masks. For example, virtual switch 1 is stored as 1<<1 =
0b00000010, i.e. all bits are clear except for bit number 1 (rightmost
being zero), which is set.
You can then simulate digitalRead() by extracting the relevant bit
from the byte you last received from NodeRed, which is done by a
bitwise and with the relevant mask:
// States of all virtual switches, one bit per switch.
uint8_t virtual_switch_states = 0;

int virtualDigitalRead(uint8_t pin) {
    uint8_t mask = virtual_switch_masks[pin];

    // If this is not a virtual switch, do a regular digitalRead().
    if (!mask)
        return digitalRead(pin);

    // For a virtual switch, extract the relevant bit
    // from virtual_switch_states.
    if (virtual_switch_states & mask)
        return HIGH;
    else
        return LOW;
}

In order to update the states of the virtual switches from the data
received, you just have to add this somewhere within loop():
if (Serial.available())
    virtual_switch_states = Serial.read();

This would work if I were using a single motor only though, right? I plan to use 6 motors, and I was considering sending a string of the form "000000" with each character representing the state of 1 of 6 motors (I would basically have 6 virtual switches on NodeRed)

Also, regarding the smoothing, I do agree it's not very refined, but it's the easiest bit of code I could come up with and felt that would be sufficient for the purposes of my project. However, I'm definitely open to suggestions or ideas on improving it, and more importantly, help with maybe improving the virtual button part.

@rayank97: A string like "000000" wouldn't work very well, as you cannot know where one string ends and the next one begins. You would have to add some sort of delimiter. It would be simpler to send a single byte, where the six switch positions are encoded as individual bits.

@rayank97: Regarding the smoothing: you can simplify it by removing switch1Prev and using switch1Smoothed instead. Also, if you set switch1 = 1200 + 1200*digitalRead(A1);, then switch1Smoothed will always be between 1200 and 2400: no need to explicitly clamp it.

Thanks for the idea for the smoothing. Regarding the virtual buttons, I just realized that even if I were to send a single byte as you suggested, wouldn't the issue of having 2 separate loops still have the effect of breaking the timing of my original code? Or am I mistaken? If I'm not, could you tell me if you think there's another way I could go about doing this?

@rayank97: There are no separate loops. virtualDigitalRead() would be O(1) even with six switches. See amended answer.


text:
Pan and tilt bracket move to sound, control servo motors using microphone sound sensors
I'm trying to code the pan and tilt bracket to turn based on where I speak, I know how to move the servo motors, but I really need help with the sound sensing. This is the code I've got currently:
#include <Servo.h>
Servo myservo;  // create servo object to control a servo
     Servo myservo2;           // a maximum of eight servo objects can be created
int sound1;
int sound2;
int pos = 0;    // variable to store the servo position

void setup()
{
  Serial.begin(9600);
  myservo.attach(5);  // attaches the servo on pin 9 to the servo object
  myservo2.attach(6);
}

void loop()
{
  sound1 = analogRead(A0);
  sound2 = digitalRead(7);

  if (sound1 > 50)
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }

   if (sound2 > 50)
   for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo2.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {
    myservo2.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

I've been working on this for some time, but for some reason, whenever I try to code the sound sensor, it always ends up being ignored, so for example, If my code says, if sound sensor number 1 detects sound, move 90 degrees vertically or horizontally, it always ignores that if statement and just continuously moves 90 degrees to wherever. I need it to follow my voice, or if that's too advanced, it's fine if it just follows any sound. So if I more 30 degree to the right on the pan and tilt bracket, and speak, I need it to turn and face me. Also, the kind of sound sensor I'm using is KY-037, the red variation with 4 pins. Any advice would be really helpful, thanks.

Why do you use digitalRead() for sound2? It will return only 0 or 1. So if(sound2 > 50) will never be true. Also currently your code tells the servo to move 180 degrees back and forth. Nothing with 90° or following you. What sound sensors do you have? I don't quite understand what you want to achieve. Do you want the servos to follow you linearily (so for example moving to 30° when you talk from 30°)? Or do you want it to change between 2 positions? What should happen if both sensors detect a loud enough sound?

What you are trying to achieve is not easy. Expect to spend a lot of time
developing, testing and tuning it.
The first step would be to work the acoustics of your device. The sound
sensors are not sensitive to the direction of the incoming sound, so you
will to have to use two of them facing different directions, like the
ears on your head face different sides. It would help to have the polar
plot of your microphones: if they are not directional enough, you may
have to build some kind of sound obstacle between them (the “head”
between the ears, or maybe even a pair of “auricles”) to improve the
angular selectivity. With cardioid microphones, you may get away with
just facing them 180° apart.
Getting this right can take significant effort. A two-channel
oscilloscope and a sinusoidal sound source would help a lot: watch the
signals coming out of both mikes, and see how their amplitudes change as
you turn the head. You want them to be sensitive enough to that
orientation. Then, adjust the potentiometers within the sound modules in
order to have the same amplitudes when the head is facing the sound
source.
Next you will have to sample these signals with your Arduino. The
default Arduino sampling rate (analogRead() in a tight loop) is about
8.93 kHz for a single channel, or 4.46 kHz per channel if
alternating between two channels. This may be enough for getting a rough
estimate of the intensity of voice, but it is kind of borderline too
low. You may want to increase the sampling rate: the way to do so has
been discussed here, and is only a search away.
With analogRead(), the sampling rate is also inconsistent and
dependent on what the sketch is doing: the more the CPU works, the
slower the sampling rate. I would strongly recommend letting the ADC
work in free running mode, and retrieve the samples from an interrupt
service routine. For this, you will have to first read and understand
the chapter on the ADC from the datasheet of the microcontroller.
Next, you have to estimate the intensities from the samples you read. In
principle, this means low-pass filtering the square of the AC part of
the signal. If that is too much work, you may get away with a simple
peak-detection.
You may want to take a look at this sound-meter sketch for
inspiration. It uses the free-running ADC technique and estimates a
sound amplitude using the proper “low-pass filtering the square of the
AC part of the signal”. It is single channel though, and you will have
to adapt it for tracking two channels. This would involve changing the
multiplexer setting within the ISR.
Lastly, you will have to make the pan servo respond to the difference in
intensities between the two ears. That is the easy part, it could
roughly go like this:
void loop() {
    float intensity_right = get_sound_intensity(RIGHT_MIKE);
    float intensity_left = get_sound_intensity(LEFT_MIKE);

    // Only move the head if we actually hear sound.
    if (intensity_right >= intensity_threshold
            || intensity_left >= intensity_threshold) {

        float difference = intensity_right - intensity_left;

        // Only move the head if the intensity difference is
        // significant.
        if (fabs(difference) >= difference_threshold) {
            if (difference > 0 && servo_position < 180) {
                servo_position += 1;
                servo.move(servo_position);
            } else if (difference < 0 && servo_position > 0) {
                servo_position -= 1;
                servo.move(servo_position);
            }
        }
    }
}

I'm trying to run this code, and "get_sound_intensity" has an error, it says it's not declared in this scope, how to define this?
Also, do you have a private email? I want to send you more details about what I'm doing. I need to finish this before 9th April, and I really need an experts help right now

@KevinZefi: Re “how to define [get_sound_intensity]”: most of my answer is about how to define it. Did you go through it? I would rather not give my private e-mail.

Ok, the thing with the oscilloscopes, I can't actually use them for the project, my project is a voice tracking camera system, the main objectives of this project is to code the servo motors and to track my voice AND my face, I managed to complete the face tracking. If what I asked for is too advanced then I can just get a simpler code, I need the code to have this kind of logic: If sound reaches sensor 1 first, turn 90 degrees, something like that. I need the project to be portable if that makes sense, I will need to present this to my professors, and I can't hook it up to an O scope.

The end result will be, to create one box which contains everything inside, so I can't have the project depend on hooking it up with oscilloscopes whenever I turn it on.
"I would rather not give my private e-mail" Ok, I'm sorry I asked, is there any other way I can send you details of my project?

Also, with the face tracking, I managed to code the servos spin based on where my face is, this was just a hunch, but can I just add the sound sensing variation on to that code?

@KevinZefi: The oscilloscope is only for the development phase, not to be kept as part of the project.

The human (and other animals) brain does far more than just look at different sound intensities to calculate angle and distance of a sound. It also compares the phase difference, something exploited by "3D sound" from stereo speakers / headphones. Incidentally it's hard to work out direction from a higher pitched and sweeping sound, which is why blackbirds use such a sound as an alarm call for airborne predators - other birds know what it means, but the hawk overhead can't work out where the call is coming from...


text:
WeMos D1 losing WiFi connection
I have a WeMos D1 connected to an air quality sensor and publishing the value on a self-hosted website.
Initially everything works fine (although router UI does not display WeMos). After an hour or two WiFi connection fails.
Other devices on the network are unaffected. Sensor data is still being polled, serial connection works fine, but the device doesn't respond to the ping and the website obviously doesn't work.
Here's the code:
#include <ESP8266WiFi.h>

#include "SerialCom.h"
#include "Types.h"

//WiFi setup:
const char* ssid = "mySSID";                    // Enter SSID here
const char* password = "myPASS";                // Enter Password here

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

WiFiServer  server(80);                         // Server on port 80
String header;

// sensor setup:

uint32_t statusPublishPreviousMillis = 0;
const uint16_t statusPublishInterval = 30000;   // 30 seconds = 30000 milliseconds

particleSensorState_t state;

unsigned long currentTime = millis();           // Current time
unsigned long previousTime = 0;                 // Previous time
const long timeoutTime = 2000;                  // Define timeout time in milliseconds (example: 2000ms = 2s)

float average;
int rounded;

void setup() {

    Serial.begin(115200);
    SerialCom::setup();
    WiFi.config(ip, gateway, subnet);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);                 // Connect to the WiFi router
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");                         // If connection successful show IP address in serial monitor
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());             // IP address assigned to your ESP

    server.begin();                             // Start server
    Serial.println("HTTP server started");
}

void loop() {

    SerialCom::handleUart(state);               // communicate with the sensor
    average = SerialCom::forward(state);        // read sensor value
    rounded = round(average);                   // round the value so that we don't have .00

    const uint32_t currentMillis = millis();
    if (currentMillis - statusPublishPreviousMillis >= statusPublishInterval) {
        statusPublishPreviousMillis = currentMillis;
    }

    WiFiClient client = server.available();
    if (client) {                               // If a new client connects,
        Serial.println("Client connected");     // print a message out in the serial port
        String currentLine = "";                // make a String to hold incoming data from the client
        currentTime = millis();
        previousTime = currentTime;

        while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
            currentTime = millis();
            if (client.available()) {           // if there's bytes to read from the client,
                char c = client.read();         // read a byte, then
//              Serial.write(c);                // print it out the serial monitor
                header += c;
                if (c == '\n') {                // if the byte is a newline character
                    // if the current line is blank, you got two newline characters in a row.
                    // that's the end of the client HTTP request, so send a response:
                    if (currentLine.length() == 0) {
                        // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
                        // and a content-type so the client knows what's coming, then a blank line:
                        client.println("HTTP/1.1 200 OK");
                        client.println("Content-type:text/html");
                        client.println("Connection: close");
                        client.println();

                        // Display the HTML web page
                        client.println("<!DOCTYPE html>");
                        client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
                        client.println("<meta charset='utf-8'>");

                        // Values in the website title
                        client.print("<title>");
                        client.print(rounded);
                        client.println(" μg/m³</title>");
                        client.println("");

                        // Web Page Heading
                        client.println("");
                        client.println(rounded);
                        client.println("");

                        client.println("");      // The HTTP response ends with another blank line
                        break;                   // Break out of the while loop
                    } else {                     // if you got a newline, then clear currentLine
                        currentLine = "";
                    }
                } else if (c != '\r') {          // if you got anything else but a carriage return character,
                    currentLine += c;            // add it to the end of the currentLine
                }
            }
        }

        header = "";                             // Clear the header variable
        client.stop();                           // Close the connection
    }
}

EDIT:
I've read somewhere that String implementation in ESP8266 library is problematic, so I replaced every String with char*. That increased the uptime to around 30 hrs.

Before the edit you said that you'd added a check for wifi disconnection which rebooted the ESP8266 and it didn't help. Did it find that wifi disconnected and reboot, or did it do nothing?

It did nothing. If nothing helps, I will test and see if it didn't detect the issue or detected it but the restart didn't help. But I would like to find the root cause and avoid restarting if possible.

Can you try a different unit? I had a similar problem a few years back. Changing the board helped a lot but finally I changed the router and the problem vanished.

I've ordered a second one, but it will take some time and would like to make it work without additional hardware.


text:
MAX30100 and ESP8266 NodeMCU Serial Errors
This is my final year project and for some reason, the max30100 sensor defaults to static values once the HTTP post request has been performed.
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include <SimpleTimer.h>

#define REPORTING_PERIOD_MS 1000

const char* ssid = "SDsouza";
const char* password = "dsouza@8104045917";
const char* serverName = "http://10.0.0.13/post-sensor-data.php";

String systolic_pressure;
String diastolic_pressure;
String pulse_rate;
String temperature_body;
String BPM;
String SpO2;

PulseOximeter pox;
uint32_t tsLastReport = 0;

SimpleTimer timer;

String sensor_data;
bool Sr;
String machineid = "MR1";
String room_number= "A1";
String bed_number= "1";

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(16,OUTPUT);
  WiFi.begin(ssid , password);
  Serial.print("Connecting to SSID:");
  Serial.print(ssid);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("Connected Successfully!!");
  Serial.println(WiFi.localIP());

  if(!pox.begin())
  {
    Serial.println("Failed");
    for(;;);
  }
  else
  {
    Serial.println("Pox Success");
  }
  pox.setOnBeatDetectedCallback(onBeatDetected);
  //pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
  timer.setInterval(1000L , getsendata);
}

void loop() {
  // put your main code here, to run repeatedly:
  pox.update();
  if(millis() - tsLastReport > REPORTING_PERIOD_MS)
  {
    BPM = pox.getHeartRate();
    SpO2 = pox.getSpO2();
    Serial.print("Bpm: ");
    Serial.println(BPM);
    Serial.print("SpO2: ");
    Serial.println(SpO2);
    tsLastReport = millis();
  }
  timer.run();
}

void onBeatDetected()
{
  Serial.println("Beat Detected");
}

void getsendata()
{
  while (Serial.available())
  {
    sensor_data = Serial.readString();
    Sr = true;

    int firstcommaindex = sensor_data.indexOf(",");
    int secondcommaindex = sensor_data.indexOf(",", firstcommaindex + 1);
    int thirdcommaindex = sensor_data.indexOf(",", secondcommaindex + 1);
    int fourthcommaindex = sensor_data.indexOf(",", thirdcommaindex + 1);

    systolic_pressure = sensor_data.substring(0, firstcommaindex);
    diastolic_pressure = sensor_data.substring(firstcommaindex + 1, secondcommaindex);
    pulse_rate = sensor_data.substring(secondcommaindex + 1, thirdcommaindex);
    temperature_body = sensor_data.substring(thirdcommaindex + 1);

    HTTPClient http;
    http.begin(serverName);
    http.addHeader("Content-Type" , "application/x-www-form-urlencoded");
    String httpRequestData = "machine_identifier=" + machineid + "&temp=" + temperature_body + "&hr=" + pulse_rate + "&sys_pressure=" + systolic_pressure + "&dias_pressure=" + diastolic_pressure + "&oxy_lvl=" + SpO2 + "&room_number=" + room_number + "&bed_number=" + bed_number + "";
    Serial.print("HTTP Request Data: ");
    Serial.println(httpRequestData);
    int httpResponseCode = http.POST(httpRequestData);

    if(httpResponseCode > 0)
    {
      Serial.print("HTTP Response Code: ");
      Serial.println(httpResponseCode);
    }
    else
    {
      Serial.print("Error Code: ");
      Serial.println(httpResponseCode);
    }
    http.end();

  }
}

The arduino mega is sending a string with the variable values set to 0 at startup. The MAX30100 sensor is doing its job of taking the readings however, as soon as the HTTP Post Request is done, the oximeter then defaults to it's static values and refuses to detect further readings.
Output:
This is output before HTTP Post

Output after HTTP Post

Once the http post request on arduino startup is done, or if i am taking readings from arduino after startup, the max30100 oximeter stops working and refuses to take further readings or update the values further.
The data is sent to mysql db where i will bbe fetching it on the website using php js and html css. This issue of the oximeter has been bothering me since so many days now and my final year project is nearing. Could anyone please guide me as to how to solve this problem?
Here is the library im using for the MAX30100: https://github.com/oxullo/Arduino-MAX30100

Why are you storing your numeric values in strings?

please, no screanshots of text ... add the actual text to your question

Well. Finally. Figured it out. After countless hours of googling and reading the issues on the github library, i just had to insert one line. resetFifo to reset the module after http post and re enable it to take readings normally.
Updated code:
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Wire.h>
#include "MAX30100.h"
#include "MAX30100_PulseOximeter.h"

#define REPORTING_PERIOD_MS 1000

MAX30100 maxim;
PulseOximeter pox;

const char* ssid = "SDsouza";
const char* password = "dsouza@8104045917";
const char* serverName = "http://10.0.0.13/post-sensor-data.php";

String systolic_pressure;
String diastolic_pressure;
String pulse_rate;
String temperature_body;
String BPM;
String SpO2;

uint32_t tsLastReport = 0;

String sensor_data;
bool Sr;
String machineid = "MR1";
String room_number= "A1";
String bed_number= "1";

HTTPClient http;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(16,OUTPUT);
  WiFi.begin(ssid , password);
  Serial.print("Connecting to SSID:");
  Serial.print(ssid);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("Connected Successfully!!");
  Serial.println(WiFi.localIP());
  if(!pox.begin())
  {
    Serial.print("Failed");
    for(;;);
  }
  else
  {
    Serial.println("Success");
  }
  pox.setIRLedCurrent(MAX30100_LED_CURR_50MA);
  http.begin(serverName);
}

void loop() {
  // put your main code here, to run repeatedly:
    pox.update();
    if(millis() - tsLastReport > REPORTING_PERIOD_MS)
    {
      BPM = pox.getHeartRate();
      SpO2 = pox.getSpO2();
      Serial.print("Bpm: ");
      Serial.println(BPM);
      Serial.print("SpO2: ");
      Serial.println(SpO2);
      tsLastReport = millis();
    }
    while (Serial.available())
    {
      sensor_data = Serial.readString();
      Sr = true;

      int firstcommaindex = sensor_data.indexOf(",");
      int secondcommaindex = sensor_data.indexOf(",", firstcommaindex + 1);
      int thirdcommaindex = sensor_data.indexOf(",", secondcommaindex + 1);
      int fourthcommaindex = sensor_data.indexOf(",", thirdcommaindex + 1);

      systolic_pressure = sensor_data.substring(0, firstcommaindex);
      diastolic_pressure = sensor_data.substring(firstcommaindex + 1, secondcommaindex);
      pulse_rate = sensor_data.substring(secondcommaindex + 1, thirdcommaindex);
      temperature_body = sensor_data.substring(thirdcommaindex + 1);

      String httpRequestData = "machine_identifier=" + machineid + "&temp=" + temperature_body + "&hr=" + pulse_rate + "&sys_pressure=" + systolic_pressure + "&dias_pressure=" + diastolic_pressure + "&oxy_lvl=" + SpO2 + "&room_number=" + room_number + "&bed_number=" + bed_number + "";
      Serial.println(httpRequestData);
      http.addHeader("Content-Type" , "application/x-www-form-urlencoded");
      Serial.print("HTTP Request Data: ");
      Serial.println(httpRequestData);
      http.POST(httpRequestData);

      maxim.resetFifo();
    }
}

This code works flawlessly and i can now serial read from arduino, read from the oximeter and http post it to the database normally and again repeat these steps without any errors.


text:
Issue understanding timestamp generated using millis() function
I have this code uploaded to an Arduino Uno which is connected to a gyroscope and storing the data on an SD card. The code is from the OEM.
The delay() function was set to 500 by default but this was changed to 10 in order to get an output frequency of 100Hz.
The millis() function was added to observe whether the 100Hz frequency was being maintained.
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
File myFile;

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
int Addr = 105; // I2C address of gyro
int x, y, z;

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

Serial.print("Initializing SD card...");

  if (!SD.begin(10)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

 writeI2C(CTRL_REG1, 0x1F); // Turn on all axes, disable power down
 writeI2C(CTRL_REG3, 0x08); // Enable control ready signal
 writeI2C(CTRL_REG4, 0x80); // Set scale (500 deg/sec)
 delay(100); // Wait to synchronize
}
void loop(){
 myFile = SD.open("test.txt", FILE_WRITE);

 getGyroValues(); // Get new values
 // In following Dividing by 114 reduces noise
 Serial.print(millis());
 Serial.print(" Raw X:"); Serial.print(x / 114);
 Serial.print(" Raw Y:"); Serial.print(y / 114);
 Serial.print(" Raw Z:"); Serial.println(z / 114);

 myFile.print(millis());
 myFile.print(" Raw X:"); myFile.print(x / 114);
 myFile.print(" Raw Y:"); myFile.print(y / 114);
 myFile.print(" Raw Z:"); myFile.println(z / 114);

myFile.close();

 delay(10); // Short delay between reads
}
void getGyroValues () {
 byte MSB, LSB;
 MSB = readI2C(0x29);
 LSB = readI2C(0x28);
 x = ((MSB << 8) | LSB);
 MSB = readI2C(0x2B);
 LSB = readI2C(0x2A);
 y = ((MSB << 8) | LSB);
 MSB = readI2C(0x2D);
 LSB = readI2C(0x2C);
 z = ((MSB << 8) | LSB);
}
int readI2C (byte regAddr) {
 Wire.beginTransmission(Addr);
 Wire.write(regAddr); // Register address to read
 Wire.endTransmission(); // Terminate request
 Wire.requestFrom(Addr, 1); // Read a byte
 while(!Wire.available()) { }; // Wait for receipt
 return(Wire.read()); // Get result
}
void writeI2C (byte regAddr, byte val) {
 Wire.beginTransmission(Addr);
 Wire.write(regAddr);
 Wire.write(val);
 Wire.endTransmission();
}

However, these are the first few values that were saved onto the "test.txt" file:

This shows a change in time of approximately 0.03s between values and therefore a frequency of 33.3Hz. Does anyone know why this is the case?

every command in the program takes time to execute ... some longer than others

You are opening and closing the file on every loop iteration. That looks like a bad idea...

29 characters at 9600 baud is about 0.030s/loop().

The delay just adds time to the overall runtime of the loop() function. So you would have a frequency of 100Hz only if all the other code would take zero time. And what you are doing there does take a significant amount of time (communicating over I2C and SPI, writing to the SD card). Thus your overall runtime of one loop() iteration is considerably longer. From your data we can even say how much longer it took. You measured a 30ms interval between the samples. 10ms of that is the delay. So the rest of the code took 20ms to execute. That also means, that with your current code you can get only up to 50Hz (by removing the delay()).
First to explain how to go with a timing situation like this lets assume the targeted frequency is possible with your code:
You have 2 options to go with timing:

Make the delay() smaller. With trail and error find a value that results in a 100Hz sampling frequency.
Use millis() directly for the timing. That way it is not important how long your code took to execute (as long as it was shorter than your sampling interval). For this you can basically copying the code from the BlinkWithoutDelay example, which uses millis() to blink an LED. You can use it to instead collect data samples and write them to the SD card.

The second option is superior and also a very important concept to understand in programming for Arduinos (or any microcontroller).

Now lets have a look at the problem with 100Hz. As explained above your current code takes too long to execute, so that you cannot reach a sample rate of 100Hz. You should use millis() to also check, which part of the code does take the most time.
I suspect that its the file writing. One way to speed this up is to only open and close the file once, instead of in every loop() iteration (as Edgar Bonet mentioned in the comments). After that I don't think you can speed this up further. A technique, that is often used in such situation, is to first collect a defined number of samples at the wanted frequency - temporarily saving them in an array - and then stop the sampling for writing to the SD card. That can give you short bursts of faster sampling at the cost of needing to wait for writing after that. It depends on your application if that is OK for you.
For the I2C you might be able to speed it up a bit. If your gyroscope is supporting that you can set the I2C clock signal to a higher frequency, for example 400kHz instead of 100kHz, via Wire.setClock(). Note that only specific values are allowed with this function and if a value works depends on your microcontroller. I think the Uno supports up to 400kHz.
You need to test by yourself if you can get the execution time below 10ms per loop() iteration.

Your loop() function takes many milliseconds to execute because reading gyroscope, opening file on SD, and writing on serial are slow and blocking operations. On top of this, you add delay(10), so your final frequency will always be lower than 100Hz.
You should use the while-millis pattern, a standard and simple solution to overcome this issue. Here a complete explanation about it.


text:
FastLED fill_solid array
I'm having trouble in the fill_solid function with arrays. can you help give color to row3.
int row3[]={1,2,3};
uint8_t sizerow3 = sizeof(row3)/sizeof(row3[0]);

void solid(){
  fill_solid(leds[row3[3]], sizerow3, CRGB :: Red);
  LEDS. show();
}

This is my complete program.
Thank you

What is the problem with your code? Please add a detailed problem description

i need help how to turn on the leds from row1[] to row5[] in sequence. (per row not per pixel)

leds[row3[3]] is not what you think it is. That is selecting one single LED depending on what is in element 4 (index 3) of the 3-element array row3. Since there is no index 3 in a 3 element array (only indexes 0, 1 and 2) the value it returns to use as an index to the leds[] array is unknown.
fill_solid is designed to fill a single uninterrupted string of LEDs starting at LED n and progressing for a number of LEDs after that. To set random LEDs all to the same colour you should simply loop through your list of target LEDs and set the colours individually. Something like:
for (int i = 0; i < sizerow3; i++) {
    leds[row3[i]] = CRGB::Red;
}
LEDS.show();


text:
Using both FastLED and Webserver without glitches possible?
I'm using an ESP8266 to control a short strip of WS2812 LEDs. I also want some way of remote Control so I'm looking into using a Web UI with the ESPAsyncWebServer library.
However using that Webserver makes the LEDs flicker so I tried disabling Interrupts
#define FASTLED_ALLOW_INTERRUPTS 0
#define FASTLED_INTERRUPT_RETRY_COUNT 2

That does help a bit, the flickering is less frequent but now there's some color glitches aswell.
All in all not usable.
So is there a way to get rid of all that flickering or is it just not possible to use the LEDs and a Webserver together when maintaining a high refresh rate?

might try websockets instead of http. the client code is about as simple and the "requests" tend to execute much faster without all the http overhead. you can also use a 2nd ESP to do web, talking to the LED ESP via serial, which is buffered and also low-impact.

Alternatively upgrading to a dual-core ESP32 would remove the problem and give you a more capable chip into the bargain...


text:
Arduino to run and LED strip of up to 100m
I am working on a project to run an RGB strip around a large room and have the colour change driven by an Arduino Uno. I have encountered a number of issues and am looking for clarification.
The first strip I used was a 12V strip at 1A/m. This would work fine except the power requirement is slightly ridiculous and it seems I need to put my array of MOSFETs in at every power injection point.
This was when I decided to experiment with a 5V addressable strip to do it. Working with a 5V system gave me more ease as the power requirements are lower and the parts list is also minimal, but after some research, it seems that the signal line will degrade significantly on that many WS2812B's / line length.
I suppose I could but a transistor inline every n-number of 5m strips (similar to the power injectors), however I would like to ask for some opinions from the community around other issues I may encounter, and whether or not this is the right solution for the job.
The scope of the project is to hold a colour for a number of seconds then switch colour based on a predefined program. This program is defined on an external device that uses the Arduino's serial port to communicate the desired colour. The implementation itself is very simple.
The main issues I can see are the power requirements (I think I have this sorted for the 5V version but not the 12V version) and getting the signal to the final LED. On a 60 LED/m strip this could be in the order of around 6000 LED's and that seems like a lot.
What are your views/recommendations?
Cheers!

What makes you think the signal will degrade over that number of LEDs?

@Majenko I read it on the arduino forum somewhere. If that is not the case then that is cool. I think the post on the forum said they were getting interference from other wires in the vicinity of the signal line (maybe power or something) I'm essentially a n00b at this - it has been ages since I messed around with micro electronics and I'm re-learning everything again lol. If my assertions are incorrect I am happy for constructive criticism :)

The WS2812B datasheet states: Built-in signal reshaping circuit, after wave reshaping to the next driver, ensure wave-form distortion not accumulate. -- Basically the "distance" is only ever the distance between two adjacent LEDs.

@Majenko That's awesome news. So there shouldn't be too much of an issue driving that many LED's with a Uno? From my research, 60(LED's per metre) * 100 * 3(bytes/LED) gives me 18K of memory needed to store the state. Since the Uno has 32K I should be fine right?

... I think there are some youtube videos that show where voltage drop can affect color on long runs. Probably due to PWM variations due to slight voltage differences betwen the power injection point and the far end.  Also the longer the string of addressable LEDs the larger the amount of data to be sent the slower the rate of intentional change.  I would at least run larger power wires and inject power at several locations.

"... gives me 18K of memory needed to store the state. Since the Uno has 32K I should be fine right?"  Will all the LEDs be set the the same color?  I'm not sure how the driver works, but if you set all the addressable LEDs to the same color then why would you need to store each LED's color setting?  Of course, if all the LED were set to the same color you could get by with a much cheaper RGB&Gnd type LED strip.

Seems I remembered incorrectly - it only has 2k of RAM. So that is a problem. I think I need to jump up to the MEGA or the Nano 33 to store the values. The main reason it is storing the values @st2000, is that I am using the FastLED library to do this. But you are right - if I write the 'setter' code myself then I won't need the memory.

@st2000 I was using a 12V -RGB setup before but the power requirements and  my assumed need for a box of MOSFET's every-so-often deterred me from the idea. 100m of lights at that voltage required 100A of power and that seemed like it was dangerous. The system needs to be foolproof and stable.

@st2000 ... that's why I think the addressable option is better cause they just plug into each other and have power at each connection to inject power when required.

... I've never put much thought into a 100 meter run of addressable LEDs so don't feel comfortable saying what you propose will work or not (I think it will, but you may have some unexpected problems you will have to work thought).  Consider searching for people who "trim their houses" w/these types of LED strips.  Some of the problems they have worked through may interest you.

Signal degradation: This is pretty much not a problem, as long as you just send the signal through the LED strip. Each WS2812B chip has circuitry to ensure, that the output signal is shaped correctly. As long as you don't have long runs of pure cable for the signal in between you will be good.
Power requirements: Using WS2812Bs lets you ditch your own MOSFET driving circuits, though the overall power will be in the same range. When you drive the LEDs at full intensity white (R, G and B full intensity) each LED will draw about 60mA. With 60 LEDs/m and 100m length you have 6000 LEDs, which equates to a max current of 360A. Thats a lot. You will probably need multiple power supplies. I think you can get 5V power supplies with like 70A from typical retailers. Of course there are also some which, provide more, but you will also want to reduce the max length of cable the current will flow (putting each power supply near the strip part, that it is powering).
Also you should inject power to the strip every 1 to 1.5m to stay safe. Above that you can see degradation after some time (I injected every 2.5m once and the LEDs still work, but you can see the degradation on the strip material and it gets hot when being on).
IMPORTANT: When you buy the typical brick power supplies, they often use a barrel connector. But with these currents you shouldn't use them. In one of my own projects I currently have to replace those with better connectors, because the barrel connectors started to melt from the heat and smoked. I know use small banana connectors, which are also used for drone motors. They can handle way more current without getting hot. Also your cable should be thick enough to handle the current without getting hot.
Controller:
As you already know you will get into the memory limit with the Uno. Your assessment of the needed memory for using the FastLED library (or the NeoPixel library) is correct. You will need 18kB only for the buffer (not including the rest of the programs variables).
Now you can either

change to a microcontroller with enough RAM to handle that buffer
or send the data out on demand instead of first filling it into a buffer.

The first option will definitely be easier with programming. The second option will require you to do some handwork. The libraries that I know of all use a buffer. Though I've once read this article about the timing on WS2812B LEDs. In the end the author also links to his working code, which puts out the data directly without using a buffer. You might wanna have a look at it. Also you could look at the code of the FastLED or Neopixel library. They of course also have the code to send the data and you might be able to copy and adapt that code for your case.

Thanks for this - really informative. The power requirement is what scares me really. I was thinking of a 8-10A power supply every 5 metres product I might use - the manufacturer says 6-8A should run 5m.

use 10A per 5 meters at least. A power supply can get less efficient when near max capacity and it will get rather hot with 8A. Used 8A supplies with the project I mentioned and they get really hot. The power is nothing really dangerous. With 5V you cannot do much harm to humans. Though you need to make sure, that every part of the project is able to handle way more current than you need. If they get too hot they might cause a fire.

And please don't use the barrel connectors, that are used by most brick power supplies. Those cannot handle currents over a few amps. Mine were melting with 8A, so I currently replacing them with small banana connectors.

And that is my ultimate worry. It will switch between colours every 40 secs or so but I can program the system that I am building to either exclude white or make it dull. The only colours I am supporting are RGB values from here so I don't think the power requirements will be huge but will still be enough to require multiple injection points.

With a 100m strip you are already in a really high territory, even when you dim the LEDs down. In this situation I would plan with the full possible power. It gets more safe, when your system is able to handle more power, but needs less. And it gets less safe, when your system can handle less power and the needed power approaches the max power. So planing with a big headroom is more safe.

RE: barrels - Yeah the final product will probably use spade connectors like this to deliver the power. That should be fine I think.

Personally for power I use small buck regulators (3A) at regular intervals (depending on density of LEDs) and feed those from higher voltage, lower current, power sources. For example a 24V 10A supply should be able to run up to about 36A at 5V spread across 12 24V->5V buck regulators and not lose as much over the power wires.

@Majenko this was a topic of discussion between me and a mate. Using 48V (something like PoE) to run some wire around the building and then regulating it down to the correct voltage.

Re “this article about the timing on WS2812B”: I have used the technique described in that article, and it worked pretty well even on an ATtiny13A, which has only 64 bytes of RAM.

Also a third option for solving the RAM problem: use multiple microcontrollers and implement some form of communication bus between them.

@Majenko this has been on my mind - but I really want to avoid it lol. The system is gonna be rolled out to places I can't debug at so debugging a dead LED or PSUI is easy. But trying to get someone to reset all controllers because there is a comms issue is not in scope of the project.


text:
Arduino Nano Atmega328P not sleeping with either <LowPower> or <avt/sleep.h>
I'm working on a battery powered Arduino Nano project. I really need it to save power for hours on end, so I turned to Arduino LowPower Library and avr/sleep.h to do the job.
However, whatever I do, it doesn't look like the board isn't going to sleep. I have a sample sketch that tries to put the board to sleep and then toggles a relay when it wakes up, but it always toggles the relay instantly after booting, so that means it hasn't gone to sleep.
I also measured the current going into the board, and it's drawing 14mA consistently. I would expect to see a much lower draw whilst it's asleep.
Here are the two pieces of code that I've tried, one with LowPower and the other one with avr/sleep.h
void setup(){
    pinMode(relayPin, OUTPUT);
}

void loop(){
    // This call doesn't seem to do anything
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    toggleRelay(); //This gets executed continuously, with no indication of sleep time
}

Here's the other one with LowPower
void setup(){
        pinMode(relayPin, OUTPUT);
    }

    void loop(){
        // This call doesn't seem to do anything
        LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);

        //This gets executed continuously, with no indication of sleep time.
        //I would expect it to see it toggle only every 8s
        toggleRelay();
    }

I'm probably doing something stupid, but I can't figure out what... Any help?
Thanks a lot!

I don't know about the LowPower library. However, four your
avr-libc-based test, you forgot to actually put the device in sleep
mode with sleep_mode():
void loop() {
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // select a deep sleep mode
    sleep_mode();   // now go to sleep
    toggleRelay();  // executed at wake up
}

Beware that, if you haven't enabled a wakeup source that is active in
the mode you selected, the microcontroller may sleep until it is
power-cycled or receives an external reset.

Oh that was it, yeah! Draw dropped straight down to 5mA. Thanks! I knew it had to be something stupid I'd forgotten.


text:
rst cause:2, boot mode:(3,6) caused by pointer reference
I am experiencing an unusual issue with my code.
I have a LOLIN WEMOS D1 mini Lite and I am using the Arduino IDE to upload the sketch.
The version of the board is 3.0.2 for ESP8266.
The problem is with the following line of code:
unsigned long n = (this->configuration)->getOffset();

There is a class Aggregator which has a private member variable named configuration which is a pointer to another object of class Configuration which is initialized as a global instance. The above line of code is contained in one of the methods of Aggregator. Basically, it is trying to access a member getter method of a Configuration object and the pointer to this object is set in one of the private members of the Aggregator class. This pointer is initialized in the constructor of the Aggregator class.
When the code is uploaded, the Serial prints out some garbage values and when the Serial Monitor of the Arduino IDE is set to 115200 Baud then the output is:
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 3460, room 16
tail 4
chksum 0xcc
load 0x3fff20b8, len 40, room 4
tail 4
chksum 0xc9
csum 0xc9
v00052b80
~ld

Whenever this line is commented out, the code works fine and the Serial console displays the actual messages and expected lines. It seems that with the above line of code, the board seems to restart in a loop.

Print out the addresses of this->configuration and your global configuration object and see if they match...


text:
how to set the arduino due adc automatic trigger
How do I trigger automatic conversion on the ADC on the DUE? If this was the uno, I could just do
 sbi(ADCSRA,ADATE); sbi(ADCSRA,ADSC);
but for the due, I seem to have to use
adc_configure_trigger(ADC, ADC_TRIG_SW, 0);
Though I am not seeing an auto trigger option, only software/external triggers. Will it just know to start conversion once it sees data coming through?

Adc has register ADC_MR (adc mode register) and also flag FREERUN...

so would setting adc_configure_trigger(ADC, ADC_MR, 1);  set up automatic trigger?

I'm not sure, maybe. Or maybe adc_configure_trigger(ADC, ADC_TRIG_SW, ADC_MR_FREERUN_ON);


text:
ESP32 Wifi not working when powered by battery
I'm quite new to ESP32 development. I've been using this devkit for a few small projects and everything was going smoothly until I decided to run it on battery. In particular, the ESP32 devkit I'm using, when connected to a battery, seems to have issues when trying to connect to the Wifi.
I'm using a 9V battery connected to a MB-V2 power supply to convert the output voltage to 3.3.V. The power supply board has the following specifics:

Input voltage: 6.5-9v (DC) via 5.5mm x 2.1mm plug
Output voltage: 3.3V/5v
Maximum output current: 700 mA
Independent control rail output: 0v, 3.3v, 5v to breadboard

As you can see in the picture, my multimeter measures an output voltage of about 3.3V

I built a sample project for debugging, here's the schematics:

The battery is connected to the power supply which outputs 3.3V and powers the ESP32 through its 3.3V pin. I don't have a schematic for this specific devkit I'm using so the devkit used in the schematics is the DOIT one, hence all of the pins are off. The code is quite simple, though, so it hopefully can clear things a bit:
#include <WiFi.h>

const int uS_TO_S_FACTOR = 1000000;
const int TIME_TO_SLEEP = 3;
const int RED_LED_PIN = 32;
const int BLUE_LED_PIN = 25;
const int YELLOW_LED_PIN = 26;
const char SSID[] = "SSID";
const char PASS[] = "PASS";

void startupSequence(){
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(BLUE_LED_PIN, LOW);
  digitalWrite(YELLOW_LED_PIN, LOW);
  // Sequence
  digitalWrite(RED_LED_PIN, HIGH);
  digitalWrite(BLUE_LED_PIN, HIGH);
  digitalWrite(YELLOW_LED_PIN, HIGH);
  delay(1000);
  digitalWrite(RED_LED_PIN, LOW);
  digitalWrite(BLUE_LED_PIN, LOW);
  digitalWrite(YELLOW_LED_PIN, LOW);
  delay(500);
}

void setup(){
  Serial.begin(115200);
  while(!Serial){}
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);
  pinMode(YELLOW_LED_PIN, OUTPUT);
  startupSequence();
  delay(500);
  digitalWrite(RED_LED_PIN, HIGH);
  delay(1000);
  Serial.print("Connecting to ");
  Serial.println(SSID);
  WiFi.begin(SSID, PASS);
  while ((WiFi.status() != WL_CONNECTED) && (millis()<10000)) {
      Serial.print(".");
      delay(500);
  }
  Serial.print("Connected. IP: ");
  Serial.println(WiFi.localIP());
  digitalWrite(RED_LED_PIN, LOW);
  if(WiFi.status() == WL_CONNECTED) //Run this only the first time
  {
    Serial.println("Connected");
    digitalWrite(YELLOW_LED_PIN, HIGH);
  } else
  {
    Serial.println("Not connected");
    digitalWrite(BLUE_LED_PIN, HIGH);
  }
  delay(3000);
  digitalWrite(BLUE_LED_PIN, LOW);
  digitalWrite(YELLOW_LED_PIN, LOW);
  Serial.println("Going to sleep");
  esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR);
  esp_deep_sleep_start();
}

void loop(){}

In the code, the ESP32 first lights up all LEDs, then it lights up the red LED while it tries to connect to the Wifi. After at most 10 secs, it lights up the yellow LED if it successfully connected, otherwise it lights up the blue LED. Also, as a last thing I send the ESP32 into deep sleep, as my intention was to measure its power consumption during sleep.
When connected to the PC, everything runs smoothly, while when connected to the battery the ESP32 (apparently) never exits the while loop and the red LED stays always on. The RED led then starts flickering and the power LED start blinking. Resetting it throught the RST button on the devkit causes the power LED to start blinking and the red LED never lights up. This continues until I cut off the power, then the code seems to start again from the beginning (i.e. the startup sequence) and the this behavior repeats.
I've read a few posts about similar issues with ESP32 devkits, but the problem was always about batteries not having high enough voltage, which doesn't seem to be my case. What could be causing the issue?

Common problem. These 9V block batteries are not meant for providing the needed current. They are only for low power appliances, like smoke detectors or IR remotes. Use a battery that can actually provide the needed current (can be up to 1A for a short time with Wifi working)

The third point my answer to this question talks about that.

"batteries not having high enough voltage, which doesn't seem to be my case" - It is as soon as you actually draw some power from the battery. Then - due to the batteries internal series resistance - the voltage will drop fast.

try the gnd pin on the upper right, that one on the lower/middle left is apparently not a gnd but is mislabeled as one on some of my modules. drove me nuts...

@chrisl you're completely right, I didn't realize it was the battery. I switched it with my phone power bank, which connects through a USB cable, and everything works fine. I didn't record currents over 120 mA even with the Wifi working though.

I have this same issue. It's quite annoying because my Arduino used to work just fine. After switching over to ESP32, 4 1.5V AA batteries ain't cutting it. I guess I'll have to order yet another battery case...

I agree with chrisl, the battery does not have a low enough impedance to operate your project. What you are not taking into account is the transmitter current when it is transmitting to the wifi. I have been finding that when it wakes up it draws upwards of 500mA for a short time, measured with a scope and current probe. This appears during the " WiFi.scanNetworks()" function. Add on top of that all the LEDs and other electronics What do you think it will draw. The fact that it operates on the USB also helps confirm this. Try with 6 bigger batteries in series, I expect it to work properly. Check this link out from:Expressif, the manufacturer of the chip at https://esp32.com/viewtopic.php?t=2662

Also replacing the linear regulator with a switching one of >1A will help matters considerably.

Thank you very much, it was the battery, I switched it for a power bank and everything works fine. I didn't realize how power-hungry the ESP32 can be. I'll try to use some of the suggestion in this thread since the power bank has another issue: it shuts down during the ESP32 deep sleep phase, but that's a different issue.


text:
How to pass non-static class member to callback on avr platforms?
I am using the PubSubClient library in my own Arduino library. I'm having trouble with trying to assign a class member as the client library setCallback callback function.
MyClass.cpp:
#include <PubSubClient.h>
#include <Wifi.h>
#include "Arduino.h"
#include "MyClass.h"

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

void MyClass::connect(String host, int port) {
  mqttClient.begin(host, port, "/");
  mqttClient.setCallback(incomingEventHandler);
}

void MyClass::loop() {
  mqttClient.loop();
}

void MyClass::incomingEventHandler(char* type, byte *payload, unsigned int length) {
  // do stuff with incoming data
  // need to access other member functions and class variables
}

MyClass.h:
#ifndef MyClass_h
#define MyClass_h

#include <PubSubClient.h>
#include <Wifi.h>
#include "Arduino.h"

class MyClass {
  public:
    void connect(String host, int port);
    void loop();
    void incomingEventHandler(WStype_t type, uint8_t *payload, size_t length);
};

#endif

Error I see is:
sketch/MyClass.cpp: In member function 'void MyClass::connect(String, int)': MyClass.cpp:14:47: error: no matching function for call to 'PubSubClient::setCallback()'
mqttClient.setCallback(incomingEventHandler);

If I move the incomingEventHandler function outside the class definition, it works as expected, however then I can't call other class members or access class properties in the same scope.
In arduino c++ how can I pass non-static class member properties as a callback? Is there a better way to approach this?
P.S. This code is only to show the intent. It might not be compile too.
There was a similar question like this at: How to pass non-static class member to callback?
but this is for esp-8266 and this is for avrmega4809 based board.

Personally I usually write a small wrapper that calls a function on a global object. Either as a normal function or as a static function if I only ever need one instance. Crude, but effective.

You can't. On the AVR platform, PubSubClient::setCallback() expects a
raw function pointer as a callback, and that is what you have to
provide. A static method is equivalent to a raw function, a non-static
method is not, and neither are a functor or an std::function.
If you need more that one MyClass object, one solution might be to
modify the pubsubclient library in order for it to store a pointer to
your MyClass instance, and pass this pointer to your callback. If you
never have to instances of MyClass subscribe to the same topic, a
better solution might be to statically store a map from topics to
MyClass instances and, within the callback, use this map to find the
appropriate instance.

Technically you can do it, but not without changing the library. Easiest way would be pure virtual interface class definition and inherit from it and override callback method. Another way would be https://www.tutorialspoint.com/function-pointer-to-member-function-in-cplusplus (similar changes as the first way)


text:
Audio range with custom waveshape
I am planning to use several Arduino to produce audio range analog signals. I need to use custom waveshapes generated on the fly. As far as I understand, there are two paths:

Aquiring a DAC, but can I send instructions fast enough (the Arduino needs to process the waveshape table) for audio rate signals? On a DAC like this one, I see that it supports a 100kb/s standard I2C and a 12 bit precision, so my guess is I will have 100kb/s / 12b / 10kHz = 0.8 input/period at 10kHz... Will this suffice? Or will it creates compression artefacts?
Using the Mozzi library, but it seems to me it outputs through a PWM digital IO pin. As I have a lot of Arduino to process, I would like to limit the number of RC circuitry I have to solder. Moreover, can Mozzi use custom waveshapes?

If you see any other solution, you are very welcome !
Thanks in advance

and I2S DAC ? .

Keep in mind the nyquist rate: You need at very least 2 samples per period to make sure the resulting wave has anything to do with the real target wave. And when you want to represent the shape of the wave correctly, then you will need significantly more samples. What is the highest frequency signal part, that you need to represent?

I need to go up to 20 kHz. I will investigate the I2S path. Thanks !


text:
Simulink Legacy Code Tool - custom Arduino servo write block problem
I'm trying to create my own servo.write block in Simulink for Arduino DUE deployment (and External Mode). Before you ask why if there is one available inside the Simulink Arduino Support Package, generally my final goal is to create a block that will use Arduino servo.writeMicroseconds function (there is no out of the box block for this one) but first i want to try with something simple to debug to see if i can get it to work....
I've been using this  guide (https://www.mathworks.com/matlabcentral/fileexchange/39354-device-drivers) and one of working examples in there as a template and started modifying it (originally it implemented Digital Output driver). I took the LCT approach.
The the original digitalio_arduino.cpp/h files from the guide (example with digital read/out) were the files I modified as they were working without any issues out-of-the-box. Step by step i made following modifications:

Remove DIO read (leave only write) from CPP and H files

Change StartFcnSpec to digitalIOSetup and make changes in H file so port is always in OUTPUT mode

Include Servo.h library within CPP file and create Servo object

Up to this point, all edits went fine, no compile errors, all header files were detected by Simulink and diode kept blinking as it should so the code actually worked (i ran it in External Mode).
But as soon as i made the final modification and replaced pinMode() with myservo.attach() and digitalWrite() with myservo.write() (of course i changed the data type in writeDigitalPin function from boolean to uint8_T) the code, despite compiling and building without any issue didn't work at all. Specified servo port was completely dead, as it even wasn't initialised. Changing value on S-Function input didn't yield any results.
Of course If i replaced custom block with built in Servo Write block from Hardware Support Package, everything worked fine so its not hardware issue.
I'm completely out of ideas what could be wrong, especially that there are no errors so not even a hint where to look.
Here is the LCT *.m script used for generating S-Function:
def = legacy_code('initialize');
def.SFunctionName  = 'dout_sfun';

def.OutputFcnSpec  = 'void NO_OP(uint8 p1, uint8 u1)';
def.StartFcnSpec   = 'void NO_OP(uint8 p1)';
legacy_code('sfcn_cmex_generate', def);
legacy_code('compile', def, '-DNO_OP=//')

def.SourceFiles     = {fullfile(pwd,'..','src','digitalio_arduino.cpp')};
def.HeaderFiles     = {'digitalio_arduino.h'};
def.IncPaths        = {fullfile(pwd,'..','src'), 'C:\ProgramData\MATLAB\SupportPackages\R2021b\aIDE\libraries\Servo\src'};
def.OutputFcnSpec  = 'void writeDigitalPin(uint8 p1, uint8 u1)';
def.StartFcnSpec   = 'void digitalIOSetup(uint8 p1)';
legacy_code('sfcn_cmex_generate', def);
legacy_code('sfcn_tlc_generate', def);
legacy_code('rtwmakecfg_generate',def);
legacy_code('slblock_generate',def);

Here is digitalio_arduino.CPP file
#include <Arduino.h>
#include <Servo.h>
#include "digitalio_arduino.h"
Servo myservo;

// Digital I/O initialization
extern "C" void digitalIOSetup(uint8_T pin)
{
    //pinMode(pin, OUTPUT);
    myservo.attach(pin);
}

// Write a logic value to pin
extern "C" void writeDigitalPin(uint8_T pin, uint8_T val)
{
    //digitalWrite(pin, val);
    myservo.write(val);
}

// [EOF]

And here is digitalio_arduino.H file
#ifndef _DIGITALIO_ARDUINO_H_
#define _DIGITALIO_ARDUINO_H_
#include "rtwtypes.h"

#ifdef __cplusplus
extern "C" {
#endif

void digitalIOSetup(uint8_T pin);
void writeDigitalPin(uint8_T pin, uint8_T val);

#ifdef __cplusplus
}
#endif
#endif //_DIGITALIO_ARDUINO_H_

As I mentioned I've been using a working example as a reference. So I've modified it step by step to see if maybe there is a point when suddenly some error comes up but everything compiles yet does not work :/
I was wondering maybe if there is an issue with the Servo.h library or the Servo object and did some tinkering with these, like  i removed Servo myservo; line of code to see if anything happens and just like expected, i started receiving errors that Servo is not defined. If I did not include Servo.h at all or forget to add IncPath to Servo.h as before compile errors about Servo not being supported symbol or not being able to find Servo.h library - so actually the code seems to be "working" in a way, it seems to have everything it needs to work :/
I also looked at the MathWorks implementation of Servo Write block, the MWServoReadWrite to see how Arduino API is being used and no surprise, it's being used in the same way as I've been trying to. They include Servo.h, they are using servo.attach() and servo.write() to control the servo port. And that's it. Yet for them it works, for me does not :/
When I inspect generated C code that runs on Arduino (with my custom S-Function block in it), it seems that all the functions are placed exactly where they are supposed to be, they receive correct arguments. I expected at least that I'll find a hint in there, i.e.  missing code or anything else.

I'm not familiar with the Simulink Arduino plugin. Is there a main program file for the Arduino side? If yes, can you provide a link to it? Then we can look how it works. Is this compiled from inside Simulink? And also uploaded to the Arduino? Can you do basic debugging in the Arduino code, for example by turning on an LED right before writing to the servo?

Hey, the main program is generated on Simulink side too but you gave me an idea, i uncommented the digitalWrite code to see if the problem is only with servo and it turned out the cause of issue os on the Simulink side
Apparently, the generated main function is missing some routine that enables Arduino timers to control servos (Simulink decides to not enable it since it does not detect its own blocks.
Ill have to inspect how the code looks with built in Servo Blocks (of SImulink) and what is missing when I'm using custom blocks.


text:
Is there a good reference for Arduino Due memory architecture and usage?
It's been harder than I expected to find a reference source or usage guide.
There's a number of sources I've looked at along the road to this question:

The Due is listed here and here as having 512KB flash memory, 96KB SRAM and zero EEPROM.

The arduino foundation tutorial notes that Due memory architecture is different but doesn't expand further.

@Majenko's answer to this previous question notes, "There is no PROGMEM required on ARM. There is no memory bus separation between Flash and RAM"

The SAM3x datasheet block diagrams show a unified bus (i.e. Von Neumann architecture (not Harvard architecture like the AVR boards))

This answer on the Arduino Forum suggests (regarding allocating constants to flash), "[...] all you have to do is use "const" in the variable declaration. [...]  Everything that's "const" gets put into flash without consuming any RAM. PROGMEM, pgm_read_byte() and the other AVR names are defined only so code designed for AVR can compile. But they do absolutely nothing on [SAM3X MCUs] "

The F() macro seems to still work.

So my question is searching for links to a reference or guide for memory usage on the Arduino Due. I hope a guide (or your answers) might explain the differences caused by the change to a Von Neumann architecture bus, what is stored where, highlighting which memory handling techniques developed for Harvard architecture AVR MCUs remain relevant on the Due.
If there is no guide I'm hoping this question and your answers may become a good reference point. Thanks for reading!

Would it be correct to say that for Arduino Due, all constants (including in-code string literals not using F())  are stored in flash?

So (review feedback welcomed) in the Arduino Due SAM3x memory architecture compared to the AVR architecture:
Non-volatile flash memory
contains:

program instruction code (same as AVR)
bootloader (same as AVR)
all runtime C++ constants including incode string literals (different to AVR)

is accessed by:

C++ const data definition code and incode literals (different to AVR)
C++ instruction code (same as AVR)
PROGMEM, PSTR(), F(), pgmspace library *_P functions are not required and compile for platform compatibility only (different to AVR).

Volatile SRAM memory
contains:

variable dynamic storage, organised in a stack and heap structure (same as AVR)
no static/constant storage, which now stays in flash (different to AVR)

is accessed by:

C++ data definition code (same as AVR)

Usage

Heap fragmentation remains an issue to be managed. Preferencing local to global allocation, and avoiding dynamic heap allocation remains relevant to Arduino Due (e.g., Arduino strings)

Techniques to move constants to flash memory are not relevant for Due, but may be relevant for multi-board compatiblity.

Yes, the Arduino Due uses a flat memory model with a single address space for Flash and RAM. Therefore all constant data sits in flash and does not need to be copied to RAM at startup, like the AVR-based arduinos do. The progmem stuff for the AVR-based CPUs is required because they need to use different instructions to read data from flash than from RAM. This is no longer the case on the Due (nor most other 32-bit MCUs, such as the ESP32), and a string address in an instruction works just the same whether its in RAM or in Flash (as long as it's not written to, of course).
The F() macro is available for convenience, so that you can more easily write code that works for all Arduino boards. On the Due, it is basically implemented as no-op.
When you're working on the memory model of the Due, I might point to this question, showing that there's a bug in the memory management implementation of the Due, allowing unlimited memory allocation.