body:
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.

title: Request for help condensing code and saving memory

Answers: 3

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.


body:
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;
       }

      ```

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

Answers: 1

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();
  }

}
```


body:
I started recently working with a uBlox Neo 6M GPS module.
Connection between Arduino and GPS module....

```
Vcc pin --> 3.3V ,
Tx pin --> D2,
Rx pin --> D3,
Gnd --> Gnd
```

I tried with this code:

    #include <SoftwareSerial.h>
    // Choose two Arduino pins to use for software serial
    int RXPin = 2;
    int TXPin = 3;
    //Default baud of NEO-6M is 9600
    int GPSBaud = 9600;
    // Create a software serial port called "gpsSerial"
    SoftwareSerial gpsSerial(RXPin, TXPin);
    void setup()
    {
      // Start the Arduino hardware serial port at 9600 baud
      Serial.begin(9600);
      // Start the software serial port at the GPS's default baud
      gpsSerial.begin(GPSBaud);
    }
    void loop()
    {
      // Displays information when new sentence is available.
      while (gpsSerial.available() > 0)
        Serial.write(gpsSerial.read());
    }

About 2-3 hours, I was working with it.. But I do not get the GPS LED to blink, as well as my Arduino's RX LED. In serial monitor I didn't get any data. Is my gps module destroyed??

title: U-blox Neo-6M GPS module and RX LED of Arduino aren't blinking

Answers: 0


body:
I want to use the Serial Monitor for some debugging, but it prints something else.

Edit-
This only happens if  I use the ```attachInterrupt()``` function

I tried another program that does not use interrupts and there it works.

My code:-
```

/*
YF‐ S201 Water Flow Sensor
Water Flow Sensor output processed to read in litres/hour
Adaptation Courtesy: www.hobbytronics.co.uk
*/
volatile int flow_frequency; // Measures flow sensor pulses
unsigned int l_hour; // Calculated litres/hour
unsigned char flowsensor = 13; // Sensor Input
unsigned long currentTime;
unsigned long cloopTime;
void flow () // Interrupt function
{
   flow_frequency++;
}
void setup()
{
   pinMode(flowsensor, INPUT_PULLUP);
   Serial.begin(9600);
   attachInterrupt(0, flow, RISING); // Setup Interrupt
   sei(); // Enable interrupts
   currentTime = millis();
   cloopTime = currentTime;
}
void loop ()
{
   currentTime = millis();
   // Every second, calculate and print litres/hour
   if(currentTime >= (cloopTime + 1000))
   {
      cloopTime = currentTime; // Updates cloopTime
      // Pulse frequency (Hz) = 7.5Q, Q is flow rate in L/min.
      l_hour = (flow_frequency * 60 / 7.5); // (Pulse frequency x 60 min) / 7.5Q = flowrate in L/hour
      flow_frequency = 0; // Reset Counter
      Serial.print(l_hour, DEC); // Print litres/hour
      Serial.println(" Lhour");
   }
}
```

Data from Serial Monitor:-

```
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
⸮⸮⸮⸮⸮⸮ISR not in IRAM!

User exception (panic/abort/assert)
--------------- CUT HERE FOR EXCEPTION DECODER ---------------

Abort called

>>>stack>>>

ctx: cont
sp: 3ffffef0 end: 3fffffc0 offset: 0000
3ffffef0:  feefeffe feefeffe feefeffe 00000100
3fffff00:  000000fe 00000000 00000000 00000000
3fffff10:  00000000 00000000 00000000 00ff0000
3fffff20:  5ffffe00 5ffffe00 3ffef0a4 00000000
3fffff30:  00000001 00000000 3ffee34c 40201e72
3fffff40:  40100402 40202e51 ffffffff 40201e84
3fffff50:  feefeffe 00000001 3ffee34c 40202399
3fffff60:  00000000 00000001 3ffee324 4020129c
3fffff70:  00000000 feefeffe feefeffe 3ffee38c
3fffff80:  3fffdad0 00000000 3ffee34c 40202448
3fffff90:  3fffdad0 00000000 3ffee34c 40201079
3fffffa0:  feefeffe feefeffe feefeffe 40201a80
3fffffb0:  feefeffe feefeffe 3ffe84e4 40100cfd
<<<stack<<<
```
Why is this happening?

Hardware-ESP8266 based NodeMCU

title: Unknown text printing on Serial Monitor

Answers: 0


body:
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

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

Answers: 2

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.


body:
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

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

Answers: 3

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


body:
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

title: Writing to partially reserved registers of sensors

Answers: 1

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


