body:
I guess a simple solution would be to stick with the original
pattern and use only one variable... but have this variable be a
container for all the stuff you need:

```c++
struct StoredData {
    int32_t some_integer_variable;
    float some_float;
    // etc...
};
```

Then you can use the same pattern as the original code:

```c++
StoredData* my_data = reinterpret_cast<StoredData*>(ram_buffer);
```

and access the individual variables as `my_data->some_integer_variable`,
`my_data->some_float`, etc.


sender: user

message:
how to run 2 different servo (continuous rotation and regular servo) in parallel, not run one after other?

I need to control 2 servos in parallel, whereas one is of continuous rotation and another is of regular positioning control (angle) on arduino IDE. I tried but it works one after another, not parallel. How can I do that, please suggest. Thanks.

sender: assistant

body:
The angel of two Servomotors should be same ?
If yes,
Try this for 180 deg. Servos :
You can connect signal pin of ech servo to a specific PWM pin of Arduino like pin number '9' in this example
It's just for test but you can change this how you want to

I hope it will work you,
Good luck

    #include <Servo.h>

    Servo myservo;

    int PWMpin = 9;  // change this for your circuit configuration

    int a = 0;

    void setup() {
      myservo.attach(9);
      myservo.write(0);  // set servo to mid-point
    }
    void loop() {
      for (int i = 0; i < 180; i++) {
       myservo.write(i);
        delay(10);
      If (i == 180) {
        analogWrite(PWMpin, a);
        }
      }
    }


body:
I am proposing one answer

https://wokwi.com/arduino/projects/297646292038844936

Here, we are not using the delay function. We are using the `millis()`
Based on your actual application, you can control individual servo accordingly.

Here is the Arduino simulation:
https://wokwi.com/arduino/projects/297646292038844936
[![enter image description here][1]][1]

    /* Sweep
      by BARRAGAN <http://barraganstudio.com>
      This example code is in the public domain.

      modified 8 Nov 2013
      by Scott Fitzgerald
      http://www.arduino.cc/en/Tutorial/Sweep
    */

    #include <Servo.h>

    Servo myservo;  // create servo object to control a servo
    Servo myservo2;  // create servo object to control a servo

    // twelve servo objects can be created on most boards
    unsigned long previousMillis = 0;        // will store last time LED was updated
    const long interval = 15;           // interval at which to blink (milliseconds)

    int pos = 0;    // variable to store the servo position
    int pos2 = 0;    // variable to store the servo position

    void setup() {
      myservo.attach(9);  // attaches the servo on pin 9 to the servo object
      myservo2.attach(10);  // attaches the servo on pin 9 to the servo object

    }

    void loop() {
      unsigned long currentMillis = millis();

      if (currentMillis - previousMillis >= interval) {
        // save the last time you blinked the LED
        previousMillis = currentMillis;

        myservo.write(pos);              // tell servo to go to position in variable 'pos'
        pos = pos + 1;
        if (pos > 180) {
          pos = 0;
        }                      // waits 15ms for the servo to reach the position

        myservo2.write(pos2);              // tell servo to go to position in variable 'pos'
        pos2 = pos2 + 1;
        if (pos2 > 90) {
          pos2 = 0;
        }

      }

    }

  [1]: https://i.stack.imgur.com/Lx1cx.gif


body:
As i know, there is no way for a single arduino or any other microcontrollers to command on pins in exactly same time and it's because of microcontrollers nature.
When you have to command 2 outputs
Microcontroller will be act like this :

Command 1 .... To pin number 9
Command 2 .... To pin number 10

and for example if your microcontroller, like arduino or others do each command in one complete clock cycle and your clock frequency will be 16 MHz, so each cycle's time period is 62.5 nano-seconds.

So your microcontroller will do your command in first clock cycle and do the second command in next clock cycle,
In the other words, command 2 will do 62.5 nano-second after command one (if each those commands takes just one clock cycle) but in normal 16 MHz arduino boards it takes much much more time to do commands like this and it was just an example to understand it's principle, and because of this reason i suggest you to connect both servomotors into same output PWM pin if you are using two standard servomotors;
But the main issue is different angle limitations of your servomotors and it's impossible to control them when you want one of them to rotate 360 deg. and the other must rotate 180 deg. .
If you connect those signal pin to a same output, you have two options with two issuse.
First, if you command to the output pin to turn 360 deg. , All things will be good but when your output pin command for angles more than 180 deg. , The little servo will stop.
Second, if you limit your rotation to 180 deg., You will not be able to rotate 360 deg. Your bigger servomotor.

I hope my description will be useful and face you by your complete pattern of what's going on in this project's issue


message:
Serial communication of strings

I used this simple code to understand the basics of serial communication. This achieves simple communication between the computer and arduino:

    String receive_buffer;
    void setup() {
      Serial.begin(9600);
    }

    void loop() {
      if(Serial.available()>0)  //check for any data received
      {
          receive_buffer = Serial.readString();  //read received data
          Serial.print("received data is: ");
          Serial.println(receive_buffer);        //display received data
      }

    }

This works. Now, my next idea was to try communicating between two arduinos. I used this code for the reciever arduino.

The sender arduino contains a motor fitted with an encoder, and using the ppr value I  calculate the rpm of the motor. The code for rpm works perfectly. I now want to communicate this data to the receiver.

**Wiring**: (RX,TX) of sender connected to (TX,RX) of receiver, and `GND` is made common.

Now, on arduino.cc, it says that Serial.write() can have String as an input. So, I tried typecasting the rpm value (which was int), into a String, and then send that string to the receiver through Serial.write().

    float ppr=512.0;
    int encpin=3;
    volatile long pulsecount=0;
    float revs;
    float rps;
    int rpm;

    extern volatile unsigned long timer0_millis;

    void setup()
    {
      pinMode(encpin,INPUT_PULLUP);
      Serial.begin(9600);
      attachInterrupt(digitalPinToInterrupt(encpin),function,RISING);
                                            //when pulse is detected
                                               //interrupt triggered,
                                               //function callled
    }
    //increments pulse by one
    void function(){
      pulsecount+=1;
    }

    void loop()
    {
     revs= pulsecount/ppr ;
     if(millis()>=1000)
      {
        rps= revs;
        rpm=rps*60;
        pulsecount=0; //resets pulsecount

        String strrpm= (String)rpm;

        //Serial.println(rpm);
        Serial.write(strrpm);

       // Serial.println("string rpm");
        //Serial.println(strrpm);

        noInterrupts ();  //resests millis() to 0
        timer0_millis = 0;
        interrupts ();
      }
    }

 However, I get an error:

    43:24: error: no matching function for call to 'HardwareSerial::write(String&)'

The issue is not with typecasting. I tried to simply print strrpm and it worked fine. When tried Serial.write() with a different and simple string, i.e `Serial.write("abcdef");` , it still gave the same error.

**How then should I should I send my strrpm (string rpm) value to the receiver?**

body:
`Serial.write()` is meant for sending binary data. So if you want to send a string with it, you need to provide a c-string, not the Arduino implementation of the `String` class. That's done easily with a member function of that class:

    Serial.write(strrpm.c_str());

That compiles successfully for me.

Though you should not do it like this. The `String` class is generally bad on small microcontrollers, especially on the AVR microcontrollers with little memory (like Uno, Nano, Mega, ...), because it causes memory fragmentation (see [Majenkos "The Evils of Arduino Strings"][1]).

Instead you should just use the corresponding `print()` functions of the `Serial` class. They are made for sending human readable strings. No need to first build up a `String` object. Just do

    Serial.println(rpm);

And it will do the string conversion itself without using the `String` class.

---

Besides that I have some notes on your code:

- The way you use `millis()` is a bit weird. There is no need to actually reset the `millis()` value itself. Normally you would hold a timestamp in a variable and then only calculate the difference between `millis()` and the timestamp. That is also overflow safe. Like this

        unsigned long timestamp = 0;

        ...
        if(millis()-timestamp >= 1000){
            ...
            timestamp+=1000;
        }

    That doesn't use an extern variable, it is not resetting the `millis()` counter (which might mess with other things too, that rely on it) and is somewhat the standard way to do it.

- You are using an atomic section for resetting the `millis()` counter, but not for accessing `pulsecount`. That is actually the place, where you absolutely need this. `pulsecount` is of type `long`, so it will need many instructions to do the calculation for `revs`. The your interrupt service routine can easily mess with the data in that moment, resulting in garbled data. Move  the calculation into the if statement and use an atomic section like with the `millis()` counter to read it into a local variable then you can do the calculations. That will keep the time, where interrupts are turned off very short. You can also - instead of turning all interrupts off - just detach the pin interrupt for that time, so that other things are not affected. Like this code:

        void loop(){
            if(millis()-timestamp > 1000){
                 // deactivate our pin interrupt, so it cannot mess with the data
                 detachInterrupt(digitalPinToInterrupt(encpin));
                 // copy pulsecount to local variable for further calculation
                 long local_pulsecount = pulsecount;
                 // reactivate our pin interrupt
                 attachInterrupt(digitalPinToInterrupt(encpin),function,RISING);
                 // Do calculation and print the value
                 ...
                 timestamp += 1000;
             }
         }

  [1]: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/


message:
Will the noise from a voltage regulator interfere with IR LEDs and receivers on an Atmega328? (Arduino Uno sketch)

I have a project which uses an IR LED and receiver to communicate with other Arduinos. I am using the Atmega328 out of the Uno, rather than the whole Arduino board and I need it to be battery-powered, so I need to use a voltage regulator to maintain 5V to the chip.

I want to avoid a linear regulator if I can, as they are inefficient, but I'm worried that the other types will cause too much noise on the output and it will interfere with the IR communication.

Should I be concerned about this or am I making a fuss about nothing, I can always use a linear one if I need to.

Thanks in advance.

body: I bought a switching mode voltage regulator (buck-boost) to test it and it works fine, I put a 10uF capacitor across the output to reduce noise but that was just a precaution - I don't know if it was necessary.


message:
Trouble initializing a struct array

The goal for this is to create a struct that includes a name, ID, fileName, and a boolean, then create an array of that structs.
Here's what I came up with:

```
struct Amiibo
{
  char *aName{};
  char *ID{};
  char *AudioFileName{};
  bool alreadyPlayed{false};
};

Amiibo amii[20] = {

      {"Mario","A5005B00","MARIO",false},                     //0
      {"Meta Knight","A5 00 02 00","MK"},                     //1
      {"Inkling", "A5 00 05 00","INK"},                       //2
      {"Donkey Kong","A5 00 01 00","DK"},                     //3
      {"Lucas","A5 00 0A 00","LUCAS"},                        //4
      {"Duck Hunt", "A5 00 08 00","DUCKH"},                   //5
      {"Ocarina of Time Link","A5 00 01 00","OOTL"},          //6
      {"Breath of The Wild Link","random","BOTWL"},           //7
      {"8-bit Link","random","8BITL"},                        //8
      {"Toon Link","random","TOONL"},                         //9
      {"Mr. Game and Watch","random","GANDW"},                //10
      {"Falco","random","FALCO"},                             //11
      {"King Dedede","random","DEDEDE"},                      //12
      {"Mewtwo","random","MEWTWO"},                           //13
      {"Captain Falcon","random","CAPF"},                     //14
      {"ROB","random","ROB"},                                 //15
      {"PAC-MAN","random","PACMAN"},                          //16
      {"Cloud","random","CLOUD"},                             //17
      {"Ness","random","NESS"},                               //18
      {"Ryu","random","RYU"}                                  //19

};
```

This gives me the following error:
> error: could not convert '{"Mario", "A5005B00", "MARIO", false}' from '<brace-enclosed initializer list>' to 'Amiibo'