body:
I'm new to the Arduino world and I have a question. I found this project to do but I need your help, I want instead of this servomotor to put an electromagnetic door lock, could you help me with the changes in the scheme and code to understand this process? Thank you very much! I leave the diagram and the code here.

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

    #include <deprecated.h>
    #include <MFRC522.h>
    #include <MFRC522Extended.h>
    #include <require_cpp11.h>

    // Include required libraries
    #include <MFRC522.h>
    #include <LiquidCrystal_I2C.h>
    #include <Keypad.h>
    #include <Servo.h>
    #include <SPI.h>
    // Create instances
    LiquidCrystal_I2C lcd(0x27, 16, 2);
    MFRC522 mfrc522(10, 9); // MFRC522 mfrc522(SS_PIN, RST_PIN)
    Servo sg90;
    // Initialize Pins for led's, servo and buzzer
    // Blue LED is connected to 5V
    constexpr uint8_t greenLed = 7;
    constexpr uint8_t redLed = 6;
    constexpr uint8_t servoPin = 8;
    constexpr uint8_t buzzerPin = 5;
    char initial_password[4] = {'1', '2', '3', '4'};  // Variable to store initial password
    String tagUID = "19 7F 30 C2";  // String to store UID of tag. Change it with your tag's UID
    char password[4];   // Variable to store users password
    boolean RFIDMode = true; // boolean to change modes
    char key_pressed = 0; // Variable to store incoming keys
    uint8_t i = 0;  // Variable used for counter
    // defining how many rows and columns our keypad have
    const byte rows = 4;
    const byte columns = 4;
    // Keypad pin map
    char hexaKeys[rows][columns] = {
      {'1', '2', '3', 'A'},
      {'4', '5', '6', 'B'},
      {'7', '8', '9', 'C'},
      {'*', '0', '#', 'D'}
    };
    // Initializing pins for keypad
    byte row_pins[rows] = {A0, A1, A2, A3};
    byte column_pins[columns] = {2, 1, 0};
    // Create instance for keypad
    Keypad keypad_key = Keypad( makeKeymap(hexaKeys), row_pins, column_pins, rows, columns);
    void setup() {
      // Arduino Pin configuration
      pinMode(buzzerPin, OUTPUT);
      pinMode(redLed, OUTPUT);
      pinMode(greenLed, OUTPUT);
      sg90.attach(servoPin);  //Declare pin 8 for servo
      sg90.write(0); // Set initial position at 90 degrees
      lcd.begin();   // LCD screen
      lcd.backlight();
      SPI.begin();      // Init SPI bus
      mfrc522.PCD_Init();   // Init MFRC522
      lcd.clear(); // Clear LCD screen
    }
    void loop() {
      // System will first look for mode
      if (RFIDMode == true) {
        lcd.setCursor(0, 0);
        lcd.print("   Door Lock");
        lcd.setCursor(0, 1);
        lcd.print(" Scan Your Tag ");
        // Look for new cards
        if ( ! mfrc522.PICC_IsNewCardPresent()) {
          return;
        }
        // Select one of the cards
        if ( ! mfrc522.PICC_ReadCardSerial()) {
          return;
        }
        //Reading from the card
        String tag = "";
        for (byte j = 0; j < mfrc522.uid.size; j++)
        {
          tag.concat(String(mfrc522.uid.uidByte[j] < 0x10 ? " 0" : " "));
          tag.concat(String(mfrc522.uid.uidByte[j], HEX));
        }
        tag.toUpperCase();
        //Checking the card
        if (tag.substring(1) == tagUID)
        {
          // If UID of tag is matched.
          lcd.clear();
          lcd.print("Tag Matched");
          digitalWrite(greenLed, HIGH);
          delay(3000);
          digitalWrite(greenLed, LOW);
          lcd.clear();
          lcd.print("Enter Password:");
          lcd.setCursor(0, 1);
          RFIDMode = false; // Make RFID mode false
        }
        else
        {
          // If UID of tag is not matched.
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Wrong Tag Shown");
          lcd.setCursor(0, 1);
          lcd.print("Access Denied");
          digitalWrite(buzzerPin, HIGH);
          digitalWrite(redLed, HIGH);
          delay(3000);
          digitalWrite(buzzerPin, LOW);
          digitalWrite(redLed, LOW);
          lcd.clear();
        }
      }
      // If RFID mode is false, it will look for keys from keypad
      if (RFIDMode == false) {
        key_pressed = keypad_key.getKey(); // Storing keys
        if (key_pressed)
        {
          password[i++] = key_pressed; // Storing in password variable
          lcd.print("*");
        }
        if (i == 4) // If 4 keys are completed
        {
          delay(200);
          if (!(strncmp(password, initial_password, 4))) // If password is matched
          {
            lcd.clear();
            lcd.print("Pass Accepted");
            sg90.write(90); // Door Opened
            digitalWrite(greenLed, HIGH);
            delay(3000);
            digitalWrite(greenLed, LOW);
            sg90.write(0); // Door Closed
            lcd.clear();
            i = 0;
            RFIDMode = true; // Make RFID mode true
          }
          else    // If password is not matched
          {
            lcd.clear();
            lcd.print("Wrong Password");
            digitalWrite(buzzerPin, HIGH);
            digitalWrite(redLed, HIGH);
            delay(3000);
            digitalWrite(buzzerPin, LOW);
            digitalWrite(redLed, LOW);
            lcd.clear();
            i = 0;
            RFIDMode = true;  // Make RFID mode true
          }
        }
      }
    }

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

title: RFID and Keypad Based Door Lock Using Arduino

Answers: 0


body:
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.

title: Send button only works when pressed immediately after

Answers: 3

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.

body:
tavis’ answer nailed down your problem: your program is completely
unresponsive when it is blocked in the first `while` loop of the
`loop()` function. Here I will try to give you some hints on how to
avoid this situation, but first some general comments:

> ```c++
> if (pres_len < (unit_delay*3) && pres_len > 50)
> ```

The threshold should be `unit_delay*2`, maybe with a longer
`unit_delay`. In Morse, a dot is one unit, and a dash is three units. If
you have to set a threshold, it should be somewhere in the middle.
Otherwise, a perfectly valid dash of 2.99 units would be mistaken
for a dot.

Also, a function returning anything but `void` should _always_ return a
value. What is this function supposed to return if `press_len` is
smaller or equal than 50? And if it is exactly equal to
`unit_delay*3`? The best way to make sure you did not forget any case is
to have an `else` at the end that returns a default value in case no
condition matches:

```c++
else
    return '?';  // we could not understand
```

In this particular case, it seems to me like you already did the
debounce prior to calling the function, so it could be simplified to

```c++
char getSymbol()
{
    if (pres_len < 2 * unit_delay)
        return '.';
    else
        return '-';
}
```

Note that giving functions meaningful names is an important step in
making the code easy to understand and reason about.

> ```c++
> if(i2>=2)
> {
>   i1++;
>   i2=0;
> }
> else
> {i2++;
> }
> ```

All this serves no useful purpose, as you do not use `i1` or `i2` after
`setup()`. Removing useless stuff is also important for the clarity of
the code.

> ```c++
> Serial.println("This code is not exist!");
> ```

It should say “I cannot understand this code!”, but it may well exist.

Now, to the core of the issue. If you want the program to be responsive,
you should embrace _non-blocking programming_. This means getting rid of
`delay()` (see [Blink Without Delay][bwod]) and getting rid of blocking
loops, like the two `while` loops at the top of `loop()`. A very useful
approach is to program your system as a [finite state machine][fsm].
Please, take the time to read and digest these two resources.

Next, as an example, I can point you to a Morse decoder of mine that is
based on the finite state machine concept. You do not have have to look
at my code, which may be too low level for your taste, but look at [the
documentation of the program internals][int]. It explains how the state
machines are built and interact with one another. Below is a state
diagram taken from that documentation. It shows the state machine that
takes the debounced “rise” and “fall” events as inputs, and generates
“dot”, “dash”, “end-of-char” and “end-of-word” symbols as outputs:

[![state diagram of Morse decoder][1]][1]

[bwod]: https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
[fsm]: https://majenko.co.uk/blog/finite-state-machine
[int]: https://github.com/edgar-bonet/tiny-morse-decoder/blob/master/internals.md
[1]: https://i.stack.imgur.com/VOcCD.png

body:
Both tavis and Edgar Bonet have hit the nail on the head, and Edgar has provided you with an excellent tutorial.

You are unlikely to get this to work properly in the Tinkercad browser simulator because it runs at different speeds depending on the complexity of the code it is running. And the complexity varies when you press buttons, which throws the timing out as the Morse button is pressed.

However, I managed to get it roughly working in Tinkercad as follows.

[![Tinkercad Morse code][1]][1]