And the same error for all the other elements of the array.
I tried changing amii[20] to a pointer using *amii[20]. That got me this error:

> braces around scalar intializer for type "Amiibo"

I'm not sure what to make of that, since I'm fairly certain this isn't scalar type.

I'd really just like to make a struct array so I can cycle through these at random using a random seed. It shouldn't be that difficult, yet I'm running up against a wall. I'd appreciate any advice you all have to give. Thanks.

body:
If you use default values in struct declaration, you have to define also constructors for setting specific elements:

    struct Amiibo
    {
      const char *aName{};
      const char *ID{};
      const char *AudioFileName{};
      bool alreadyPlayed{false};

      Amiibo() = default;  // default implementation for default constructor

      Amiibo(const char* name, const char* id, const char * audio)  // constructor with three c strings as parameters
      : aName{ name }
      , ID{ id }
      , AudioFileName{ audio }
      { ; }
    };

    Amiibo amii[] = {
          {"Mario","A5005B00","MARIO"},                           //0
          {"Meta Knight","A5 00 02 00","MK"},                     //1
          {"Inkling", "A5 00 05 00","INK"},                       //2
          {"Donkey Kong","A5 00 01 00","DK"},                     //3
          {"Lucas","A5 00 0A 00","LUCAS"},                        //4
          {"Duck Hunt", "A5 00 08 00","DUCKH"},                   //5
          {"Ocarina of Time Link","A5 00 01 00","OOTL"},          //6
          {"Breath of The Wild Link","random","BOTWL"},           //7
          {"8-bit Link","random","8BITL"},                        //8
          {"Toon Link","random","TOONL"},                         //9
          {"Mr. Game and Watch","random","GANDW"},                //10
          {"Falco","random","FALCO"},                             //11
          {"King Dedede","random","DEDEDE"},                      //12
          {"Mewtwo","random","MEWTWO"},                           //13
          {"Captain Falcon","random","CAPF"},                     //14
          {"ROB","random","ROB"},                                 //15
          {"PAC-MAN","random","PACMAN"},                          //16
          {"Cloud","random","CLOUD"},                             //17
          {"Ness","random","NESS"},                               //18
          {"Ryu","random","RYU"}                                  //19
    };

Btw on the older AVRs all those strings will resides also in memory


message:
How to send a message to my phone that my Arduino system is on when turning on my Arduino

i have installed a GSM shield on the Arduino to create security alarm system using PIR SENSOR when ever there motion I will receive a call to my phone.
but i want to add also a line of code which can make my system send me a txt message stating that my system is turned on so i can make sure that when ever i turn my system on i can doule check by getting a message that says that system is turned on successfully
i dont know how to start doing that.
this is the code i did:

    int PIR = 6;

    void setup() {
      // put your setup code here, to run once:
      Serial.begin(96000);
     pinMode (PIR , INPUT );
    }

    void loop() {
      // put your main code here, to run repeatedly:
    if (digitalRead (PIR == HIGH)){
      Serial.println("thief detected");
      delay (200);
      Serial.println ("ATD+0197263315;");
      delay(1000);
      Serial.println("ATH");
      delay(1000);

      }
      else digitalWrite (PIR, LOW );

    }

body:
You can send an SMS using the Arduino [GSM library](https://www.arduino.cc/en/Reference/GSM). Here is a bare bones sketch that sends one pre-set SMS when it starts up, based on [this tutorial](https://www.arduino.cc/en/Tutorial/LibraryExamples/GSMExamplesSendSMS):

    #include <GSM.h>

    #define PINNUMBER "1234"
    #define REMOTENUMBER "07123456789"
    #define TXTMESSAGE "System started!"

    GSM gsmAccess;
    GSM_SMS sms;

    void setup() {
      boolean notConnected = true;

      while (notConnected) {
        if (gsmAccess.begin(PINNUMBER) == GSM_READY) {
          notConnected = false;
        } else {
          delay(1000);
        }
      }

      sms.beginSMS(REMOTENUM);
      sms.print(TXTMESSAGE);
      sms.endSMS();
    }

    void loop() {
    }

If you can't or don't want to use the GSM library, it should also be possible to send an SMS by using the [SoftwareSerial](https://www.arduino.cc/en/Reference/SoftwareSerial) library to control your GSM shield using [AT codes](https://www.developershome.com/sms/howToSendSMSFromPC.asp). Here's [a tutorial](https://create.arduino.cc/projecthub/SurtrTech/send-sms-text-from-arduino-using-sim800l-gsm-gprs-module-228975) on this approach, which is lighter weight but might be more fiddly to get working, especially if you need a PIN for your SIM card.


message:
Check pin capabilities at compile time

Are there board-independent functions to check pin capabilities at compile time? I.e.

- Can the pin be used as output, as in `digitalWrite()`?
- Does the pin support PWM, as in `analogWrite()`?
- Does the pin support ADC, as in `analogRead()`?
- Does the pin support interrupts, as in `attachInterrupt()`?

I'm looking for functions/macros like e.g. `isDigitalOutput(pin)` which would return false for input-only pins such as A6 and A7 on a 328P, but true on a Mega where those pins are input/output.

body:
For compatibility with `analogWrite()` there's `digitalPinHasPWM(p)` macro which returns 1 when PWM is supported on pin `p`.

For `analogRead()` there's `analogInputToDigitalPin()` which can be used as

```
#if ((p-PIN_A0 < 0) || (analogInputToDigitalPin(p-PIN_A0) != p))
#error Not an analog pin!
#endif
```

For `attachInterrupt()` there is `digitalPinToInterrupt(p)` which returns `NOT_AN_INTERRUPT` if the pin `p` doesn't support interrupts.

I still haven't found anything to test compatibility with `digitalWrite()`.


message:
Delay coding not working as expected

***Added second attempt at bottom of code, Please check it, works with out lag time but never turns Vacuum off?***  This project is pretty well explained in the code description. My main problem is I need a delay for **ditialWrite(vacPin,LOW);**.  With this part included the stepper doesn't react a quickly as before 2/3 sec lag, & the ACS712 current sensor does not read at all in the console screen.
I have tried different operatives, statements, and relocating the code in different spots with no luck!
I think this has a simple fix, but it has alluded me!. Hope this is clear enough, any help would be appreciated.

```
/*This version works as is **EXCEPT** the Delay vac 4 sec has to be turned off. See ########### area for Problem.
/*Auto Blast gate project:  for dust collection in wood shop.
  Arduino Nano
  ACS712 current sensor
  DRV8825 stepper driver
  Nema 17 stepper
  Each tool will be monitor by a current sensor and when that analog port exceeds a given threshold
  1. Rotate the stepper to a predetermined position to align ports for that tool.
  2. After the gate is align a digital pin will drive relay to turn on Vacuum system.
      Vacuum will stay on as long as sensor exceed the threshold while tool is running.
      **When tool stops vacuum will continue for 4 seconds to clear remaining dust.**
  3. If the same tool is used next, the Stepper will remain in it's current position.
      But the vacuum system should still operate the same.
  4.  currently using buttons to simulate tools and also one ACS712 for testing  */

// defines pins numbers
const int stepPin = 3;
const int dirPin  = 2;
const int enPin  = 8;
const int vacPin = 4; //simulate Vacuum relay

int ca = 0;  //currentAngle
int na = 0;  //angle
int stepPerAngle = 5 / 9; // full step = 1.8 or could have used "*1.8"
int   numstep;
int analogValue = 0;

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

  // Sets the 3 pins as Outputs
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(enPin, OUTPUT);
  pinMode(vacPin, OUTPUT); //Just added this for vac

  //set values for 2 outputs
  digitalWrite(enPin, LOW);
  digitalWrite(dirPin, HIGH);
  digitalWrite(vacPin, LOW); //just add this for vac

}

void loop() {
  int n;
 analogValue = 0;

  // Assign button degrees
  if      ( analogRead(A0) > 600) {
    analogValue = (analogRead(A0));
    Serial.print("AO = ");
    Serial.println(analogValue);
    na = 0;

  }
  else if ( analogRead(A1) > 600) {
    analogValue = (analogRead(A1));
    Serial.print("A1 = ");
    Serial.println(analogValue);
    na = 45;
  }

  else if ( analogRead(A2) > 600) {
    analogValue = (analogRead(A2));
    Serial.print("A2 = ");
    Serial.println(analogValue);
    na = 225;
  }

  else if ( analogRead(A3) > 600) {   //=tool on
  analogValue = (analogRead(A3));
    Serial.print("A3 = ");
    Serial.println(analogValue);
    na = 270;

  }

 /*###########################################################
 **this is where I need help.  The first if statement works as it should.
 when those 2 condition are met the vacPin goes high.** */

  if(analogValue > 600 && ca==na) {
    digitalWrite(vacPin, HIGH);
  }

/* **this part is not working correctly.  If the delay is remove it works as the "else if" statment reads.
  I need the delay so when a tool is stopped, the vacuum continues for a few secounds to clear remaining saw dust** */

else if (analogValue < 600) {
   delay (4000); **/*  with this on:
             the stepper does not start as quickly as before,
             the analog will not read the ACS712 sensor at all,  only the buttons*/**
    digitalWrite(vacPin, LOW);
  }

//################################################################################

  if ( ca != na ) {

  //2nd SCENARIO
  if (na - ca > 0 && na - ca <= 180)
    { digitalWrite(dirPin, HIGH);
      n = ((na - ca) * 5 / 9);
      numstep = n;
      ca = na;

    }

    //3rd SCENARIO
    else if (ca - na > 0 && ca - na > 180)
    { digitalWrite(dirPin, HIGH);
      n = ((na + 360 - ca) * 5 / 9);
      numstep = n;
      ca = na;
    }

    // 4th SCENARIO
    else if (na - ca < 0 && na - ca <= 180)
    { digitalWrite(dirPin, LOW);
      n = ((ca - na) * 5 / 9);
      numstep = n;
      ca = na;
    }

    //5th SCENARIO
    else if (na - ca > 0 && na - ca > 180)
    { digitalWrite(dirPin, LOW);
      n = ((ca + 360 - na) * 5 / 9);
      numstep = n;
      ca = na;
  }

    for (int x = 0; x < numstep; x++) {

      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1000);  //speed
      digitalWrite(stepPin, LOW);
      delayMicroseconds(1000);

    }

    delay(200);
  }

}
```

#################################################

```
if(analogValue > 600 && ca==na) {
    digitalWrite(vacPin, HIGH);
  }

/* this part is not working correctly.  If the delay is remove it works as the "else if" statment reads.
  I need the delay so when a tool is stopped, the vacuum continues for a few secounds to clear remaining saw dust */

// another variation to the section in question
else if (analogValue < 600 && vacPin==HIGH) {
   delay (4000);
/*  written this way it works but never turn Vacuum off?*/
    digitalWrite(vacPin, LOW);
  }
```

body:
It's not exactly clear what you're trying to do, but I think you want to start the vac and start the stepper, then 4 seconds later stop the vac. The 4 second delay forces the rest of your code to wait (doing nothing) during the 4 seconds.

Look at the Arduino IDE example program, BlinkWithoutDelay. The technique used there is what you need to use instead of delays, to allow your program to manage multiple things at once. This technique is called non-blocking; any time part of your program waits for something to happen blocks the code from doing anything else until that 'something' completes.

Search for non-blocking programming to read more. There are plenty of articles on the web, including in Arduino Stack Exchange that discuss that.

Update (following your 2021-05-05, 20:48Z update):

[Here is an answer][1] I wrote to similar question in which I wrote about non-blocking programming in more detail. The short answer is that you can't use delay() when you need to monitor or control several things simultaneously. *Delays keep anything else from happening until they expire* which is what is keeping your stepper from advancing as you intended. You need to do something like:

    if the tool is running,
      ; // do nothing
    else,
      save the time;    // this is the tool-stopped time
      move the stepper; // I assume the stepper completes in < 4s
    end

    if the tool is stopped and the vac is running,
      if (current_time - saved_time) >= 4000,
        stop the vac;
      end;
    end;
    // and let loop() keep running

Notice that this *never waits* for the tool or the fan. It just checks quickly and often, whether something needs to be done; if so, it does it; and in any case it continues on.

Because this is in your loop function, this code runs over and over again, so eventually, when 4 seconds has passed (in the case of the vac), the vac will get stopped, but meanwhile, the stepper has been able to run and any other small tasks needing doing will have an opportunity. The important point is, your code *never hangs around waiting* for anything to happen; it just very rapidly checks everything that could need to be {started, stopped, accelerated, ...}, if/when something is ready to be done, it does it, but it moves on immediately, in either case.

  [1]: https://arduino.stackexchange.com/questions/60759/how-to-rotate-two-or-more-steppers-simultaneously-by-giving-array-of-angles/66380#66380


body:
 I don’t know where to start but, this worked **PERFECTLY!** I need to work on stepper speed and ramp Length to smooth out, or jumpers on the DRV8825 expansion bd. Other than that, I want to understand the library! I went to the readme and it explained the thing it can do, but I don’t know how to utilize on my own. I noticed your name and written by are the same! Am I talking to a person or a company? Thanks again
 Thanks for everyone else that help as well and I need to study some of those solutions as well!

**MicroBahner**
May 8
This would be my suggestion with MobaTools:

/*This version works as is **EXCEPT** the Delay vac 4 sec has to be turned off. See ########### area for Problem.
  Auto Blast gate project:  for dust collection in wood shop.
  Arduino Nano
  ACS712 current sensor
  DRV8825 stepper driver
  Nema 17 stepper
  Each tool will be monitor by a current sensor and when that analog port exceeds a given threshold
  1. Rotate the stepper to a predetermined position to align ports for that tool.
  2. After the gate is align a digital pin will drive relay to turn on Vacuum system.
   Vacuum will stay on as long as sensor exceed the threshold while tool is running.
   **When tool stops vacuum will continue for 4 seconds to clear remaining dust.**
  3. If the same tool is used next, the Stepper will remain in it's current position.
   But the vacuum system should still operate the same.
  4.  currently using buttons to simulate tools and also one ACS712 for testing
*/
// suggestion with MobaTools for driving the stepper and timer fuction
#include <MobaTools.h>

// defines pins numbers
const int stepPin = 3;
const int dirPin  = 2;
const int enPin  = 8;
const int vacPin = 4; //simulate Vacuum relay

const int stepPer360Degree = 200; // Number of steps for one revolution ( adjust to your needs )
MoToStepper stepper ( stepPer360Degree, STEPDIR );
MoToTimer vacTimer; // for delayed switch off
const long runOnTime = 4000;

int na = 0;  //angle

int analogValue = 0;

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

  // Setup the stepper
  stepper.attach( stepPin, dirPin );
  stepper.setSpeedSteps( 1000, 20 ); // sets Speed and ramplength
  stepper.attachEnable( enPin, 100, LOW ); // Disable after 100ms. enabled is LOW

  pinMode(vacPin, OUTPUT); //Just added this for vac

  //set values for 2 outputs
  digitalWrite(vacPin, LOW); //just add this for vac

}

void loop() {
  analogValue = 0;

  // Assign button degrees
  if      ( analogRead(A0) > 600) {
    analogValue = (analogRead(A0));
    Serial.print("AO = ");
    Serial.println(analogValue);
    na = 0;

  }
  else if ( analogRead(A1) > 600) {
    analogValue = (analogRead(A1));
    Serial.print("A1 = ");
    Serial.println(analogValue);
    na = 45;
  }

  else if ( analogRead(A2) > 600) {
    analogValue = (analogRead(A2));
    Serial.print("A2 = ");
    Serial.println(analogValue);
    na = 225;
  }

  else if ( analogRead(A3) > 600) {   //=tool on
    analogValue = (analogRead(A3));
    Serial.print("A3 = ");
    Serial.println(analogValue);
    na = 270;

  }

  // position stepper if needed
  if ( stepper.read() != na ) stepper.write( na );

  // start vac if tool is on and stepper is in position
  if (analogValue > 600 && !stepper.moving()) {
    digitalWrite(vacPin, HIGH);
  }

  if ( vacTimer.expired() ) {
    // switch off vac if timer expires
    Serial.println( "Vac = off");
    digitalWrite(vacPin, LOW);
  }

  if (analogValue < 600 && digitalRead( vacPin ) && !vacTimer.running()) {
    // start timer to switch off vac after time
    Serial.println( " start vac run-on-time" );
    vacTimer.setTime( runOnTime );
  }

}
If you want to give it a try, the library can be installed by means of the library manager ( enter mobatools in the search field )


message:
Can internal and external pull up/pull down resisters be used together?

What happens if a sketch uses code like `pinMode(18,INPUT_PULLDOWN)` to configure internal pull-down (or pull-up) resistors, but is used in a circuit where external resistors are also present?

Are there likely to be any problems, conflicts or unexpected behaviour, e.g. if software sets a pull-down, but there is an external pull-up, or visa versa?

I am using an ESP32 (which has both internal pull-ups and pull-downs available on most GPIO pins), but I would appreciate a general answer. To clarify, I am not after the pros and cons of using external resistors (which is discussed in other questions), but the potential pitfalls of using both, especially if they are pulling in opposite directions.

body:
It is actually beneficial for the chip to have an additional pull-up or pull-down. It can help to reduce noise and to protect from ESD on the pin coming in. The internal resistors can only take a very small amount of current and an external can take some of the current in case an ESD event is happening.
The downsides of an external resistor are (not complete list):
- space requirements
- cost (although very low cost)
- slightly increased power consumption

If these are not a problem for you, an external resistor is a good idea.

Here is a [video][1] (not me), that explains the ESD-part it in more detail.

EDIT:
I just re-read your question and saw that you asked about mixing pull-up and pull-down. That you should normally not do as jksemple said.

  [1]: https://www.youtube.com/watch?v=6OxE06n6n44


body: The main risk if you use both internal and external pullup/down resistors working in opposite directions is that the input will be left at an intermediate voltage that is not guaranteed to be read as high or low. Furthermore a little noise on the input might flip a read from high to low or vice versa. There is no risk of damaging the input however


body: When you add the external resistor it will be connected to the internal pull resistor (up or down) depending on configuration. The pull resistor will either be series or parallel with the external resistor. In series it will behave as a voltage divider, in parallel it will increase the current required to cause the pin to change state. Mixing will not harm the computer as the pull resistor is designed to be connected to the opposite polarity externally. With the data sheet and the value of your resistor you can calculate the current and or voltage. You do not want to use external pull up and pull down resistors on the same pin. It may work but it is best to do the calculations to see if it will give you a viable value.


message:
Is my BMA421 locked up?

I have been trying to set up the BMA421 motion sensor in a nrf52 based smart watch, using the [datasheet][1] for the BMA423, which has the same interface. I had got the sensor working well with the original source code, but I was trying to set it up myself. It is connected via I2C, address 0x18.

I made some mistakes in my original code. I was trying to initialise the chip with a 6Kb byte stream (as in the original source), in chunks of 64 bytes. I didn't resend the register at the start of each data chunk, so ended up writing bytes to random registers.

Unfortunately, I have managed to get the sensor into an unrecoverable state - it now returns 0xFF to all reads, and doesn't respond to a soft-reset code (register 0x7E=0xB6). Even exhausting the watch battery to power cycle the chip doesn't seem to help.

I have found someone with a similar issue on the [Borsch Sensortec forum][2], so I am hoping that a complete battery discharge works.

Does anyone have any other suggestions?

  [1]: https://datasheet.lcsc.com/szlcsc/Bosch-Sensortec-BMA423_C189517.pdf
  [2]: https://community.bosch-sensortec.com/t5/MEMS-sensors-forum/BMA423-lockup/td-p/8927

body: The BMA421 was not locked. An erroneous write to the wrong register had switched it to the (non-existant) SPI interface. The solution was to power cycle the sensor.


message:
How to make ultrasonic and light sensors detect whether a person moving in or out

I am trying to make a circuit that will be used for turning on a light whenever there are 1 or more people in a room. I need to add to a variable counter when someone enters and subtract when someone leaves. However, I do not know how to use the ultrasonic sensor for this purpose. What can I do?

body:
See [this][1] tutorial on the Arduino Projecthub, that project was already made. [Here][2] is a tutorial how to use a Ultrasonic sensor.

  [1]: https://create.arduino.cc/projecthub/ryanchan/room-occupancy-counter-3b3ffa?ref=part&ref_id=10308&offset=2
  [2]: https://howtomechatronics.com/tutorials/arduino/ultrasonic-sensor-hc-sr04/


message:
ESP8266 Arduino Json object array deserialisation into struct

I'm trying to de serialize an array of JSON objects into a struct.
Following the instructions given by the Arduino JSON assistant, I managed to produce this helper function:

    void JsonPreprocessor(const char* buf)
    {
      StaticJsonDocument<96> filter;

      JsonObject filter_ResponseData_Metros_0 = filter["ResponseData"]["Metros"].createNestedObject();
      filter_ResponseData_Metros_0["Destination"] = true;
      filter_ResponseData_Metros_0["ExpectedDateTime"] = true;
      filter_ResponseData_Metros_0["Deviations"] = true;

      StaticJsonDocument<512> doc;

      DeserializationError error = deserializeJson(doc, buf, DeserializationOption::Filter(filter));

      if (error) {
        Serial.print(F("deserializeJson() failed: "));
        Serial.println(error.f_str());
        return;
      }

      JsonArray ResponseData_Metros = doc["ResponseData"]["Metros"];
      for (int i = 0; i < MAX_ELEMENTS; i++)
      {
        strcpy(dep_arr[i].destination, ResponseData_Metros[i]["Destination"]);
        strcpy(dep_arr[i].destination, ResponseData_Metros[i]["ExpectedDateTime"]);
      }
    }
The function writes into an array of structs declared like this:

    struct Departure {
       char* destination;
       char* departure;
       int  deviation;
    } depart;

    struct Departure dep_arr[MAX_ELEMENTS];
And the JSON passed as a constant character array to the preprocessor function. Uploading and running this function keeps crashing my ESP8266 without any debug output. Without posting the whole json object, which is long enough as is without the filters, My object array in JSON looks similar to this after filtering:

    {
      "ResponseData": {
        "Metros": [
          {
            "Destination": "Destination_1",
            "ExpectedDateTime": "2021-04-29T05:15:30",
            "Deviations": 1
          },
          {
            "Destination": "Destination_2",
            "ExpectedDateTime": "2021-04-29T05:21:30"
          },
          {
            "Destination": "Destination_2",
            "ExpectedDateTime": "2021-04-29T05:30:30"
          },
          {
            "Destination": "Destination_1",
            "ExpectedDateTime": "2021-04-29T05:36:30"
          },
          etc...
        ]
      }
    }
In my test code I've defined my MAX_ELEMENTS macro to be 3.

I'm at a complete loss due to not having any debug output. I'm using ArduinoJson6 and my code is written and compiled on Arduino IDE 2.0.0-beta.5

body:
No memory is allocated for the strings.
You should declare your struct like so:

```c++
struct Departure {
   char destination[32];
   char departure[32];
   int  deviation;
} depart;
```

This assumes the max length for both strings is 31 characters.

Then, pass the max size to `strlcpy()`:

```c++
strlcpy(dep_arr[i].destination, ResponseData_Metros[i]["Destination"], 32);
strlcpy(dep_arr[i].destination, ResponseData_Metros[i]["ExpectedDateTime"], 32);
```

If your strings are **very** long, you can use a `String` instead of `char[]`.

See the example [JsonConfigFile.ino](https://arduinojson.org/v6/example/config/), it shows all of this.


message:
How to set 60 min beeper?

I am trying to make a device that will register latency and number of shocks for passive avoidance behavior in drosophila. My device has two buttons green and red. I press green when I put a fruit fly into the test tube. When drosophila enters the shock compartment I press the red button to give electric shock through Grass stimulator. My Arduino registers latencies or elapsed time from pressing green button and subsequent presses red button and the number of shocks (presses of the red button). This part works just fine, however, I want to have a 60 sec beeper as the test runs only 1 min. This part does not work. The beeper counts 60 seconds from the starting of the device,  not from the press of the green button.  I am not sure what I am doing wrong.

Here is the code:
```

#include <LiquidCrystal.h>

/*
  Super-basic stopwatch using millis();
*/

unsigned long start, finished, elapsed;
unsigned long startTime;
unsigned long endTime;
unsigned long duration;
byte timerRunning;
int switchPin = 3;              // switch is connected to pin 3
int val;                        // variable for reading the pin status
int buttonState;                // variable to hold the button state
int buttonPresses = 0;          // how many times the button has been pressed
const int buz = 13;
unsigned long delayStart = 0; // the time the delay started
//bool timerRunning = false; // true if still waiting for delay to finish
// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd (9, 8, 7, 6, 5, 4);

void setup()
{
  lcd.begin(16, 2);
  //lcd.setCursor (0,0);
  //lcd.print("resetting");
  lcd.setCursor (3,1);
  lcd.print("resseting");
  delay(3000);
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("Latency= ");
lcd.setCursor (0,1);
lcd.print ("Shocks= ");
  Serial.begin(9600);
  pinMode(2, INPUT); // start button
  pinMode (2, INPUT_PULLUP);
  pinMode (buz,OUTPUT);
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  digitalWrite(buz, LOW); // turn buz off
  delayStart = millis();   // start delay
  //delayRunning = true; // not finished yet
  buttonState = digitalRead(switchPin);   // read the initial state
  Serial.println("Press 'Green' for Start/Reset, 'Red' for Shocks");
}

void displayResult()
{
  float h,m,s,ms;
  unsigned long over;
  elapsed=finished-start;
  h=int(elapsed/3600000);
  over=elapsed600000;
  m=int(over/60000);
  over=over`000;
  s=int(over/1000);
  ms=over00;
  Serial.print("Elapsed time: ");
  Serial.println(elapsed);
  Serial.print("Latency: ");
  Serial.print(m,0);
  Serial.print("m ");
  Serial.print(s,0);
  Serial.print("s ");
  Serial.print(ms,0);
  Serial.println("ms");
  Serial.print("Shocks: ");
  Serial.print(buttonPresses);
  Serial.println(" time(s)");
  lcd.setCursor (8,0);
  lcd.print(m,0);
  lcd.print("m");
  lcd.print(s,0);
  lcd.print("s");
  lcd.print(ms,0);
  lcd.setCursor (7,1);
  lcd.print(buttonPresses);

}

void loop()

    {float h,m,s,ms;

  if (digitalRead(2) == HIGH);{ // button pressed & timer not running already
  start=millis();
  lcd.setCursor (7,1);
  lcd.print("           ");
  buttonPresses=0;
  lcd.print(buttonPresses);
    Serial.println("Started");
    lcd.setCursor (8,0);
    lcd.print("           ");
    lcd.print("Start...");
  lcd.print(buttonPresses);
  lcd.setCursor (8,0);
    lcd.noBlink();

  delay(300);

  // Turn on the blinking cursor:

  lcd.blink();
    delay(200); // for debounce

  }

  if (digitalRead(3)==HIGH)
  { lcd.noBlink();
  lcd.setCursor (9,0);
   lcd.print("        ");
    finished=millis();
    delay(200); // for debounce
    buttonPresses++;
    displayResult();
    delay(200);}

    if (timerRunning && ((millis() - delayStart) >= 60000)) {
    //timerRunning = false; // // prevent this code being run more then once
    digitalWrite(buz, HIGH); // turn buz on
   // tone(buz, 1000); // Send 1KHz sound signal...
  delay(1000);        // ...for 1 sec
  noTone(buz);     // Stop sound...
  delay(1000);        // ...for 1sec
    Serial.println("Turned buz on");
    lcd.setCursor (10,1);
    lcd.print("1min");
  }}

```

body:
The best place to start, is with the `BlinkWithoutDelay` example in the IDE.

Once you master that concept, you may be tempted to start several different timers. With enough timers, your code will start to look like a bowl of spaghetti.

Next, you could build a generic function which would help to reduce the "spaghetti code".

I would favour an OOP approach.

```
// Sketch uses 910 bytes (2%) of program storage space.
// Global variables use 18 bytes (0%) of dynamic memory.
// Arduino Uno, IDE 1.8.9
class MillisTimer{

  private:

    unsigned long m_timeInMilliSeconds;
    unsigned long m_previousMillis;
    byte m_timerActive;

  public:

    MillisTimer(unsigned long timeInMilliSeconds):
      m_timeInMilliSeconds(timeInMilliSeconds){
      m_timerActive = 0;
      m_previousMillis = 0;
    }

    bool Update(){
      if(m_timerActive && (millis() - m_previousMillis >= m_timeInMilliSeconds)){
        m_previousMillis += m_timeInMilliSeconds;
        return 1;
      }
      else{
        return 0;
      }
    }

    void Start(){
      m_timerActive = 1;
    }

    void Stop(){
      m_timerActive = 0;
    }

    void ReStart(){
      m_timerActive = 1;
      m_previousMillis = millis();
    }

};

// Make a copy of the object to work with.
MillisTimer SixtySecondTimer(60000);

void setup(){

  // Call this function from a button click
  // to start the 60 second timer.
  SixtySecondTimer.Start();

  // Timer complete indicator.
  pinMode(LED_BUILTIN, OUTPUT);

}

void loop(){

  // Call the update function as fast as possible.
  if(SixtySecondTimer.Update()){
    digitalWrite(LED_BUILTIN, HIGH);
    SixtySecondTimer.Stop();
  }

}

```


message:
Brushless Motor "twitches" on its own when connected to battery

I've been trying to make a Bluetooth slider app that can control the spin speed of a brushless motor. The transmitter I am using is Arduino Mega. **The problem I'm having is that my motor will start twitching at very random times even though my Arduino code specifies `ESC.write(0)`**, meaning the ESC should remain completely still.

Furthermore, I've noticed that the twitching begins the exact moment I connect my HM10 Bluetooth module to the Arduino. The motor is still able to be controlled by the slider on my app, however, even when the slider is set at zero, the motor turns on its own! I will attach a video to the problem in [this link][1].

A couple of things I've noticed that may be of interest: when the ESC bullet connectors touch each other, there are audible sparks as well as [burn holes][2].

Here is my arduino code
```cpp

/*
   -- New project --

   This source code of graphical user interface
   has been generated automatically by RemoteXY editor.
   To compile this code using RemoteXY library 2.4.3 or later version
   download by link http://remotexy.com/en/library/
   To connect using RemoteXY mobile app by link http://remotexy.com/en/download/
     - for ANDROID 4.7.12 or later version;
     - for iOS 1.4.7 or later version;

   This source code is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
*/

//////////////////////////////////////////////
//        RemoteXY include library          //
//////////////////////////////////////////////

// RemoteXY select connection mode and include library
#define REMOTEXY_MODE__SOFTSERIAL
#include <SoftwareSerial.h>

#include <RemoteXY.h>

#include <Servo.h>

Servo ESC; //create servo object

// RemoteXY connection settings
#define REMOTEXY_SERIAL_RX 10
#define REMOTEXY_SERIAL_TX 11
#define REMOTEXY_SERIAL_SPEED 9600

// RemoteXY configurate
#pragma pack(push, 1)
uint8_t RemoteXY_CONF[] =
  { 255,2,0,0,0,60,0,11,13,1,
  4,0,23,16,17,64,2,26,2,0,
  31,5,22,11,2,26,31,31,79,78,
  0,79,70,70,0,129,0,5,7,18,
  6,17,76,69,68,0,129,0,15,85,
  37,6,17,83,101,114,105,97,108,32,
  111,117,116,112,117,116,0 };

// this structure defines all the variables and events of your control interface
struct {

    // input variables
  int8_t slider_1; // =0..100 slider position
  uint8_t switch_1; // =1 if switch ON and =0 if OFF

    // other variable
  uint8_t connect_flag;  // =1 if wire connected, else =0

} RemoteXY;
#pragma pack(pop)

/////////////////////////////////////////////
//           END RemoteXY include          //
/////////////////////////////////////////////

int power = 8;
int ledPin = 2;

void setup()
{
  RemoteXY_Init ();

  digitalWrite(LED_BUILTIN, HIGH);
  // TODO you setup code

  pinMode (LED_BUILTIN, OUTPUT);
  pinMode (power, OUTPUT);
  pinMode (ledPin, OUTPUT);
  //pinMode (7, OUTPUT);
  //int ledMapping;

  ESC.attach(6, 1000, 2000); //attach ESC to output from pin 6

  Serial.begin(9600);
}

void loop()
{
  RemoteXY_Handler ();

  //Serial.println(RemoteXY.slider_1);
  digitalWrite(power, HIGH); //supply power to Bluetooth module through pin 8
  //digitalWrite(7, HIGH);
  int ledMapping = map(RemoteXY.slider_1, 0, 100, 0, 255);
  //Serial.println(ledMapping);
  analogWrite(ledPin, ledMapping);

  int spinMapping = map(RemoteXY.slider_1, 0, 100, 0, 180); //map the slider to the servo
  if (RemoteXY.switch_1 == 1){
  ESC.write(spinMapping); //write to the ESC the value of mapped slider
  }
  else if (RemoteXY.switch_1 == 0){
  ESC.write(0);
  }
  Serial.println(spinMapping);

  if(RemoteXY.switch_1 == 1){
  digitalWrite(LED_BUILTIN, HIGH);
  }
  else if (RemoteXY.switch_1 == 0){
   digitalWrite(LED_BUILTIN, LOW);
  }

  // TODO you loop code
  // use the RemoteXY structure for data transfer
  // do not call delay()

}
```
But I don't think it is the problem. The reason is because even though I have ESC.write(0) when the LED switch is off, the ESC still turns (as is apparent in the video) randomly and twitches.

Any help would be greatly appreciated. I am trying to use this as a prototype for an eletric skateboard, but obivously if the motor is turning on its own even when it should be stopped, it is very dangerous to use.

  [1]: https://drive.google.com/file/d/1NwVl3F15rTog_EPCxPceJfow1yBoHfq2/view?usp=sharing
  [2]: https://drive.google.com/file/d/1dyn3_VLeubOUxQb4ZejbKco4c8cEg81V/view?usp=sharing
  [3]: https://docs.google.com/document/d/1GsYKApxfY5csRA0qH1scYx3iGR-bePbQzn_PYm0e6NA/edit?usp=sharing

body: try detaching the ESC instead of ESC.write(0)


message:
Arduino UNO With On / Off Module Switch + Battery Advice

*So I have the following connected and the programming works fine when connect by USB*

**The Parts**
 - 1 Arduino UNO
 - 1 Laser Module (KEYS)
 - 1 Rocker Switch Module (Standard 3 PIN)
 - 2 Variation Motors (KEYS)
 - 1 Speaker Module (BIG SPEAKER MODULE)
 - 2 Push Button Modules (Standard 3 PIN)
 - 1 SD Card Reader Module (Generic)
 - 1 3V 1800 amh Battery

**The Problem 1**
*I want to make an On/Off Switch but it doesn't work.*

Battery Powers The Arduino Like This: (WORKS)

https://postimg.cc/JHmTwFKc

Battery Powers The Arduino Like This: (NOT WORKING)

https://postimg.cc/V0RKzFVy

PROBLEM 1: Why doesn't this work when it does for the Nano I have here:

https://postimg.cc/SnXHfwPJ

*Secondly Here are some pictures of the setup I have*

Battery - Rocker

https://postimg.cc/KK6qfjMW

Rocker - Arduino

https://postimg.cc/hXH6y2FM

https://postimg.cc/4HJrvnCg

Wide View Of Project

https://postimg.cc/3WY5Qfkc

**The Problem 2**
*I need advice on what size battery to use the project for 1-2 hours I think I need (5v,7v,9v) but would like some help with which would be best suited or any suggestions you have*

**What I think it is but need help**
 1. The Wiring is wrong (but I have tested it all and its working fine)
 2. The Rocker Module is passing 3V to the UNO (Not enough Power)
 3. The Battery is not powerful enough (I need a bigger battery)
 4. NOOB Problems as its my first project

**What I need help with**
 1. What battery to use?
 2. Making the On/Off switch work

Thanks for the HELP!!!

**BONUS**
Here is the code used:

        #include <pcmConfig.h>
        #include <pcmRF.h>
        #include <TMRpcm.h>

        #include <SPI.h>
        #include <SD.h>

        //SD card pin
        #define SD_ChipSelectPin 10
        //soundplayer object
        TMRpcm tmrpcm;

        int led = 13;
        //pin numbers
        int buttonpin = 3;
        int lazerpin = 4;
        int buttonpin2 = 5;
        int motorPin = 6;
        int motorPin2 = 7;

        //other values
        int t = 0;
        int val;
        int val2;
        int ammoUsed = 0;
        int prestate = 0;
        int prestate2 = 1;
        int canReload = 0;

        void setup()
        {
          //pin modes
          pinMode(led, OUTPUT);
          pinMode(lazerpin, OUTPUT);
          pinMode(buttonpin, INPUT);
          pinMode(buttonpin2, INPUT);
          pinMode(motorPin, OUTPUT);
          pinMode(motorPin2, OUTPUT);

          Serial.begin(9600);
          if (!SD.begin(SD_ChipSelectPin))
          {
            return;
          }
          else {
            //setup sound
            tmrpcm.speakerPin = 9;
            tmrpcm.quality(1);
            tmrpcm.setVolume(5);
            //play setup sound (user knows the gun is ready)
            playSound(0);
            tmrpcm.disable();
            tmrpcm.stopPlayback();
          }
        }

        //method to call sounds depending on the input
        void playSound(int t) {
          tmrpcm.disable();
          tmrpcm.stopPlayback();

          if (t == 0) {
            tmrpcm.setVolume(5);
            tmrpcm.play("0.wav");
            delay(2980); //time of clip
          }
          else if (t == 1) {
            tmrpcm.setVolume(6);
            tmrpcm.play("1.wav");
            delay(660); //time of clip
          }
          else if (t == 2) {
            tmrpcm.setVolume(5);
            tmrpcm.play("2.wav");
            delay(950); //time of clip
          }
          else if (t == 3) {
            tmrpcm.setVolume(6);
            tmrpcm.play("3.wav");
            delay(620); //time of clip
          }
          else if (t == 4) {
            tmrpcm.setVolume(5);
            tmrpcm.play("4.wav");
            delay(660); //time of clip
          }

          tmrpcm.disable();
          tmrpcm.stopPlayback();

          return;
        }
        void loop()
        {
          val = digitalRead(buttonpin); // check the state of the button
          val2 = digitalRead(buttonpin2); // check the state of the button

          //reload gun
          if (val2 == HIGH && prestate2 == 0 && canReload == 1)
          {
            //reset ammo and play sound with vibrate
            ammoUsed = 0;
            canReload = 0;
            digitalWrite(motorPin, HIGH); //vibrate
            digitalWrite(motorPin2, HIGH); //vibrate
            playSound(3);
            digitalWrite(motorPin, LOW);  //stop vibrating
            digitalWrite(motorPin2, LOW);  //stop vibrating
            prestate2 = 1;

          }
          else if (val2 == LOW)
          {
            //reload let go
            prestate2 = 0;
          }

          //Shooting the gun 1-4 normal. 5 is louder and longer.
          if (val == LOW) // if button is pressed, turn LED on
          {
            digitalWrite(lazerpin, LOW);
            digitalWrite(led, LOW);
            prestate = 0;
          }
          else if (val == HIGH && prestate == 0)
          {
            if (ammoUsed != 5)
            {
              ammoUsed ++;

              if (ammoUsed > 0) {
                canReload = 1;
              }
              else {
                canReload = 0;
              }

              //turn on lazer and virbate
              digitalWrite(lazerpin, HIGH);
              digitalWrite(led, HIGH);
              digitalWrite(motorPin, HIGH); //vibrate
              digitalWrite(motorPin2, HIGH); //vibrate

              //play sound
              if (ammoUsed == 5) {
                playSound(2);
              }
              else {
                playSound(1);
              }
              //after sound lazer and vibrate turn off
              digitalWrite(motorPin, LOW);  //stop vibrating
              digitalWrite(motorPin2, LOW);  //stop vibrating
              digitalWrite(lazerpin, LOW);
              digitalWrite(led, LOW);

              prestate = 1;
            }
            else {
              //no ammo just vibrate and play sound with no lazer
              digitalWrite(motorPin, HIGH); //vibrate
              digitalWrite(motorPin2, HIGH); //vibrate
              playSound(4);
              canReload = 1;
              digitalWrite(motorPin, LOW);  //stop vibrating
              digitalWrite(motorPin2, LOW);  //stop vibrating
              prestate = 1;

            }
          }

        }

body:
So here is the deal (I Kinda Solved It) so I took apart a 9V battery pack with a flip switch in it..... soldered some wired to it and now it works perfectly...... haha

but I would still like the know the reason why the rocker switch module doesn't work.

the only thing I can think of is the Voltage or Amp passed from the Switch Module isn't enough to power the board (as I tried 3 different rocker switches and all acted the same)

Thanks for the help


message:
Multiple variable shared between threads?

I got 4 threads running on ESP32 (dual core):
- 1 thread running on 1st core which is related to the WiFi.
- 1 thread running on 2nd core which is related to the touchscreen.
- 1 thread running on 2nd core which is related to the display.
- 1 thread running on 2nd core which is related to the sensors.

Some of the threads execute almost instantly, while for instance the one handling the sensors can take a few seconds per interaction, and no blocking should occur meanwhile for the rest of the threads.

Anyway, with the growing of the program, a lot of variables started to be involved in data transfers between the cores, and since the whole thing is about to be redone, I have the following questions, to clear the things up for myself, since I found quite a lot of confusing, even contradictory information in examples and explanations on the internet:

 - Is the "**volatile**" keyword really sufficient for exchange of data between threads (no ISR)?
 - Should "**volatile**" always be between "**noInterrupts**()" and "**interrupts**()", even when there is no ISR function?
 - What approaches should be used when exchanging a lot of variables between the threads (currently about 40 variables, but the number will probably grow)?
 - Is **xQueueSend / xQueueReceive** blocking in case it is put all around the threads with different variables?

body:
> Is the "volatile" keyword really sufficient for exchange of data
> between threads (no ISR)?

No - "volatile" just tells the compiler that the variable may change value due to something other than the immediate code being generated and informs the code-generator not to rely on the value remaining static when it would otherwise expect so. When copying the value to a register for instance, it would normally expect that register value to continue to represent the value of the variable in memory but if the variable is volatile, that assumption doesn't hold. This would be used to indicate that an ISR might change it at any time; that the variable is an input register and may be changed from the outside at any time; or that another thread may change it, again, at any time (assuming pre-emptive multi-threading or multi-tasking).

    Should "volatile" always be between "noInterrupts()" and "interrupts()", even when there is no ISR function?

No - volatile just describes an attribute about the variable over time

> What approaches should be used when exchanging a lot of variables between the threads

Use a semaphore here. A thread that wants access to one of - or the collection of - shared variables asks for the semaphore. The RTOS either returns it immediately, or (because another thread already holds it) suspends the task until it becomes available, and returns it then. The thread holding the semaphore may access the variables (or whatever shared resource this semaphore controls), then returns the semaphore on completion. Semaphores are usually built in to the RTOS.

(As I'm not familiar with your particular RTOS, I'll leave your fourth question for someone who is).


message:
Sending multiple data with SPI interface monitored by an Osciloscope

I have multiple 32-bit data stored in an array, and I want to sequentially send them by SPI interface. I want to check that my code is correctly sending data by SPI interface, so I upload the code and connect my Linkit7697 to an oscilloscope.
The expecting waveform is like this:
[![enter image description here][1]][1]

But it turns out to be like this:
[![enter image description here][2]][2]

It seems that all data are composited together in every 32 bits.
What's wrong? Any idea?

Here is my code:
```
#include <SPI.h>

#define SPI_MOSI (11)
#define SPI_MISO (12)
#define SPI_CS (10)
#define SPI_CLK (13)

uint32_t test[]={
  0xF0000000,   //11110000000000000000000000000000
  0x00F00000,   //00000000111100000000000000000000
  0x0000F000,   //00000000000000001111000000000000
  0x0000000F    //00000000000000000000000000001111
  };

int i = 0;

void setup() {
  digitalWrite(SPI_CS,HIGH); //Set slave select to high, linkit7697 is Master
  SPI.begin();
  SPI.beginTransaction(SPISettings(20000000,MSBFIRST,SPI_MODE0 ));

}

void loop() {

  for (i = 0; i < 4; i++){
    digitalWrite(SPI_CS,LOW);
    SPI.transfer(&test[i],4);
    digitalWrite(SPI_CS, HIGH);

  }

}
```

  [1]: https://i.stack.imgur.com/wm8SY.png
  [2]: https://i.stack.imgur.com/U3uJU.jpg

body:
>     SPI.transfer(&test[i],4);

The `SPI.transfer()` transmit one byte each time and therefore expecting a pointer to a byte (i.e. uint8_t) while you are passing in an address of an `uint32_t`. What you need to do is to cast the address of `uint32_t` into a pointer of `uint8_t` before passing it into the `SPI.transfer`.

```
uint8_t *ptr = (uint8_t *) &test;

SPI.beginTransaction(SPISettings(20000000,MSBFIRST,SPI_MODE0 ));
digitalWrite(SPI_CS,LOW);
for (i = 0; i < sizeof(test); i++) {
  SPI.transfer(*ptr++, 4);
}
digitalWrite(SPI_CS, HIGH);
SPI.endTransaction();
```

Please also note that Arduino is a little endian machine, so if you have a data as `0x41424344`, the first byte get transmitted will be `0x44`.

One more thing, it is always good to call `SPI.endTransaction()`, it free up the SPI bus to allow other SPI devices to use the data bus.


message:
Request for help condensing code and saving memory

I'm building a final project for a class that involves playing an audio file of a wave shield every time I scan an amiibo with an RFID scanner. I'm a pretty new programmer, so I'm not very familiar with the how to best reduce DRAM usage. As such, I got the following error when I attempted to run my most recent iteration of code:

> Global variables use 2801 bytes (136%) of dynamic memory, leaving -753 bytes for local variables. Maximum is 2048 bytes.

Here is my code:

    ////// WAVE SHIELD HEADERS //////
    #include <FatReader.h>
    #include <SdReader.h>
    #include <avr/pgmspace.h>
    #include "WaveUtil.h"
    #include "WaveHC.h"
    /////////////////////////////////

    /////// LCD HEADERS /////////////
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

    //////////////////////////////////////////

    ////////// RFID HEADERS /////////////////
    #include <SPI.h>
    #include <Adafruit_PN532.h>

    #define PN532_IRQ   (6)
    #define PN532_RESET (3)  // Not connected by default on the NFC Shield

    Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

    /////// various declarations /////////
    uint8_t GLOBALUID[7];

    //////////////////////////// WAVE SHIELD PORTION OF CODE ///////////////////////////////////

    SdReader card;    // This object holds the information for the card
    FatVolume vol;    // This holds the information for the partition on the card
    FatReader root;   // This holds the information for the filesystem on the card
    FatReader f;      // This holds the information for the file we're play

    WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

    #define DEBOUNCE 100  // button debouncer

    // this handy function will return the number of bytes currently free in RAM, great for debugging!
    int freeRam(void)
    {
      extern int  __bss_end;
      extern int  *__brkval;
      int free_memory;
      if((int)__brkval == 0) {
        free_memory = ((int)&free_memory) - ((int)&__bss_end);
      }
      else {
        free_memory = ((int)&free_memory) - ((int)__brkval);
      }
      return free_memory;
    }

    void sdErrorCheck(void)
    {
      if (!card.errorCode()) return;
      putstring("\n\rSD I/O error: ");
      Serial.print(card.errorCode(), HEX);
      putstring(", ");
      Serial.println(card.errorData(), HEX);
      while(1);
    }

    /////// MAIN SETUP /////////

    void setup() {
      // set up serial port
      Serial.begin(115200);

      // Set the output pins for the DAC control in the wave shield.
      pinMode(2, OUTPUT);
      pinMode(3, OUTPUT);
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);

      // Set button outputs
      pinMode(A0, INPUT);
      pinMode(A1, INPUT);

      // Set random seed for picking amiibo
      randomSeed(analogRead(A2));

      // initialize lcd
      lcd.init();
      lcd.init();
      lcd.backlight();
      lcd.setCursor(0,0);

       if (!card.init()) {
        putstring_nl("Card init. failed!");
        sdErrorCheck();
        while(1);
      }

      // enable optimize read - some cards may timeout. Disable if you're having problems
      card.partialBlockRead(true);

    // look for a FAT partition
      uint8_t part;
      for (part = 0; part < 5; part++) {
        if (vol.init(card, part))
          break;
      }
      if (part == 5) {
        putstring_nl("No valid FAT partition!");
        sdErrorCheck();
        while(1);
      }

      // tell the user about what was found
      putstring("Using partition ");
      Serial.print(part, DEC);
      putstring(", type is FAT");
      Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?

      // Try to open the root directory
      if (!root.openRoot(vol)) {
        putstring_nl("Can't open root dir!");
        while(1);
      }
    }
    //////////// END OF WAVE SHIELD ///////////////

    ////////////// FUNCTION FOR SELECTING AUDIO FILES ////////////
    void playSoundClip(){

      char charUID[7];

      for(int i = 0; i < 7; i++)
        charUID[i] = GLOBALUID[i];

      Serial.println();

    /*
          {"Mario",                   { 4, 79, 119, 42, 55, 60, 128 },"MARIO"},     //0
          {"Meta Knight",             { 4, 243, 209, 58, 117, 76, 128},"MK"},       //1
          {"Inkling",                 { 4, 84, 47, 218, 87, 73, 128 },"INK"},       //2
          {"Donkey Kong",             { 4, 244, 122, 98, 249, 61, 128 },"DK"},      //3
          {"Lucas",                   { 4, 7, 52, 202, 178, 73, 129 },"LUCAS"},     //4
          {"Duck Hunt",               { 4, 40, 173, 146, 84, 73, 128 },"DUCKH"},    //5
          {"Ocarina of Time Link",    { 4 163 57 114 221 76 128 },"OOTL"},          //6
          {"Breath of The Wild Link", ( 4 133 61 74 120 76 128 },"BOTWL"},          //7
          {"8-bit Link",              { 4 192 150 130 221 76 128 },"8BITL"},        //8
          {"Toon Link",               { 4, 89, 88, 226, 161, 62, 128 },"TOONL"},    //9
          {"Mr. Game and Watch",      { 4, 134, 32, 154, 85, 73, 128 },"GANDW"},    //10
          {"Falco",                   { 4, 23, 139, 178, 17, 74, 129 },"FALCO"},    //11
          {"King Dedede",             { 4, 108, 188, 242, 232, 73, 128 },"DEDEDE"}, //12
          {"Mewtwo",                  { 4, 241, 126, 202, 87, 73, 128 },"MEWTWO"},  //13
          {"Captain Falcon",          { 4, 11, 204, 178, 124, 72, 129 },"CAPF"},    //14
          {"ROB",                     { 4, 40, 208, 50, 3, 73, 128 },"ROB"},        //15
          {"PAC-MAN",                 { 4, 45, 26, 2, 114, 64, 129 },"PACMAN"},     //16
          {"Cloud",                   { 4, 107, 128, 26, 114, 64, 128 },"CLOUD"},   //17
          {"Ness",                    { 4, 107, 128, 26, 114, 64, 128 },"NESS"},    //18
          {"Ryu",                     { 4, 109, 252, 234, 33, 75, 128 },"RYU"}      //19
    */

      uint8_t amiiboNo = 0;

      if(strcmp(charUID,"479119425560128"))
        amiiboNo = 0; //Mario
      else if(strcmp(charUID,"42432095811776128"))
        amiiboNo = 1; //Meta Knight
      else if(strcmp(charUID,"484472188773128"))
        amiiboNo = 2; //Inkling
      else if(strcmp(charUID,"42441229824961128"))
        amiiboNo = 3;// Donkey Kong
      else if(strcmp(charUID,"475220217873129"))
        amiiboNo = 4;// Lucas
      else if(strcmp(charUID,"4401731468473128"))
        amiiboNo = 5;// Duck Hunt
      else if(strcmp(charUID,"41635711422176128"))
        amiiboNo = 6;// Ocarina of Time Link
      else if(strcmp(charUID,"4133617412076128"))
        amiiboNo = 7;// Breath of The Wild Link
      else if(strcmp(charUID,"419215013022176128"))
        amiiboNo = 8;// 8-bit link
      else if(strcmp(charUID,"4898822616162128"))
        amiiboNo = 9;// toon link
      else if(strcmp(charUID,"4134321548573128"))
        amiiboNo = 10;// Mr. Game and Watch
      else if(strcmp(charUID,"4231391781774129"))
        amiiboNo = 11;// Falco
      else if(strcmp(charUID,"410818824223273128"))
        amiiboNo = 12;// king dedede
      else if(strcmp(charUID,"42411262028773128"))
        amiiboNo = 13;// Mewtwo
      else if(strcmp(charUID,"41120417812472129"))
        amiiboNo = 14;// Captain Falcon
      else if(strcmp(charUID,"44020850373128"))
        amiiboNo = 15;// ROB
      else if(strcmp(charUID,"44526211464129"))
        amiiboNo = 16;// Pacman
      else if(strcmp(charUID,"424913721823376128"))
        amiiboNo = 17;// Cloud
      else if(strcmp(charUID,"41071282611464128"))
        amiiboNo = 18;// Ness
      else if(strcmp(charUID,"41092522343375128"))
        amiiboNo = 19;// Ryu

      Serial.println(amiiboNo);

      uint8_t clipNo = random(3);

      switch(amiiboNo){
        case 0:
          if(clipNo == 0)
            playComplete("MARIO01.WAV");
          else if(clipNo == 1)
            playComplete("MARIO02.WAV");
          else if(clipNo == 2)
            playComplete("MARIO03.WAV");
          break;
        case 1:
          if(clipNo == 0)
            playComplete("MK01.WAV");
          else if(clipNo == 1)
            playComplete("MK02.WAV");
          else if(clipNo == 2)
            playComplete("MK03.WAV");
          break;
        case 2:
          if(clipNo == 0)
            playComplete("INK01.WAV");
          else if(clipNo == 1)
            playComplete("INK02.WAV");
          else if(clipNo == 2)
            playComplete("INK03.WAV");
           break;
        case 3:
          if(clipNo == 0)
            playComplete("DK01.WAV");
          else if(clipNo == 1)
            playComplete("DK02.WAV");
          else if(clipNo == 2)
            playComplete("DK03.WAV");
           break;
        case 4:
          if(clipNo == 0)
            playComplete("LUCAS01.WAV");
          else if(clipNo == 1)
            playComplete("LUCAS02.WAV");
          else if(clipNo == 2)
            playComplete("LUCAS03.WAV");
           break;
        case 5:
          if(clipNo == 0)
            playComplete("DUCKH01.WAV");
          else if(clipNo == 1)
            playComplete("DUCKH02.WAV");
          else if(clipNo == 2)
            playComplete("DUCKH03.WAV");
           break;
        case 6:
          if(clipNo == 0)
            playComplete("OOT01.WAV");
          else if(clipNo == 1)
            playComplete("OOT02.WAV");
          else if(clipNo == 2)
            playComplete("OOT03.WAV");
           break;
        case 7:
          if(clipNo == 0)
            playComplete("BOTWL01.WAV");
          else if(clipNo == 1)
            playComplete("BOTWL02.WAV");
          else if(clipNo == 2)
            playComplete("BOTWL03.WAV");
           break;
        case 8:
          if(clipNo == 0)
            playComplete("8BITL01.WAV");
          else if(clipNo == 1)
            playComplete("8BITL02.WAV");
          else if(clipNo == 2)
            playComplete("8BITL03.WAV");
           break;
        case 9:
          if(clipNo == 0)
            playComplete("TOONL01.WAV");
          else if(clipNo == 1)
            playComplete("TOONL02.WAV");
          else if(clipNo == 2)
            playComplete("TOONL03.WAV");
           break;
        case 10:
          if(clipNo == 0)
            playComplete("GANDW01.WAV");
          else if(clipNo == 1)
            playComplete("GANDW02.WAV");
          else if(clipNo == 2)
            playComplete("GANDW03.WAV");
           break;
        case 11:
          if(clipNo == 0)
            playComplete("FALCO01.WAV");
          else if(clipNo == 1)
            playComplete("FALCO02.WAV");
          else if(clipNo == 2)
            playComplete("FALCO03.WAV");
           break;
        case 12:
          if(clipNo == 0)
            playComplete("DEDEDE01.WAV");
          else if(clipNo == 1)
            playComplete("DEDEDE02.WAV");
          else if(clipNo == 2)
            playComplete("DEDEDE03.WAV");
           break;
        case 13:
          if(clipNo == 0)
            playComplete("MEWTWO01.WAV");
          else if(clipNo == 1)
            playComplete("MEWTWO02.WAV");
          else if(clipNo == 2)
            playComplete("MEWTWO03.WAV");
           break;
        case 14:
          if(clipNo == 0)
            playComplete("CAPF01.WAV");
          else if(clipNo == 1)
            playComplete("CAPF02.WAV");
          else if(clipNo == 2)
            playComplete("CAPF03.WAV");
           break;
        case 15:
          if(clipNo == 0)
            playComplete("ROB01.WAV");
          else if(clipNo == 1)
            playComplete("ROB02.WAV");
          else if(clipNo == 2)
            playComplete("ROB03.WAV");
           break;
        case 16:
          if(clipNo == 0)
            playComplete("PACMAN01.WAV");
          else if(clipNo == 1)
            playComplete("PACMAN02.WAV");
          else if(clipNo == 2)
            playComplete("PACMAN03.WAV");
           break;
        case 17:
          if(clipNo == 0)
            playComplete("CLOUD01.WAV");
          else if(clipNo == 1)
            playComplete("CLOUD02.WAV");
          else if(clipNo == 2)
            playComplete("CLOUD03.WAV");
           break;
        case 18:
          if(clipNo == 0)
            playComplete("NESS01.WAV");
          else if(clipNo == 1)
            playComplete("NESS02.WAV");
          else if(clipNo == 2)
            playComplete("NESS03.WAV");
           break;
        case 19:
          if(clipNo == 0)
            playComplete("RYU01.WAV");
          else if(clipNo == 1)
            playComplete("RYU02.WAV");
          else if(clipNo == 2)
            playComplete("RYU03.WAV");
           break;

        }
    }

    //////// MAIN LOOP /////////
    void loop() {

          lcd.print("Scan an");
          lcd.setCursor(0,1);
          lcd.print("amiibo!");
          delay(3000);

        uint8_t * ID{};

        waitForRFID();

        playSoundClip();

    }

    //////////////// MORE WAVE SHIELD ///////////////////////

    // Plays a full file from beginning to end with no pause.
    void playComplete(char *name) {
      // call our helper to find and play this name
      playfile(name);
      while (wave.isplaying) {
      // do nothing while its playing
      }
      // now its done playing
    }

    void playfile(char *name) {
      // see if the wave object is currently doing something
      if (wave.isplaying) {// already playing something, so stop it!
        wave.stop(); // stop it
      }
      // look in the root directory and open the file
      if (!f.open(root, name)) {
        putstring("Couldn't open file "); Serial.println(name); return;
      }
      // OK read the file and turn it into a wave object
      if (!wave.create(f)) {
        putstring_nl("Not a valid WAV"); return;
      }

      // ok time to play! start playback
      wave.play();
    }

    /////////////// END OF WAVE SHIELD //////////////////////

    //////////////// RFID FUNCTION /////////////////////////
    uint8_t* waitForRFID(){
        nfc.SAMConfig();

      Serial.println("Waiting for an amiibo ...");

      uint8_t success;
      uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
      uint8_t uidLength;
      uint8_t testuid[7];
      while(true){
        if (nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength)){

          Serial.print("Hex UID: ");
          nfc.PrintHex(uid, uidLength);
          Serial.print("Octal UID: { ");
          for(int i = 0; i < uidLength; i++){
            Serial.print(uid[i]);
            GLOBALUID[i] = uid[i];
            if (i != uidLength - 1)
              Serial.print(", ");
          }
          Serial.println(" }");

          Serial.print("GLOBALUID: ");
          for(int i = 0; i < 7; i++)
            Serial.print(GLOBALUID[i]);

          Serial.println();
          Serial.println();
        }
        return testuid;
      }

    }

    //////////////// END OF RFID FUNCTION /////////////////

My first guess for what may be taking up the most memory is the switch statement. When I uncomment that, the memory usage jumps from 90% to over 130%. I've tried other ways to get this code to work, like concatenating text, but this is the only way that seemed to work reliably, until I ran out of memory.

I'm also using a lot of libraries to help use the shields and LCD I have attached to the Uno. I couldn't get rid of those libraries without compromising the project.

Other than that, I don't know what to do. If anyone has any suggestions for condensing the code down, I'd really appreciate any advice you have to offer.

Thanks.

body: Just a SWAG try switching from a UNO to a MEGA the code should work once the decelerations are fixed. What the compiler is not telling you is how much memory is actually used. You have the Heap and Stack etc.


body:
You have a huge `switch...case` here to decide the name of the file that
should be played. This costs a lot of code space, but also data space,
because every single literal string in this portion of code gets copied
to RAM during initialization.

There is no need to spend all this cost, as the file names have been
assigned in a very regular fashion, so you can build the file name
_algorithmically_. As a general rule, whenever you find yourself
programming by copying, pasting, then applying some predictable
modifications to the copies, you are almost certainly doing something
wrong. Making repeated copies of the same thing, with predictable
changes is what computers are best for. So you have to ask yourself how
you can instruct the computer (in this case, the Arduino) to do that for
you. Do not do the computer's job yourself!

In this case, the file name is built by gluing three pieces together:

* a prefix that depends on `amiiboNo`
* a two-digit number between `"01"` and `"03"`, depending on `clipNo`
* the constant suffix `".WAV"`

The prefix cannot be computed algorithmically, so you still have to
write down all the possible prefixes. You could use a big
`switch...case` for this, but it is way more convenient to pick the
right prefix from an array indexed by `amiiboNo`:

```c++
const char *file_prefixes[] = {
    "MARIO", "MK",    "INK",    "DK",    "LUCAS", "DUCKH",  "OOT",
    "BOTWL", "8BITL", "TOONL",  "GANDW", "FALCO", "DEDEDE", "MEWTWO",
    "CAPF",  "ROB",   "PACMAN", "CLOUD", "NESS",  "RYU"
};
```

Then, you declare an array of `char` for holding the file name, and you
build that file name by putting together the three pieces listed above.
Your whole `switch...case` can then be replaced by this:

```c++
char filename[13];           // longest file name: 12 characters + NUL
char file_number[3] = "01";  // 2 digits + NUL
file_number[1] += clipNo;    // file_number: "01", "02" or "O3"
strcpy(filename, file_prefixes[amiiboNo]);
strcat(filename, file_number);
strcat(filename, ".WAV");
playComplete(filename);
```

This will already save you a lot of RAM, but probably not enough. I did
not see any obvious inefficient use of variables in your program (but I
did not look in too much detail), so we will continue to aim at literal
strings.

The problem with literal strings is the fact that they get copied from
flash to RAM during initialization, and whereas you probably have enough
flash, the RAM is in short supply. This is a problem specific to Harvard
architectures, as they have separate address spaces for code and data.
We can use some AVR-specific tricks to instruct the compiler not to
perform this copying. This makes it harder to access the data because
C++ does not natively know about address spaces. Fortunately, there are
some macros and helper functions that can make it easy in specific
cases.

The best know such helper in Arduino world is the `F()` macro. Use it
every time you `print()` or `println()` a literal string, as in:

```c++
Serial.println(F("Waiting for an amiibo ..."));
```

Next, we have to get rid of the very long list of numeric UIDs. For
this, we use the `PSTR()` macro and `strcmp_P()` function [provided by
the avr-libc][libc]. Replace every line that looks like

```c++
if (strcmp(charUID, "479119425560128"))
```

by something like

```c++
if (strcmp_P(charUID, PSTR("479119425560128")) == 0)
```

Note that the value returned by `strcmp_P()` has to be compared to `0`, as
this is what that function, just like `strcmp()`, returns in case of
equality. Thanks to timemage for noticing this issue.

Last, we could also keep all the file prefixes in flash, but this would
be trickier. For now, I suggest you apply the tricks described here and
see whether they are enough to make your program fit.

**Edit**: more on the somewhat obscure statement:
`file_number[1] += clipNo;`

In C++, a `char` is an 8-bit number. Depending on the platform, it can
be either signed (range: −128…+127) or unsigned (0…255). The name comes
from the fact that it is most often used to store the numeric value of an
ASCII character. For example, the numeric value 33 means `'!'`, 48 means
`'0'`, and 65 means `'A'`.

The definition

```c++
char file_number[3] = "01";
```

creates a 3-cell array initialized with the following content:

```text
             ┌─────┬─────┬─────┐
file_number: │  48 │  49 │   0 │
             └─────┴─────┴─────┘
```

Using the language notation for characters, the contents could also be
written as follows:

```text
             ┌─────┬─────┬─────┐
file_number: │ '0' │ '1' │ '\0'│
             └─────┴─────┴─────┘
```

The last cell with the ASCII NUL is there to inform library functions
such as `strcat()` that this is where the string of characters ends.

The statement

```c++
file_number[1] += clipNo;
```

accesses the second element of the array (array indexing starts at 0)
and increments its numeric value by the amount of `clipNo`. For example,
if `clipNo` is 1, then the value in the middle cell will be changed
from 49 (i.e. `'1`') to 50 (i.e. `'2'`). This relies on the fact that
ASCII digits have consecutive numeric values, which would also be
expected from any sane character encoding.