```c++
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const byte MORSE_BUTTON_PIN = 6;
const byte SEND_BUTTON_PIN = 7;
const byte MORSE_LED_PIN = 8;

const unsigned long DEBOUNCE_DELAY_ms = 50;
const unsigned long MORSE_UNIT_1 = 500;  // milliseconds.
const unsigned long MORSE_UNIT_2 = 2 * MORSE_UNIT_1;  // milliseconds.
const unsigned long MORSE_UNIT_5 = 5 * MORSE_UNIT_1;  // milliseconds.

const String MORSE_CODES[] =
{
  ".-", "-...", "-.-.", "-..", ".",
  "..-.", "--.", "....", "..", ".---",
  "-.-", ".-..", "--", "-.", "---",
  ".--.", "--.-", ".-.", "...", "-",
  "..-", "...-", ".--", "-..-", "-.--",
  "--.."
};

String symbol;
String message;

Debouncer morse_button(MORSE_BUTTON_PIN, DEBOUNCE_DELAY_ms);
Debouncer send_button(SEND_BUTTON_PIN, DEBOUNCE_DELAY_ms);

void setup()
{
  Serial.begin(115200);
  pinMode(MORSE_BUTTON_PIN, INPUT);
  pinMode(SEND_BUTTON_PIN, INPUT);
  pinMode(MORSE_LED_PIN, OUTPUT);
  // Set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Hello, world!");
}

void loop()
{
  static unsigned long press_begin_time = 0;
  static unsigned long release_begin_time = 0;
  static bool measure_the_gap = false;

  morse_button.Update();
  send_button.Update();

  if (morse_button.Fall())
  {
    // Remember when the morse button was pressed and
    // switch on the LED.
    int timestamp = millis();
    digitalWrite(MORSE_LED_PIN, HIGH);
    press_begin_time = timestamp;
  }

  if (morse_button.Rise())
  {
    // Remember when the morse button was released and
    // switch off the LED.
    int timestamp = millis();
    digitalWrite(MORSE_LED_PIN, LOW);
    release_begin_time = timestamp;
    int pressed_time = timestamp - press_begin_time;
    if (pressed_time > MORSE_UNIT_2)
    {
      // Dash.
      //Serial.print("-");
      symbol += "-";
    }
    else
    {
      // Dot.
      //Serial.print(".");
      symbol += ".";
    }
    measure_the_gap = symbol.length() > 0;
  }

  if (measure_the_gap)
  {
    unsigned long timestamp = millis();
    //Serial.println("Measuring the gap.");
    if (((timestamp - release_begin_time) > MORSE_UNIT_2))
    {
      // A long gap between presses signifies the end of a symbol.
      //Serial.println("Long gap");
      //Serial.println(symbol);
      measure_the_gap = false;
      message += DecodeSymbol(symbol);
      symbol = "";
    }
  }

  if (send_button.Fall())
  {
    // Print the Morse string.
    //Serial.println(message);
    lcd.clear();
    lcd.setCursor(0, 1);
    lcd.print(message);
    message = "";
  }

  // Delay for Tinkercad simulator.
  // Not needed for real hardware.
  delay(10);
}

char DecodeSymbol(String& symbol)
{
  //Serial.print(symbol);
  //Serial.print(": ");
  char ch = '?';
  for (int i = 0; i < 26; i++)
  {
    if (symbol == MORSE_CODES[i])
    {
      ch = 'A' + i;
      break;
    }
  }
  //Serial.println(ch);
  return ch;
}
```

For debouncing the buttons, I used this [debouncer][2] that I've put on GitHub. For Tinkercad, you will need to copy and paste that debouncer code (the debouncer.h file followed by the debouncer.cpp file) into the top of the Tnkercad code file because Tinkercad doesn't allow you to include your own code files.

  [1]: https://i.stack.imgur.com/rIJPR.png
  [2]: https://github.com/TimMathias/Arduino-Debouncer


body:
For whatever reason the delay function is not working (it is not delaying at all) with my ESP32 development board. Has anyone come across a similar issue before? It's not working with other sketches, in either the loop or set up functions. A sample sketch:

    #include <Wire.h>
    #include <Adafruit_Sensor.h>
    #include <Adafruit_BNO055.h>
    #include <utility/imumaths.h>
    #include <BleMouse.h>

    // mouse object
    BleMouse ble("test", "me");

    /** I2C pins **/
    #define I2C_SDA 33
    #define I2C_SCL 32

    // I2C object
    TwoWire wire_custom = TwoWire(0);

    // Sensor object
    Adafruit_BNO055 bno = Adafruit_BNO055(55, 0x28, &wire_custom);

    /**************************************************************************/
    function definitions
    ...

    /**************************************************************************/
    void setup(void)
    {
      wire_custom.begin(I2C_SDA, I2C_SCL, 400000);

      Serial.begin(115200);

      ble.begin();

      if (!bno.begin())
      {
        Serial.print("Ooops, no BNO055 detected ... Check your wiring or I2C ADDR!");
        while (1);
      }
      delay(1000);
      bno.setExtCrystalUse(true);

      // updating range
      bno.setMode(Adafruit_BNO055::OPERATION_MODE_CONFIG);
      delay(1000);
      write_register (0x28, 0x0A, 0b00111010);
      bno.setMode(Adafruit_BNO055::OPERATION_MODE_NDOF);
      delay(10000);
      byte result = read_register (0x28, 0x0A, 1);
      Serial.print(result);
      Serial.print("\n");
      Serial.print("\n");
    }

    /**************************************************************************/
    void loop(void)
    {
      sensor_calibration ();

      sensor_data (x_placeholder, y_placeholder);

      transform_sensor_data (x_placeholder, y_placeholder, x, y);

      if (ble.isConnected()) {
        ble.move(x, y);
      }
    }

title: Delay function not working with ESP32

Answers: 0


body:
I can't remember for the life of me how exactly I set up this screen in previous models, partially because the references I'm using in my code have different names from the pins on the Adafruit display.

My code identifies the following digital pins for the following display pins:

    OLED_MOSI = 12
    OLED_CLK = 11
    OLED_DC = 10
    OLED_CS = 8
    OLED_RESET = 9

My Arduino is then attached from the following pins to those labelled on the OLED display as"

    12 -> SDA
    11 -> SCK
    10 -> DC
    8 -> CS
    9 -> RES
    5V -> VDD
    GND -> GND

In other words, I am interpreting the following as being equivalent:

    RES = RESET
    SCK = SCK
    MOSI = SDA

Is there anything within the information I've provided that is wrong / may cause the screen to malfunction?

Thank you very much in advance.

title: Adafruit OLED 7 Pin Display - Abbreviations

Answers: 1

body:
* `DC` selects between `D`ata and `C`ommands.
* `CS` is the `C`hip `S`elect
* `SDA` is the `S`erial `DA`ta.
* `SCL` is the `S`erial `CL`ock.

These four together form what the documentation calls the "4-wire serial interface". It's not quite like SPI, owing to the presence of the `DC` pin (which is why it doesn't use SPI terminology), but close enough that SPI can be used to communicate with it.