[libc]: https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html


body:
As a minor addendum to Edgar Bonet's excellent answer, you could simplify your code further and save even more memory by renaming your files.

In particular, instead of storing a list of character names indexed by Amiibo number and using those as the filename prefix, why not use the Amiibo numbers directly?  That is, instead of your files being named

> `MARIO01.WAV`, `MARIO02.WAV`, `MARIO03.WAV`, `MK01.WAV`, `MK02.WAV`, `MK02.WAV`, etc.

you could just name them e.g.

> `AMI01_01.WAV`, `AMI01_02.WAV`, `AMI01_03.WAV`, `AMI02_01.WAV`, `AMI02_02.WAV`, `AMI02_03.WAV`, etc.

and construct the name in your code e.g. like this:

    char filename[13];
    int len = snprintf(filename, sizeof(filename), "AMId_d.WAV", amiiboNo + 1, clipNo + 1);
    if (len < 0 || len >= sizeof(filename)) {
      // TODO: handle error or insufficient buffer size here
    }

The main advantage here is that you'll save memory by not having to store the list of character names.  The tradeoff, of course, is that your filenames will now be a lot less descriptive.

You could probably optimize this a bit more by manipulating the bytes of the filename directly like Edgar does.  But personally I'd suggest starting with the generic `snprintf` based solution and only switching to direct byte manipulation if it's still too much. At least I'd assume that the `snprintf` implementation in the standard library is probably going to be fairly well optimized for a low footprint.  Of course I could be wrong.


message:
Blink LED with different on off times just once with millis

So Im having trouble trying to figure this out. My project needs a valve to stay shut and when an event is triggered, 3 seconds into that event the valve opens for 2 seconds, then remain shut till it's triggered again. I was just treating it like an LED in the code. I was trying to code it to jump from one if-statement to the next with the appropriate delays but it doesn't work the way i thought it would. Any help would be great. Thanks

```
//the event does ventGo0 = true;

 if(((millis() - previousVenting) > offoffDuration)&&(ventGo0==true)){
        previousVenting1 = millis();
        ventGo1=true;
        ventGo0=false;
       }

     if(((millis() - previousVenting1) > onDuration)&&(ventGo1==true)){
       digitalWrite(ventPin, HIGH);
       previousVenting2 = millis();
       ventGo2=true;
       ventGo1=false;
     }

       if(((millis() - previousVenting2) > offDuration)&&(ventGo2==true)){
         digitalWrite(ventPin, LOW);
         ventGo2=false;
       }

      ```

body:
You could use two `millis()` based timers.

```lang-cpp
// Sketch uses 1066 bytes (3%) of program storage space.
// Global variables use 27 bytes (1%) of dynamic memory.
// Arduino Uno, IDE 1.8.9
class MillisTimer{

  private:

    unsigned long m_timeInMilliSeconds;
    unsigned long m_previousMillis;
    byte m_timerActive;

  public:

    MillisTimer(unsigned long timeInMilliSeconds):
      m_timeInMilliSeconds(timeInMilliSeconds){
      m_timerActive = 0;
      m_previousMillis = 0;
    }

    bool Update(){
      if(m_timerActive && (millis() - m_previousMillis >= m_timeInMilliSeconds)){
        m_previousMillis += m_timeInMilliSeconds;
        return 1;
      }
      else{
        return 0;
      }
    }

    void Start(){
      m_timerActive = 1;
    }

    void Stop(){
      m_timerActive = 0;
    }

    void ReStart(){
      m_timerActive = 1;
      m_previousMillis = millis();
    }

    byte IsActive(){
      return m_timerActive;
    }

};

// Make copies of the object to work with.
MillisTimer TwoSecondTimer(2000);
MillisTimer ThreeSecondTimer(3000);

void setup(){

  // Call this function when an event is triggered.
  ThreeSecondTimer.ReStart();

  // Timer status indicator.
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);

}

void loop(){

  // Call the update function as fast as possible.
  if(ThreeSecondTimer.Update()){
    digitalWrite(LED_BUILTIN, HIGH);
    ThreeSecondTimer.Stop();
    TwoSecondTimer.ReStart();
  }

  // Call the update function as fast as possible.
  if(TwoSecondTimer.Update() && !ThreeSecondTimer.IsActive()){
    digitalWrite(LED_BUILTIN, LOW);
    TwoSecondTimer.Stop();
  }

}
```