In SPI the pin that sends data from the Arduino to the slave is known as the `MOSI` - `M`aster `O`ut `S`lave `I`n.  Some microcontrollers also call this `SDO` - `S`erial `D`ata `O`ut, where it's "out from the master's perspective".


body:
I've recently acquired a Bluetooth module to attach to my Arduino Uno, but I'm trying to draw parallels to the standard method of communication that I'm familiar with, which seems to be just directly reading or writing to sensors through methods like digitalRead and digitalWrite, respectively. Additionally however, it seems like it's also possible to connect to a serial console, through the `Serial` class. These make sense, and I've used both individually (serial console viewed by the built-in Serial window in Arduino IDE, and serial write done through `Serial.print/println()`).

However, in the Bluetooth module I purchased (HW-10), there are pinouts that connect to the TX/RX ports, which I've currently left unconnected since I'm not using the Bluetooth module or any other serial module. My question is, once I connect these, does this completely replace the connection through USB that is currently used to interface with the Uno?

If so, I had a set of specific functionalities in mind for whether these would be "replaced" by connecting the module through the 4 pinouts (TX, RX, VCC, GND):

**1. Serial:** Can I write and access the serial monitor through the IDE by connecting to 9600 baud, both in code and in the Serial Monitor

**2. Pins:** Do these connections also allow me to write and read signals from all of the pins, including analog and digital

**3. Sending code:** Can I still send code through Bluetooth without needing a USB connection?

Apologies if this question seems really obvious or specific, I'm confused as I've read a bunch of wording saying that the Bluetooth module uses a "serial connection", when I only understood serial functionality as being a method of outputting text, not controlling the Arduino. Thanks in advance for help!

title: Struggling to understand how Bluetooth serial is related to USB on Arduino

Answers: 1

body:
> I don't actually know what a UART is

UART (Universal Asynchronous Receiver Transmitter) is the technical term for the communication interface, which is called `Serial` in Arduino speak. It's often called UART, because that is more precise, since there are many different communication protocols, which also work serially (meaning transferring data bits one after another in contrast to parallel, where multiple bits are transferred simultaneously), like I2C, SPI or USB. All serial protocols, but totally different from the Arduino `Serial` interface. Yes, this is a bit confusing. I guess the Arduino term `Serial` was coined to make the learning curve less steep for beginners (hiding complexity can also make things confusing unfortunately).

So UART is the same as the Arduino `Serial` interface.

> once I connect these, does this completely replace the connection through USB that is currently used to interface with the Uno?

Here it is good to know, how the USB communication works on the Uno. The microcontroller on the Uno (Atmega328p) does not have a native USB interface. So it cannot speak to USB itself. For that there is an extra microcontroller on the board (I think an Atmega32u4). This controller has a native USB interface and it acts as a USB to `Serial` bridge (it creates a virtual serial interface on the PC and translate between that and its physical `Serial`/UART interface). The Atmega328p (which you program with your code) has it's RX and TX pins connected to the RX and TX pins on the Atmega32u4, which can then translate between the `Serial`/UART protocol and the USB protocol. Thus the Atmega328p doesn't know anything about USB. I just talks via `Serial`/UART to the Atmega32u4. In fact it also doesn't know anything about bluetooth. Most bluetooth modules for Arduino are also just bluetooth-`Serial` bridges

Now you need to know, that `Serial`/UART is made for one-to-one connections. With multiple devices you can get problems, when multiple devices try to send data at the same time. I this case (BT module RX to Arduino TX and vice versa) you would get garbled data, if you try to simultaneously send data from bluetooth and USB to the Arduino. The signals would overlap on the Arduinos RX pin, corrupting the data.

That means, that you don't want to send from both interfaces. In fact it is the easiest way to just use one `Serial`/UART  interface for only one device. If you leave the Serial Monitor (or any other Serial communication program) closed on the PC, the PC will not interfere with the communication. Though you need to disconnect the bluetooth module, when you write your program to the Arduino, since this is done via `Serial` and you don't want it to meddle with the data.

So in result the bluetooth module will not "replace" the connection through USB. It will be added and it is your duty to prevent data corruption.

> 1. Serial: Can I write and access the serial monitor through the IDE by connecting to 9600 baud, both in code and in the Serial Monitor

Yes. You don't need to use 9600 baud necessarily. The only requirement is, that you use the same baud number in both sketch and Serial Monitor. That number just represents the speed, that the data is send in. Both sender and receiver need to agree on the same communication speed, or the receiver will not be able to read the data. Imagine someone talking to you, but talking twice the speed with that you are able to understand the words. You will not be able to understand much, because the speaker is just too fast. Either you would need to change your hearing/understanding speed or the sender needs to change it's speaking speed, to make the two match.

9600 baud is just one of the standard baudrates, though one of the lower ones. If you need it to be faster (maybe because you are sending much data in fast succession), you might want to use a higher baudrate.

> 2. Pins: Do these connections also allow me to write and read signals from all of the pins, including analog and digital

That is up to you. `Serial`/UART is just a communication interface. How it is used is up to you. You already have seen, that it is often used to output text for a user to read over the `Serial` interface, often used as a way to debug the code by sending specific text at specific places in the code. Since that connection works in both ways, you can also program the Arduino to receive commands over `Serial`/UART and then act upon them.

Here the overlaying communication protocol comes in. `Serial`/UART just transmits a series of bytes over its two lines. It doesn't care, what these bytes mean. It can be text (for example encoded via the ASCII standard, as the Serial Monitor does), or it can be just some binary data. Also there is no concept of "messages". There are only individual bytes and you don't have control over when exactly they are sent. So to make meaningful use of `Serial`/UART you need to use an extra communication protocol on top of `Serial`/UART, that the receiver understands.

When you send text to the Serial Monitor you are the receiver. Thus you would send text (because you can understand text) and a natural way for humans to distinguish individual messages is to use a delimiter character. In normal text that can be a period, though in this field going to a new line has somewhat evolved to the standard (so the delimiter character is the newline character `'\n'`). If you read the delimiter character (either yourself on the Serial Monitor, or the Arduino in your program), that marks the end of the message. You can also use that text based approach in your Arduino program (and I would say that is the easiest way). Though you don't need to. You could also use any binary protocol on it (or even invent your own protocol).

I would suggest you look at the examples in the Arduino IDE, that involve `Serial` and maybe try some tutorials on the web. There are many of them available.

> 3. Sending code: Can I still send code through Bluetooth without needing a USB connection?

You don't need an USB connection for `Serial`/UART to work. In fact the Atmega328p, which you program on the Uno, doesn't care about the USB connection at all. It only knows `Serial`/UART.

---

I hope that gave you a good overview over that topic. When you understand these core concepts you will be able to understand the tutorials and examples on the internet.


body:
I have an Arduino Uno and two Hi-tec servos (HS-40 & 5055 digital) that I'm using for a basic robot build. I'm trying to have one servo(HS-40) turn the head back and forth (left to right) slightly faster than the other servo (HS-5055) controlling the upper torso.

I would like to have each servo working at the same time but not at the same speed without waiting for one servo to complete its movement.

I tried a sketch with a delay of 45-50 which seems to work fine for the movement speed and 0-75 degrees is ideal for the head travel and 0-65 degrees for the torso travel. I would like to have this movement to be repeated continuously so the robot mimics like it is looking side to side or left to right naturally.

Please help as I tried many sketches but can't find one that works like this. I tried modifying other code but can't get them work. Any help will be greatly appreciated.

How do modify this code so just the second servo runs at 40 which will slow down just enough? Also this is not my code, but it's one that seems to be close to what I'm trying to do.

```
#include <Servo.h>

Servo servo1;
Servo servo2;

int i = 0;

void setup() {
  servo1.attach(8);
  servo2.attach(9);
}

void loop() {
  for (i = 0; i < 70; i++) {
    servo1.write(i);
    servo2.write(i);
    delay(50);
  }
  for (i = 70; i > 0; i--) {
    servo1.write(i);
    servo2.write(i);
    delay(50);
  }
}
```

title: Two servos for robot (head & chest) movement at different speeds at once

Answers: 2

body:
Heres a little sketch you can try.  It uses timing to accomplish the different servo speeds.  It won't give you the exact servo travel each loop but it sounds like you might not mind if it randomly is off by a few degrees each loop.

    #include <Servo.h>
    Servo servo1;
    Servo servo2;
    int i = 0;
    void setup() {
      Serial.begin(9600);
      servo1.attach(8);
      servo2.attach(9);
    }

    int sweep_time = 3500; // 70 * 50ms = 3500

    int head_degrees = 75; // sweep degrees for the head to move
    int body_degrees = 65; // sweep degrees for the body to move

    int millis_per_head_move = sweep_time / head_degrees;
    int millis_per_body_move = sweep_time / body_degrees;

    void loop() {
      int i = 0; int j = 0;
      unsigned long now_millis = 0;
      unsigned long start_sweep = millis(); // mark the time when we start the first sweep

      while ( millis() - start_sweep < sweep_time ) {  // keep moving first sweep until sweep time has elapsed
        now_millis = millis() - start_sweep;
        if (now_millis % millis_per_head_move == 0 ) servo1.write(i++);
        if (now_millis % millis_per_body_move == 0 ) servo2.write(j++);
        delay(1);
      }
      Serial.print(i); Serial.print(" "); Serial.println(j);

      start_sweep = millis();  // mark the time when we start the second/back sweep
      while ( millis() - start_sweep < sweep_time ) {  // keep moving second sweep until sweep time has elapsed
        now_millis = millis() - start_sweep;
        if (now_millis % millis_per_head_move == 0) servo1.write(i--);
        if (now_millis % millis_per_body_move == 0) servo2.write(j--);
       delay(1);
      }
      Serial.print(i); Serial.print(" "); Serial.println(j);
    }

body:
Thanks for the answer from @tavis

Here is the simulation of their code and it answers your questions aptly.
[![enter image description here][1]][1]

The code (same as above, except the sweep time change)

    #include <Servo.h>
    Servo servo1;
    Servo servo2;
    int i = 0;
    void setup() {
      Serial.begin(9600);
      servo1.attach(8);
      servo2.attach(9);
    }

    int sweep_time = 1000; // 70 * 50ms = 3500

    int head_degrees = 75; // sweep degrees for the head to move
    int body_degrees = 65; // sweep degrees for the body to move

    int millis_per_head_move = sweep_time / head_degrees;
    int millis_per_body_move = sweep_time / body_degrees;

    void loop() {
      int i = 0; int j = 0;
      unsigned long now_millis = 0;
      unsigned long start_sweep = millis(); // mark the time when we start the first sweep

      while ( millis() - start_sweep < sweep_time ) {  // keep moving first sweep until sweep time has elapsed
        now_millis = millis() - start_sweep;
        if (now_millis % millis_per_head_move == 0 ) servo1.write(i++);
        if (now_millis % millis_per_body_move == 0 ) servo2.write(j++);
        delay(1);
      }
      Serial.print(i); Serial.print(" "); Serial.println(j);

      start_sweep = millis();  // mark the time when we start the second/back sweep
      while ( millis() - start_sweep < sweep_time ) {  // keep moving second sweep until sweep time has elapsed
        now_millis = millis() - start_sweep;
        if (now_millis % millis_per_head_move == 0) servo1.write(i--);
        if (now_millis % millis_per_body_move == 0) servo2.write(j--);
        delay(1);
      }
      Serial.print(i); Serial.print(" "); Serial.println(j);
    }

Link to the simulation:
https://wokwi.com/arduino/projects/303847722463527490

Here is another example with three Servo motors running at three different sweep times:
https://wokwi.com/arduino/projects/299552195816194570

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


body:
I have one external sensor and I want it to be connected with Arduino. The sensor came up with a usb cable and the pin out diagram is also given in the data sheet .

When I simply connect the the cabe which came along the sensor (E322968) with no Arduino board involved, but through Arduino IDE and setting baud rate to 115200 I am able to see the output in serial monitor of the Arduino .
[![enter image description here][1]][1]

 I want to capture this data to some variables for further manipulation. In the data sheet the pinout is specified as
[![enter image description here][2]][2]

Please help me get the data to Arduino variable .

What I tried is connected,
1. the RX1 or Arduino mega to the TX1 of the sensor (pin2) and
2. from Arduino VCC(5v) to VCC of the sensor :: pin(1)
3. ground to gnd of sensor, (pin5)

  [1]: https://i.stack.imgur.com/4u9Ae.png
  [2]: https://i.stack.imgur.com/r47Gg.png

title: Arduino Mega reading from external sensor Issue

Answers: 1

body:
> the RX1 or Arduino mega to the TX1 of the sensor (pin2) and

That will not work. These pins are for RS232, which uses the same communication protocol (UART) as the Arduino, but it uses different voltage levels. But fortunately your sensor has also RX and TX pins at TTL level (Transistor-Transistor-Logic). You want to connect these to the Arduino.

One thing to keep in mind: The sensor logic seems to work at 3.3V (voltage on the RX and TX lines). If you also want to send data to the sensor, you may need to step down the 5V of the Uno to the 3.3V of the sensor on its RX line (since 5V might damage the sensor). You can use a simple voltage divider with 2 resistors or a proper level shifter (which uses transistors) (voltage dividers limit the communication speed, though 115200baud should not be a problem).