message:
Where can I know voltage between GND(ground) and each port of UNO R3?

Currently I'm new to arduino uno r3.

Where can I find each voltage between each port and GND(ground)?

Or can the voltage be changed?

I don't want to break my led bulbs since large difference of 2 potentials

body:
5[V] is ideal EMF(electromotive force) of arduino UNO R3.

Since I stated "**ideal**" ,the actual EMF be slightly lower than 5[V].

In this instance , EMF can be assumed as voltage between GND and port of UNO R3 as ports are connected only by a wire.


body: You can measure each one at the output of the port (where you plug a connecting-wire to the port). Measure from that wire to ground with your DVM. It should be either 0v or 5v, depending on whether the port is set LOW or HIGH. (Or it could be pulsing from 0v - 5v - 0v - ... , if it is one of the PWM ports and the port has been set to provide a PWM output.) If the pin is in INPUT mode (and not INPUT_PULLUP), you're likely to read noise picked up by the connection between the pin and the meter, as an INPUT pin will be in high-impedance mode - no voltage will be asserted by the MCU, so the connection will behave almost like an un-connected wire, e.g., an antenna.


message:
Inaccurate voltage readings on an esp32 as opposed to multimeter

I am working on detecting the amplitude of a signal coming from a guitar pickup. I am using an esp32 and an LM386 module for amplifying the signal.