body:
i connected an Arduino Nano to an external SPI Flash using [THIS](https://it-blackbox.blogspot.com/2018/04/spi-arduino-nano.html) tutorial (russian) and the SPIMemory library. While accessing the Flash works well, i have encountered the following issue:

**The Problem: When the SPI MISO line is pulled high by the flash while the Arduino boots, it does not start**, for example because it was rebooted while accessing the flash. I have to power down the Flash before it boots again. But even then, it takes unusually long to boot.

I know that the Atmega328p allows reprogramming via SPI, but to my knowledge this should not cause this behavior since the SPI lines do not change (starting the programming mode would require a command to be sent immediately after restart). Is there any way to prevent this behavior? (Except disabling SPI programming via fuse bits, this would be my last choice)

**EDIT**

Programming the Arduino via ISP does work, however i added some series resistors to the flash to prevent accidentally driving the SPI lines from multiple sources.

The problem seems to come from the MISO line, when it is pulled to VCC the Arduino does not start. This is not mentioned in the data sheets anywhere and i am not sure how to prevent this (sketch below to show the wiring).

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

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

title: Arduino does not boot when SPI lines are loaded

Answers: 1

body:
I honestly can't imagine why a sketch like that would hang in this scenario. But I'm confident that my answer can solve the issue.

My guess is that the following happens:
The flash is selected (CS pulled low by atmega) at the moment at which the reset happens. At this moment, the master will stop generating a clock signal and CS will be floating.
Thus, the flash will not be deselected *reliably* due to the floating CS and MISO will remain in the state it was before the reset occured (HIGH if it was transmitting a logic 1, LOW for 0). Basically, the SPI communication of the flash will be stuck with MISO being actively pulled to logic high or low.

IDK why this causes the sketch to freeze, but if you add a pullup resistor to the flash's CS, it should be deactivated by default (and also after a reset of the atmega as pins will be inputs/floating by default). As a result, the flash can not actively pull MISO and should therefore barely affect the atmega at all.

I suggest you add the mentioned pullup and see if that makes any difference. If it doesn't I'm going to delete this answer, but it was a bit too long for a comment ;).

Edit: I also just saw that you are missing the pullup resistor on the reset pin. That could well be the actual problem.


body:
I am trying to connect ESP32 via bluetooth classic to my PC to transfer some data from a sensor.

As a first step, I am simply trying to send some random data over bluetooth serial. The code is at follows:
```
#include "BluetoothSerial.h"

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

int myData[8];
BluetoothSerial SerialBT;

void setup() {
  Serial.begin(115200);
  Serial.println("Opening Serial Connection on COM4");
  SerialBT.begin("ESP32"); //Bluetooth device name
  SerialBT.println("Opening Serial Bluetooth Connection on COM6");

}

void loop() {

  for(int i = 0; i < 8; i++)
  {
    myData[i] = random(0,500);
  }
  if(Serial.available())
    {

     for(int i = 0; i < 8; i++)
  {
    SerialBT.write(myData[i]);
  }

    }
    delay(20);
}
```
In Windows bluetooth settings, I have paired the ESP32 with windows and connected it. I have set up incoming and outgoing COM ports for bluetooth where incoming port is  COM6 and outgoing port is COM5.

However, when I open arduino serial monitor for COM6, it is empty and no data is being printed. I am using arduino IDE. Furthermore, on COM4, there is nothing printed despite the Serial.println("Opening Serial Connection on COM4"); command which I think should work regardless of bluetooth.

I have tried everything I can think of. I would be grateful if anyone can help me solve this problem as I have been stuck for days

title: Problem with ESP32 bluetooth

Answers: 0


body:
How would you send a struct from an i2c slave when requested by an i2c master?

**Slave Struct Respdonder Sketch (Seeeduino Xiao)**

    #include <Wire.h>

    struct TransmitData
    {
      int a;
      int b;
      int c;
      int d;
      float e;
      float f;
      float g;
      float h;
    };

    TransmitData data;

    void setup()
    {
      Serial.begin(9600);
      Wire.begin(2);
      Wire.onRequest(requestEvent);

      data.a = 1;
      data.b = 2;
      data.c = 3;
      data.d = 4;
      data.e = 5.1;
      data.f = 6.1;
      data.g = 7.1;
      data.h = 8.1;
    }

    void loop()
    {
      delay(100);
    }

    void requestEvent()
    {
      Serial.print("sending ("); Serial.print(sizeof data); Serial.println(" bytes)");
      Wire.write((byte *)&data, sizeof data);
    }

**Master Struct Requester/Reciever Sketch (Arduino MEGA)**

    #include <Wire.h>

    struct TransmitData
    {
      int32_t a;
      int32_t b;
      int32_t c;
      int32_t d;
      float e;
      float f;
      float g;
      float h;
    };

    TransmitData data;

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

    void loop() {
      Serial.print("requesting ("); Serial.print(sizeof data); Serial.print(" bytes)... ");
      if (Wire.requestFrom(2, sizeof data)) {
        Wire.readBytes((byte*) &data, sizeof data);
        Serial.println("done");

        Serial.println(data.a);
        Serial.println(data.b);
        Serial.println(data.c);
        Serial.println(data.d);
        Serial.println(data.e);
        Serial.println(data.f);
        Serial.println(data.g);
        Serial.println(data.h);
      }
      else {
        Serial.println("could not connect");
      }
      delay(500);
    }

The serial output on the slave device is:

    sending (32 bytes)

The serial output on the master device is:

    requesting (24 bytes)... done
    1
    0
    2
    0
    0.00
    0.00
    5.10
    6.10

title: Sending a struct over i2c

Answers: 1

body:
`int` isn't guaranteed to be the same size across platforms. Use fixed width integer types instead.

https://en.cppreference.com/w/cpp/types/integer

    struct TransmitData
    {
      int32_t a;
      int32_t b;
      int32_t c;
      int32_t d;
      float e;
      float f;
      float g;
      float h;
    };


body:
I'm making a hydroponics system that collects data and sends it to the user through a SIM module. The problem is that while I want it to happen only once every 15 minutes and for the pump to operate for 30 seconds only, yet the device seems to do everything 10 times as quickly, if not even faster. Is there any way to fix this without multiplying everything by 10?
```
#include <SoftwareSerial.h>
#include <DHT.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
#include <GravityTDS.h>
#include <Servo.h>

#define ONE_WIRE_BUS 5
#define DHTPIN 7
#define DHTTYPE DHT11
#define TdsSensorPin A1
#define PUMPPIN 11

SoftwareSerial mySerial(9, 10);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DHT dht(DHTPIN, DHTTYPE);
GravityTDS gravityTds;
Servo myservo;

char msg;
char call;

void setup()
{

  dht.begin();

  sensors.begin();

  gravityTds.setPin(A1);
  gravityTds.setAref(5.0);
  gravityTds.setAdcRange(1024);
  gravityTds.begin();

  myservo.attach(PUMPPIN);
}

void loop()
{
  const unsigned long SECOND = 1000;
  const unsigned long MINUTE = 60*SECOND;
  const unsigned long HOUR = 60*MINUTE;

  delay(30*SECOND);
  int h = dht.readHumidity();
  float t = dht.readTemperature();
  float tdsValue = 0;
  float temperature = t;
  gravityTds.setTemperature(temperature);
  gravityTds.update();
  tdsValue = gravityTds.getTdsValue();

  sensors.requestTemperatures();

  mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
  delay(1000);  // Delay of 1000 milli seconds or 1 second
  mySerial.println("AT+CMGS=\"+************\"\r"); // Replace x with mobile number
  mySerial.print(h);// The SMS text you want to send
  mySerial.print("% humidity, ");
  mySerial.print(t);
  mySerial.print(" degrees Celsius air temperature, ");
  mySerial.print(sensors.getTempCByIndex(0));
  mySerial.print(" degrees Celsius water temperature, ");
  mySerial.print(tdsValue,0);
  mySerial.print(" ppm");

  delay(100);
  mySerial.println((char)26);// ASCII code of CTRL+Z
  delay(1000);

  myservo.write(0);   //Clockwise maximum speed rotation
    delay(30*SECOND);
  myservo.write(90);
  delay(15*MINUTE);

}```

title: Delay function executes too quickly

Answers: 0


body:
I am doing [this][1] simple introductory exercise to light an RGB Led, but I am confused about the code in the exercise. The following is the code:

    /* Adafruit Arduino - Lesson 3. RGB LED
    */

    int redPin = 11;
    int greenPin = 10;
    int bluePin = 9;

     //uncomment this line if using a Common Anode LED //#define
     COMMON_ANODE

    void setup() {
    pinMode(redPin, OUTPUT);
    pinMode(greenPin, OUTPUT);
    pinMode(bluePin, OUTPUT);   }

    void loop() {
      setColor(255, 0, 0);  // red
      delay(1000);
      setColor(0, 255, 0);  // green
      delay(1000);
      setColor(0, 0, 255); // blue
      delay(1000);
      setColor(255, 255, 0);  // yellow
      delay(1000);
      setColor(80, 0, 80);  // purple
      delay(1000);
      setColor(0, 255, 255);  // aqua
      delay(1000); }

    void setColor(int red, int green, int blue) {
    #ifdef COMMON_ANODE
         red = 255 - red;
         green = 255 - green;
         blue = 255 - blue;
    #endif
      analogWrite(redPin, red);
      analogWrite(greenPin, green);
      analogWrite(bluePin, blue);   }

In this code, why were they able to carry out setColor before expanding upon what it means later through `void setColor(int red, int green, int blue)`? Should that portion of the code come earlier or does it matter? Also I don't quite understand how the definition of the colors red, green, and blue were defined towards the bottom. I know what 255 would indicate maximum brightness, but why do you have to subtract the color from 255? Any help would be much appreciated.

  [1]: https://learn.adafruit.com/adafruit-arduino-lesson-3-rgb-leds/arduino-sketch

title: Code For Lighting RGB Led

Answers: 1

body:
> why were they able to carry out setColor before expanding upon what it means later

You are correct in C that is the case. However the Arduino IDE adds "function prototypes" to the top of your code automatically. That means you no longer have to abide by the "define before use" of C and C++.

> I know what 255 would indicate maximum brightness, but why do you have to subtract the color from 255?

This is for if your LED is "common anode" instead of "common cathode". With a common anode LED you write a LOW to turn it on and a HIGH to turn it off - this is the exact opposite of a common cathode.

So to set the brightness of a common anode LED you need to use the opposite value, and since PWM goes from 0-255 the opposite is 255-0: 255 is off, and 0 is fully on.


body:
I have a 200mw laser module that came with a 3v 1A power supply. I want to control it from a digital pin on an arduino uno.

Can I use a simple voltage divider like this or is there some consideration to current I'd need to take into account? The laser module was quite expensive so I'm hesitant to try it out.

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/DCqO8.png)

<!-- End schematic -->

title: Control laser diode from digital pin

Answers: 1

body:
Your solution does not work, mainly because GPIOs are not intended to source current higher than a few mA. If you want the laser diode to emit a reasonable amount of power, you need to drive it with a transistor. A MOSFET-based low-side-switch would probably be the easiest solution. But note that you still need to limit the current, e.g. by using a series resistor.

Even better would be to use a constant current driver (you can use any led driver with appropriate rating).

If the power supply that came with the laser diode is a constant current source, it might be possible to switch its output directly (without resistor), but that depends on how it behaves when it is open-circuited.


body:
I am getting an error while trying to upload programs to the Attiny85 through a USBTinyISP programmer, found [here][1]. Unfortunately, it isn't working. Following [this][2] tutorial for connecting the board and [this][3] tutorial for programming it with the Arduino IDE. My code is:

    #include <SoftwareSerial.h>

    void setup() {
      // put your setup code here, to run once:

    }

    void loop() {
      // put your main code here, to run repeatedly:

    }

A picture of my setup, which I checked at least 10 times:

[![setup][4]][4]

However, I get this error message:

    avrdude: Version 6.3, compiled on Jun 22 2016 at 16:05:21
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : usb
         Using Programmer              : usbtiny
    avrdude: usbdev_open(): Found USBtinyISP, bus:device: bus-0:\\.\libusb0-0001--0x1781-0x0c9f
             AVR Part                      : ATtiny85
             Chip Erase delay              : 400000 us
             PAGEL                         : P00
             BS2                           : P00
             RESET disposition             : possible i/o
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    12     4    0 no        512    4      0  4000  4500 0xff 0xff
           flash         65     6    32    0 yes      8192   64    128 30000 30000 0xff 0xff
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

         Programmer Type : USBtiny
         Description     : USBtiny simple USB programmer, http://www.ladyada.net/make/usbtinyisp/
    avrdude: programmer operation not supported

    avrdude: Using SCK period of 10 usec
    avrdude: initialization failed, rc=-1
             Double check connections and try again, or use -F to override
             this check.

    An error occurred while uploading the sketch
    avrdude done.  Thank you.

Can someone please help me to fix this problem?
Thank you.

P.S.: On a website that talked about this error message and a similar programmer said to take out a jumper. I took out the only jumper on the programmer and it did not affect the error message.

UPDATE:
I changed the support from "attiny" by David 0 Mellis to "ATTinyCore" by SpenceKonde. Here is a screenshot of my tools menu:

[![tools menu][5]][5]

Now I get a different error:

        avrdude: Version 6.3, compiled on Jun 22 2016 at 16:05:21
             Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
             Copyright (c) 2007-2014 Joerg Wunsch

             System wide configuration file is "C:\Users\loydn\Documents\Arduino\hardware\ATTinyCore-master\avr/avrdude.conf"

             Using Port                    : COM3
             Using Programmer              : arduino
             Overriding Baud Rate          : 2400
             Setting bit clk period        : 5.0
    avrdude: ser_open(): can't open device "\\.\COM3": The system cannot find the file specified.

    avrdude done.  Thank you.

    Problem uploading to board.  See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.