I get quite stable readings with a multimeter, but the readings on the Arduino IDE show peaks and also peaks come when no signal should be there.

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

Here is a link for short videos of both the esp32 readings and the multimeter:

[https://drive.google.com/drive/folders/1gpvkN_sz627jG0TNPpUps82105EB89OF?usp=sharing][2]

Thanks!

EDIT (Adding simple code being used) :

    int ampedVoltagePin = 12;

    void setup() {
      pinMode(ampedVoltagePin, INPUT);
      Serial.begin(9600);
    }

    void loop() {
      Serial.println(analogRead(ampedVoltagePin));
      delay(100);
    }

EDIT (Adding diagram):

[![enter image description here][3]][3]

  [1]: https://i.stack.imgur.com/FKUO6.png
  [2]: https://drive.google.com/drive/folders/1gpvkN_sz627jG0TNPpUps82105EB89OF?usp=sharing
  [3]: https://i.stack.imgur.com/2bDr9.png

body:
I see multiple problems with your setup:

- You only take a measurement every 100ms. That measurement takes the voltage during a very short time span. But the lowest string on a guitar in standard tuning has 82.41Hz (E2). You are measuring at 10Hz. According to the Nyquist–Shannon sampling theorem you need to measure at at least twice the frequency of your lowest frequency to measure. Otherwise your measured data will not have any real meaning and will not represent the input wave. So you need to measure at least with 165Hz.

- The amplifier can output voltages up to it's supply voltage, so 5V. You connect the output directly to the ESP32, which is a 3.3V device. That can damage the pin, that you are using.

- Currently you are trying to measure the signal directly. But you wrote, that you want to have the amplitude. Currently you would need to calculate that in code (for example by taking the min and max value over a time range greater than one period of the lowest frequency, so at least 12ms (1/82.4Hz)). A multimeter most likely will do that in hardware with analog electronics.

- I'm not sure if it is good to connect a speaker and the ESP in parallel. As a speaker is basically an inductor moving in a magnetic field, you might get backwards voltage induced by it. That might be harmful to the ESP. Others here might know more about that.

- You connect the Arduino ground to speaker ground. But that is most likely not the same as the amplifiers ground. Most likely the amplifier drives the speaker symmetrically, so also with negative voltages in reference to the speaker ground. That can damage the ADC of the Arduino. Also it's unclear, how good that ground actually is. That pin is not meant for grounding a microcontroller. Driving a speaker is different from measuring the voltage with an Arduino, so you would need different amplifiers to do it.

I'm not an expert in the field of analog electronics, but I guess you could use a diode to get one half-wave and then feeding it into a low pass filter. The resulting voltage is relatively steady (depending on the cut-off frequency of the filter) and can then be measured by the ESP. I'm sure, that this will only give you a rough measurement of the amplitude, but enough for typical applications like amplitude visualization. For really precise measurements you most likely need to use a more complex electronics setup to work against the non-linearities of the parts (especially the diode).


body:
I managed to get accurate readings by following @chrisl's suggestion in the comment.

Instead of trying to get values at given points I am now averaging 500 values and the readings are as expected.

New code:

    int ampedVoltagePin = 12;
    int counter = 0;
    int sumOfVoltages = 0;
    int sampleSize = 500;
    int average;

    void setup() {
      pinMode(ampedVoltagePin, INPUT);
      Serial.begin(9600);
    }

    void loop() {

      sumOfVoltages += analogRead(ampedVoltagePin);

      if (counter > sampleSize -2) {
        average = sumOfVoltages/sampleSize;
        Serial.println(average);
        sumOfVoltages = 0;
        counter = 0;
      }

      counter ++;
    }


body:
Yes, you do need to sample at a rate at least 2x the highest harmonic you want to consider.  But that's not your biggest problem.

The LM386 is normally used with an output capacitor.  The chip specs say it is "self balancing", which means its output sits at half the supply voltage when there is no signal present, then swings up and down from that.  The inductance of the speaker is not the issue here, it's that it has a very low DC resistance (8 ohms, typically) and you are putting it across a 2.5V DC source (the LM386 output).  This not good for the amp, and it's terrible for the speaker since it is outside its normal centered operating point.

So use a big electrolytic capacitor between the LM386 and the speaker.  The data sheet shows 250 uFd, but that's not critical. Note that the + pin of the capacitor must connect to the LM386 output.  But the Arduino input must connect to the amp directly, as you are doing now, and you must subtract +2.5V from every reading to get an AC waveform.  You can then handle that as you wish, such as by taking the absolute value and filtering (averaging with a time constant).


message:
Writing to partially reserved registers of sensors

I'm trying to change the range of a gyroscope I'm using and there is the following guideline:

> it is recommended to mask out
(logical and with zero) reserved bits of registers which are partially marked as reserved.

I tried reading about bit masking with the bitwise operators and I feel I understand it for trying to read only certain bits, but not for writing.

For example, how would I write to the following register, masking out the 2 bits which are reserved?
[![enter image description here][1]][1]

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

body:
You always write a whole byte when you set the register. You only need to "mask out" those bits if there's a danger that you may inadvertently set them to 1, for instance through some value over flow from other bits when combining values together to form that byte.

If you're not doing that then there's nothing to mask out.  For instance if you just want to set a specific set of bits then just set that value - `0b00101001` is going to be `0b00101001` whether you mask it or not.

If you decide you *really* want to mask a value, for instance if you are writing a library and you have no control over what an end user may decide to pass to a function, then `&` (or `&=`) is your friend:

```c++
uint8_t val = 0x55; // 0b01010101 in binary
val &= 0b00111111; // or 0x3F if you want to use HEX
// val is now 0x15 since bit 6 has been "masked" to 0.
```


message:
Send button only works when pressed immediately after

I am new to Arduino and I am trying to create a Morse code based "chat".

I can submit a message in Morse code using the send button (the one on the right,) and when I press the button on the left and the whole decoded message should appear on the screen. However, this is not happening unless I press the send button immediately after introducing the Morse code. Can anyone help me out? I tried changing the delay period, but nothing seems to make it send how it should.

As I said, I am a beginner, so please go easy on me.

This is my code:
```
/* String tone = "-... ..- -. .- ";

  Morse code - Receiver

  modified on 14 Apr 2019
  by Saeed Hosseini @ Electropeak
  https://electropeak.com/learn

*/
#include <LiquidCrystal.h>
// Create an LCD object. Parameters: (RS, E, D4, D5, D6, D7):
LiquidCrystal lcd = LiquidCrystal(2, 3, 4, 5, 6, 7);
String code = "";
int len = 0;
char ch;
int ok;
char new_char;
int i1=0;
int i2=1;
const int but_send=8;
const int but = 12;
const int led = 13;
String a="";
unsigned long pres_len = 0, rel_time, pres_time = 0, old_time_len = 0, old_pres = 0, space = 0;
int state = 0;
int unit_delay = 250;
int min_delay = 10;
int buttonState = 0;

char MakeString()
{
  if (pres_len < (unit_delay*3) && pres_len > 50)
  {
    return '.';                        //if button press less than 0.6sec, it is a dot
  }
  else if (pres_len > (unit_delay*3))
  {
    return '-';                        //if button press more than 0.6sec, it is a dash
  }
}

void Morse_decod()
{
  static String morse[] = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....",
                             "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-",
                             ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "!"
                            };
  int i = 0;
  while (morse[i] != "!")
  {
    if (morse[i] == code)
    {
      Serial.print(char('A' + i));
      a=a+char('A' + i);
      //lcd.print(char('A' + i));
      Serial.print(" ");
      if(i2>=2)
      {
        i1++;
        i2=0;
      }
      else
      {i2++;
      }
      break;
    }
    i++;
  }
  if (morse[i] == "!")
  {
    Serial.println("");
    Serial.println("This code is not exist!");
  }

  code = "";
}
void sendText()
{
  Serial.println(digitalRead(but_send));
  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  //if (digitalRead(but_send) == HIGH) {
    // turn LED on:
     //gitalWrite(led, HIGH);
  if(ok==1){
    Serial.println(a);}
  ok=0;

    //}
  //else {
    // turn LED off:
    //Serial.println("NIMIC");
  //}
 delay(200);
}
void setup() {
  Serial.begin(9600);
  pinMode(but, INPUT_PULLUP);
  pinMode(but_send, INPUT_PULLUP);
  pinMode(led, OUTPUT);
  lcd.setCursor(i1, 12);
  lcd.begin(16, 2);

}
void loop() {
label:
  while (digitalRead(but) == HIGH) {}
  old_pres = rel_time;
  pres_time = millis();
  digitalWrite(led, HIGH);
  while (digitalRead(but) == LOW) {}
  rel_time = millis();
  digitalWrite(led, LOW);
  pres_len = rel_time - pres_time;
  space = pres_time - old_pres;
  if (pres_len > min_delay)
  {
    code += MakeString();
  }
  while ((millis() - rel_time) < (unit_delay * 3))
  {

    if (digitalRead(but) == LOW)
    {
      goto label;

    }

  }

  Morse_decod();
 delay(1000);
  if (digitalRead(but_send) == LOW)
  {
    ok=1;
    //Serial.println("A intrat aici");
    sendText();
    //delay(100);

  }

 //Serial.println(digitalRead(but_send));

}
```

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

This is what should happen all the time, not only after pressing the send button very fast:
[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/60JV4.png
  [2]: https://i.stack.imgur.com/OmIUT.png

If needed, I can send a link from my tinkercad simulation.

body: It looks like the line : while (digitalRead(but) == HIGH) {} will capture the processor in a loop until "but" is pressed.  So if you press the send button immediately after using "but" it might see that you pressed "send", but if you let the program loop get back to while (digitalRead(but) == HIGH) {}, then nothing can happen until "but" is pressed again.