FIX!!!:
It turns out that it was a problem with the programmer. By connecting the Attiny85 to the 10-pin header instead of the 6-pin one, it was able to upload successfully.

  [1]: https://www.amazon.com/USBtinyISP-Programmer-Bootloader-Download-Interface/dp/B01FDD4EP0/ref=cm_cr_arp_d_bdcrb_top?ie=UTF8
  [2]: https://shallowsky.com/blog/hardware/attiny85-c.html
  [3]: https://wolles-elektronikkiste.de/en/programming-attiny85-84-45-44-25-24
  [4]: https://i.stack.imgur.com/oz7S7.jpg
  [5]: https://i.stack.imgur.com/ZW4Oq.png

title: Attiny85 uploading error

Answers: 0


body:
I'm trying to execute a math of analog read but I get some weird result.. I searched about int and floats but didn't understand..

My code is :

```
#include <SevSeg.h>

SevSeg sevSeg;

int bitsChange = analogRead(A0) ;
float fuel = (923 - bitsChange) * 0.121065375;
sevSeg.setNumber(round(fuel));
```

Assuming bitsChange = 683, so fuel has to be after rounding 29, what I get is 39!!!!

I want to know why I get this result to learn about it..

title: Math on analog read wrong result

Answers: 0


body:
I am trying to learn about MOSFETs and see this [p channel MOSFET][1] and this [tutorial][2].  I am trying to use a 3.3V arduino GPIO pin to control a load that is powered from a 4.2V battery in much the same configuration as the circuit drawn in that tutorial.  Most other tutorials I see say the Gate Voltage needs to be equal or greater than the Source Voltage, but the tutorial I cited describes that actually the Voltage between the Gate and Source just needs to be more negative than the Threshold Voltage.  The P channel mosfet I cited is Vthreshold -2V to -4.  So my question is whether this P channel MOSFET would allow me to use a 3.3V arduino GPIO to control whether that 4.2V source is closed or open to the drain/load.  Looking at how that tutorial does the math, it seems in my case the GPIO being off would mean Vgs is 0 - 4.2 = -4.2 and therefore the MOSFET is in the ON state.  If GPIO is on at 3.3V then Vgs is 3.3 - 4.2 = -0.9 and therefore the MOSFET is OFF.  However, the tutorial doesn't say what happens when Vgate < Vsource but by an amount less than the Vthreshold so I don't know if my math is right.

In sum my questions are:
1) Is my math and prediction of the MOSFET states correct when that 3.3V GPIO is on or off?
2) If not, is it because of some other quality in this MOSFET and a different P MOSFET would work?
3) I presume that if I keep out of the Vgs upper and lower bounds then I avoid issues where the MOSFET is in a partially on and partially off state, is that correct?
4) Is it just impossible to use P MOSFETS in this way?

Note:  My questions only pertain to P MOSFETs.  For my project (switching a 1-2A disco light toy), it has to be a high side switch and that's even besides the point because I am more importantly trying to understand how the P channel mosfets work.

  [1]: https://cdn-shop.adafruit.com/datasheets/1794datasheet.pdf
  [2]: https://www.baldengineer.com/p-channel-mosfet-tutorial-with-only-positive-voltages.html

title: Switching 4.2V circuit with 3.3V Arduino GPIO

Answers: 1

body: The MOSFET you chose will probably fail. Using a 30V device on a 24V system is asking for problems. Go to a minimum of a 60V MOSFET and use a UIS, Avalanche rated one. R4 is very week for what you need to do, I would suggest something in the 10K range to swamp out any leakage in the Arduino. If the MOSFET is properly rated the flyback diode is not needed but make a space for it incase you have to sub a MOSFET. Putting C2 in parallel with C1 will help. I do this a lot with electrolytics. I double up each one the needed size when one fails you don't notice it. I would suggest a couple of 220nF caps across the motor but that is application dependent.


body:
I've looked at previous questions regarding sketch extraction and know that it is possible to extract the hex code from an Arduino board using avrdude from the command line.

However, I want to see if the following is possible:

 1. Connect to Arduino 33 IoT board
 2. Extract onboard Firmware as a hex file
 3. Disconnect from Arduino 33 IoT board.

I understand that getting the initial source code is not possible, but I am in particular looking to just get the hex code in a wireless manner. If it is not possible via the Arduino 33 IoT board, is there any Arduino board with which this can be done? Any help or guidance would be appreciated.

title: Is it possible to extract the firmware of an Arduino BLE or IoT board wirelessly?

Answers: 1

body:
Technically, the firmware can read its own application section, but it won't send it to you wirelessly (or via any interface) if such a feature isn't implemented in that firmware. If you were to implement the firmware yourself, you can do (almost) anything. But if it is a third party firmware, this will not be possible.

The reason this works with arduinos and avrdude is, because firmware up- and download are implemented in hardware (ISP, works without a bootloader).


body:
I connected my motor and a servo to my L293D motor shield and i used a 3.7 volt battery with 4800 mAh. I also connected a button to on and off the motor for a certain amount of time but only the servo is working properly while my motor doesn't run.

HERE IS THE CODE
``` int LEDState=0;
int LEDPin=11;
int buttonPin=4;
int buttonNew;
int buttonOld=1;
int dt=100;
#include <Servo.h>
#include <AFMotor.h>
Servo myservo;
int servopin(10);
AF_DCMotor motor1(1);

void setup(){
  Serial.begin(9600);
  pinMode(LEDPin,OUTPUT);
  pinMode(buttonPin,INPUT);
  myservo.attach(servopin);
  motor1.setSpeed(200);
}

void loop(){
  buttonNew=digitalRead(buttonPin);
  if(buttonOld==0 && buttonNew==1){
    if (LEDState==0){
      digitalWrite(LEDPin,HIGH);
      myservo.write(0);
      Serial.print(buttonOld);
     int motorpos='0';
     int motorpos2='1';
      if (motorpos=='0'){
        motor1.run(FORWARD);
        delay(2000);
        motorpos='1';
      }
      if(motorpos='1'){
        motor1.run(RELEASE);
      }
       LEDState=1;
    }
    else{
      digitalWrite(LEDPin,LOW);
      myservo.write(90);
      Serial.print(buttonNew);
      int motorpos='0';
      int motorpos2='1';
      if (motorpos=='0'){
        motor1.run(BACKWARD);
        delay(2000);
        motorpos='1';
      }
      if (motorpos='1'){
        motor1.run(RELEASE);
      }
        LEDState=0;
    }
  }
  buttonOld=buttonNew;
  delay(dt);
}
```

title: Problem with my motor and L293D motor shield module

Answers: 0