message:
Cannot receive IR codes after sending IR on same Arduino (I have irrecv.enableIRIn();)

I have two Arduinos with identical wiring, they will (hopefully) end up being laser guns for my younger cousins.

When they both have a sketch which simply toggles lights when the correct IR code is received, everything works as it should. see the code here:

// Start of sketch 1

    #include <IRremote.h>
    IRsend irsend; //Setup the IR transmitter
    int receiver = 8; //initialize pin 13 as receiver pin.
    IRrecv irrecv(receiver); //create a new instance of receiver
    decode_results results;

    // declare consants
    const int trigger = 13;
    const int greenLight = 7;
    const int yellowLight = 2;
    const int timeBetweenTransmittion = 800;

    // declare variables
    bool toggleGreen = true;
    bool toggleYellow = true;
    long int previousTransmittion = 0;

    // put your setup code in here, to run once:
    void setup()
    {
      pinMode(trigger, INPUT_PULLUP);
      Serial.begin(9600); // send code at 9600 bits per second
      irrecv.enableIRIn(); // start the receiver
    }

    // put your main code in here, to run repeatedly:
    void loop() {
      if (not digitalRead(trigger) && millis() > previousTransmittion + timeBetweenTransmittion) // if the button is pressed and it's been enought time since the last transmittion
      {
        Serial.println("send!");
        irsend.sendNEC(1367857, 32); // send the code
        irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
        previousTransmittion = millis(); // set the record for latest transmittion to the currnt time

        // toggle the yellow light
        digitalWrite(yellowLight, toggleYellow);
        toggleYellow = not toggleYellow;
      }

      if (irrecv.decode(&results)) { // if we have received an IR signal
        Serial.println (String(results.value, HEX)); //display HEX results
        if (String(results.value, DEC) == "1367857")
        {
          Serial.println("correct code");
          // toggle the green light
          digitalWrite(greenLight, toggleGreen);
          toggleGreen = not toggleGreen;
        }
        irrecv.resume(); // it stops the receiver when something's received so we muct resume the ir receiver
     }
    }

// End of sketch 1

The receiver is on pin 8 and, button on pin 13 and transmitting LED is always on pin 3.

No issues there.

However, when I use the same concepts on a larger-scale project, a strange problem occurs. Once one of the Arduinos has sent some IR, the receiver no longer works. After every line of code which sends IR, I follow it with `irrecv.enableIRIn();`, and after every time it receives code I have the line `irrecv.resume();`. I can't work out what the problem is. It's very long, but the full code is below:

// Start of code 2

    // include the library code:
    #include <LiquidCrystal.h> // For the LCD
    #include <IRremote.h> // For the IR communication
    #include <PCM.h> // For the audio output

    const unsigned char gunShot[] PROGMEM = {}; // In the program this contains a huge array of notes, I removed them to save space

    const unsigned char gunClick[] PROGMEM = {}; // In the program this contains a huge array of notes, I removed them to save space

    // Declare consants for pins
    const int rs = A0, en = A1, d4 = A2, d5 = A3, d6 = A4, d7 = A5; // State constants for all the pins used for the LCD
    const int trigger = 13;
    const int redLight = 7;
    const int magReader1 = 9;
    const int magReader2 = 10;
    const int speaker = 11;
    const int healButton = 12;
    const int receiver = 8;
    const int muzzle = 2;

    // Declare constants for gameplay
    const int timeBetweenShots = 800; //(in 1000ths of a second)

    const int healAmount = 100;

    const int medicAmmo = 16;
    const int assultAmmo = 31;
    const int sniperAmmo = 1;

    const int medicDamage = 30;
    const int assultDamage = 23;
    const int sniperDamage = 75;

    const int playerNumber = 4;

    // Declare all valiables
    int timesKilledByTeam1 = 0; // I would loved to have used an array here, but for some reason an array broke the program
    int timesKilledByTeam2 = 0;
    int timesKilledByTeam3 = 0;
    int timesKilledByTeam4 = 0;
    int timesKilledByTeam5 = 0;
    int timesKilledByTeam6 = 0;
    int timesKilledByTeam7 = 0;
    int timesKilledByTeam8 = 0;

    String receivedCode = ""; // Store the received code in a string variable
    bool gameDone = false;

    bool semiCanShoot = true;
    bool gunShouldClick = true;

    int health = 100;
    int gameMode = 1; // 1=TDM, 2=FFA, 3=LTS, 4=LPS
    bool respawn = true;
    int teamOrPlayer = playerNumber;
    int loadStatus; // 0 is no mag, 1 is mag1, 2 is mag2

    int mag1Ammo; // Current ammo in mag1
    int mag2Ammo; // Current ammo in mag2
    int maxAmmo; // Ammo in one mag for the selected class
    int damage; // Damage this player is inflicting per shot

    long int timeOfFlash = 0;
    long int timeOfMuzzle = 0;
    long int timeOfLastShot = 0;
    long int loopTimer = 0;

    int gameStartTime; // In seconds so no need for long int
    //int secondsRemaining;
    int gameDuration;

    int playerClass = 0; // 0=Medic, 1=Asult, 2=Snipr

    int shootCode;

    IRsend irsend; //Setup the IR transmitter
    IRrecv irrecv(receiver); //create a new instance of receiver
    decode_results results;
    LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

    void SetupClass()
    {
        switch (playerClass)
        {
            case (0):
              maxAmmo = medicAmmo;
              damage = medicDamage;
              break;
            case (1):
              maxAmmo = assultAmmo;
              damage = assultDamage;
              break;
            case (2):
              maxAmmo = sniperAmmo;
              damage = sniperDamage;
              break;
        }
        mag1Ammo = maxAmmo;
        mag2Ammo = maxAmmo;
    }

    // Define subroutines
    //void QuickDisplayUpdate(int ammo, int secondsRemaining, int loadStatus, int health) // During a game, to save unnecessary computation, only update the things that might have changed during the game
    void QuickDisplayUpdate()
    {
        lcd.setCursor(11,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) / 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(12,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) / 60));

        lcd.setCursor(14,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) % 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(15,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) % 60));

        lcd.setCursor(7,1); // Put the / in as it might have been removed from a previous "Reload!"
        lcd.print("/");

        lcd.setCursor(0,1);
        if (loadStatus == 0) lcd.print("Reload!");
        else if (loadStatus == 1)
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag1Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag1Ammo));
        }
        else
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag2Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag2Ammo));
        }

        lcd.setCursor(13,1);
        if(health < 100)
        {
          lcd.print(" ");
          lcd.setCursor(14,1);
          if(health < 10)
            {
              lcd.print(" ");
              lcd.setCursor(15,1);
            }
        }

        lcd.print(String(health));
    }

    void FullDisplayUpdate(int teamOrPlayer)
    {
        lcd.clear();
        lcd.setCursor(0,0);
        switch (gameMode)
        {
            case (1):
              lcd.print("TDM");
              break;
            case (2):
              lcd.print("FFA");
              break;
            case (3):
              lcd.print("LTS");
              break;
            case (4):
              lcd.print("LPS");
              break;
        }

        lcd.setCursor(3,0);
        lcd.print(String(teamOrPlayer));

        lcd.setCursor(5,0);
        switch (playerClass)
        {
            case (0):
              lcd.print("Medic");
              break;
            case (1):
              lcd.print("Asult");
              break;
            case (2):
              lcd.print("Snipr");
              break;
        }

        lcd.setCursor(11,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) / 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(12,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) / 60) + ":");

        lcd.setCursor(14,0);
        if((gameDuration - (millis() / 1000 - gameStartTime)) % 60 < 10)
        {
          lcd.print("0");
          lcd.setCursor(15,0);
        }
        lcd.print(String((gameDuration - (millis() / 1000 - gameStartTime)) % 60));

        lcd.setCursor(0,1);
        if (loadStatus == 0) lcd.print("Reload!");
        else if (loadStatus == 1)
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag1Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag1Ammo));
        }
        else
        {
          lcd.print("Mag" + String(loadStatus) + ":");
          lcd.setCursor(5,1);
          if (mag2Ammo < 10)
          {
            lcd.print("0");
            lcd.setCursor(6,1);
          }
          lcd.print(String(mag2Ammo));
        }

        lcd.setCursor(8,1);
        if (maxAmmo < 10)
        {
          lcd.print("0");
          lcd.setCursor(9,1);
        }
        lcd.print(String(maxAmmo));

        lcd.setCursor(11,1);
        lcd.print("H:" + String(health));

    }

    void Play()
    {
      gameDone = false; // When the game starts, the game isn't done

      FullDisplayUpdate(teamOrPlayer); // Fully update the display before the game starts

      // Setup the shoot code
      if(damage > 9) shootCode = (String(teamOrPlayer) + String(damage) ).toInt();
      else shootCode = (String(teamOrPlayer) + "0" + String(damage)).toInt();

      // Wait until either a start or cancel code is recieved
      Serial.println("wait");
      receivedCode = "";
      //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
      while (receivedCode.length() != 2 && receivedCode.length() != 4)
      {
        if (irrecv.decode(&results))
        {
          receivedCode = String(results.value, DEC); // Store the received code in a variable when we have received an IR signal
          irrecv.resume(); // Remove the code
        }
      }

      Serial.println("code: " + receivedCode);

      gameStartTime = millis() / 1000; // Set the game start time in seconds

      if (String(receivedCode) == "50") // If the received code was starting code (50) then play
      {
          Serial.println("strt, dur: " + String(gameDuration) + "team: " + String(teamOrPlayer));

          while (gameDone == false) // Repeat until the game is done
          {
              //Serial.println("Game loop");

              CheckForIR(); // Check for an IR code as often as possible

              if (playerClass == 0) // Only check for heal button if they are a medic
              {
                if (not digitalRead(healButton) && millis() > timeOfLastShot + timeBetweenShots) // If they are pressing the heal button and it's been enought time since last shot
                {
                    Serial.println("heal bttn");
                    if (loadStatus == 1 && mag1Ammo == maxAmmo) // If mag1 is in and it's full
                    {
                        Serial.println("heal 1");
                        irsend.sendNEC((String(teamOrPlayer) + "00").toInt(), 32); // Send the heal code
                        //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                        digitalWrite(muzzle, 1); // Turn on the muzzle flash
                        timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                        //startPlayback(healShot, sizeof(healShot)); // Play  heal sound
                        mag1Ammo = 0; // Empty the current mag
                    }
                    else if (loadStatus == 2 && mag2Ammo == maxAmmo) // If mag2 is in and it's full
                    {
                        Serial.println("heal 1");
                        irsend.sendNEC((String(teamOrPlayer) + "00").toInt(), 32); // Send the heal code
                        //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                        digitalWrite(muzzle, 1); // Turn on the muzzle flash
                        timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                        //startPlayback(healShot, sizeof(healShot)); // Play  heal sound
                        mag2Ammo = 0; // Empty the current mag
                    }
                }
              }

              CheckForIR();

              if (not digitalRead(trigger) && (millis() > timeOfLastShot + timeBetweenShots)) // If the trigger is pulled and it's been long enough since last shot
              {
                  Serial.println("sht bttn");
                  if (loadStatus == 1 && mag1Ammo > 0) // If mag1 is in and it has ammo
                  {
                      if (playerClass != 0 || semiCanShoot == true) // They can shoot if they are on full auto or if semi can shoot
                      {
                          Serial.println("1 sht");
                          irsend.sendNEC(shootCode, 32); // Send the shoot code
                          irrecv.enableIRIn(); // Start the receiver
                          digitalWrite(muzzle, 1); // Turn on the muzzle flash
                          timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                          mag1Ammo = mag1Ammo - 1; // Reduce ammo of current mag by one
                          semiCanShoot = false; // Once they have shot, they cannot shoot again if on semi mode
                          startPlayback(gunShot, sizeof(gunShot)); // Play shot
                          Serial.println("1 sht done");
                      }
                  }

                  else if (loadStatus == 2 && mag2Ammo > 0) // If mag2 is in and it has ammo
                  {
                      if (playerClass != 0 || semiCanShoot == true) // They can shoot if they are on full auto or if semi can shoot
                      {
                          Serial.println("2 sht");
                          irsend.sendNEC(shootCode, 32); // Send the shoot code
                          irrecv.enableIRIn(); // Start the receiver
                          digitalWrite(muzzle, 1); // Turn on the muzzle flash
                          timeOfMuzzle = millis(); // Set the time of the muzzle turning on
                          mag2Ammo = mag2Ammo - 1; // Reduce ammo of current mag by one
                          semiCanShoot = false; // Once they have shot, they cannot shoot again if on semi mode
                          startPlayback(gunShot, sizeof(gunShot)); // Play shot
                          Serial.println("2 sht done");
                      }
                  }

                  else if (gunShouldClick) // (If no mag in OR no ammo in the mag that's in) AND gun should click
                  {
                      Serial.println("clik");
                      startPlayback(gunClick, sizeof(gunClick)); // Play click sound
                      gunShouldClick = false; // Gun shouldn't click again until they releace trigger
                  }
                  timeOfLastShot = millis(); // Update the time of last shot
                  Serial.println("shot done");
              }

              CheckForIR();

              // Check for if the gun should click again and if player can shoot again if on semi mode
              if (digitalRead(trigger)) semiCanShoot = true; // If they are not holding the trigger, they can shoot again if on semi mode
              if (digitalRead(healButton) && digitalRead(trigger)) gunShouldClick = true; // If they are not holding the trigger or the heal button, the gun should click again when they do hold it again

              CheckForIR();

              // If the LEDs have been on for long enough, turn them off
              if (millis() > timeOfFlash + 50) digitalWrite(redLight, 0); // Turn off the red LEDs if they have been on for enough time
              if (millis() > timeOfMuzzle + 50) digitalWrite(muzzle, 0); // Turn off the muzzle if it's been on for enough time

              CheckForIR();

              if (millis() > loopTimer + 250) // Some things need to be done less often, so do that to save time so IR receive checks can be done more frequently
              {
                  loopTimer = millis();

                  QuickDisplayUpdate(); // Quick update the display after every loop

                  CheckForIR();

                  // Update the loadStatus variable depending on the mag detector inputs
                  if (!digitalRead(magReader1) && digitalRead(magReader2))
                  {
                      loadStatus = 1;
                      mag2Ammo = maxAmmo; // Refil mag2 if mag one is in
                  }
                  else if (!digitalRead(magReader2) && digitalRead(magReader1))
                  {
                      loadStatus = 2;
                      mag1Ammo = maxAmmo; // Refil mag1 if mag two is in
                  }
                  else loadStatus = 0;

                  CheckForIR();

                  // Check to see if the game has reached the time limit
                  if (gameDuration - (millis() / 1000 - gameStartTime) < 1)
                  {
                    Serial.println("tm up");
                    gameDone = true;
                  }
              }

          } // Game is done

      } // If the received code wasn't the starting code then cancel the game and return to waiting menu
    }

    void CheckForIR()
    {
      //Serial.println("check");
      //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
      if (irrecv.decode(&results)) // If there is a code
      {
          receivedCode = String(results.value, DEC); // Store the received code in a string variable
          Serial.println(receivedCode);
          irrecv.resume(); // Remove the code
          if (receivedCode.length() == 3) // If the received code has length 3, we have been shot
          {
              Serial.println ("shot"); //display shot code
              if (receivedCode.substring(0,1) != String(teamOrPlayer)) // Only continue if the shooter is on another team
              {
                  Serial.println ("another team");
                  digitalWrite(redLight, 1); // Turn on the red lights
                  health = health - (receivedCode.substring(1, 3).toInt()); // Reduce health by incoming damage, if it's an enemy heal it won't have an effect
              }
              else if (receivedCode.substring(1, 3).toInt() == 0)
              {
                Serial.println("heal");
                health = health + healAmount; // Heal if they are a teammate and they are doing 0 damage
              }

          }

          if (health > 100) health = 100; // Set back to 100, cannot be on over 100 health
          else if (health < 1)
          {
              Serial.println ("died");
              switch(receivedCode.substring(0,1).toInt()) // Increment's the killer's kills by one
              {
                case (1):
                  timesKilledByTeam1++;
                  break;
                case (2):
                  timesKilledByTeam2++;
                  break;
                case (3):
                  timesKilledByTeam3++;
                  break;
                case (4):
                  timesKilledByTeam4++;
                  break;
                case (5):
                  timesKilledByTeam5++;
                  break;
                case (6):
                  timesKilledByTeam6++;
                  break;
                case (7):
                  timesKilledByTeam7++;
                  break;
                case (8):
                  timesKilledByTeam8++;
                  break;
              }

              health = 100; // Reset the health
              mag1Ammo = maxAmmo; // Refil the mags
              mag2Ammo = maxAmmo;

              // Update the LCD
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("You died!");
              lcd.setCursor(0,1);
              lcd.print("Return to base");

              if (respawn == false) gameDone = true; // If playing one life gamemode, end game
              else // Otherwise wait until respawn code is recieved
              {
                  //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                  while ((receivedCode != "50") && (gameDuration - (millis() / 1000 - gameStartTime) > 1)) // Keep looking for IR siginal until it's 50 or the time's up
                  {
                      //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
                      if (irrecv.decode(&results)) // if we have received an IR signal
                      {
                          receivedCode = String(results.value, DEC); // Store the received code in received code variable
                          irrecv.resume();
                      }
                  }
              }
              FullDisplayUpdate(teamOrPlayer); // Reset the LCD to gameplay mode

          }
      }
    }

    void setup()
    {
      lcd.begin(16, 2); // Set up the LCD's number of columns and rows
      Serial.begin(9600); // Send code at 9600 bits per second
      irrecv.enableIRIn(); // Start the receiver
      pinMode(trigger, INPUT_PULLUP);
      pinMode(magReader1, INPUT_PULLUP);
      pinMode(magReader2, INPUT_PULLUP);
      pinMode(healButton, INPUT_PULLUP);
    }

    void loop() // Repeat while looking for game (between games)
    {
        Serial.println("\nlp");
        digitalWrite(redLight, 1); // Turn on the lights to show player isn't playing at the moment

        // Print waiting screen to LCD
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("Awaiting start");
        lcd.setCursor(0,1);
        lcd.print("Player: " + String(playerNumber));

        //irrecv.resume();//  NOT YET TESTED
        //irrecv.enableIRIn(); // sending ir stops the receiver so start the receiver again
        while (not irrecv.decode(&results)) // wait until we have received an IR signal
        {
            // Transmit previous game data while we wait
            //Serial.println("wait");
        }

        receivedCode = String(results.value, DEC); // Store the received code in a string variable
        Serial.println(receivedCode); //display results
        irrecv.resume();

        if (receivedCode.length() == 4) // It was a sucessfull transmission if the recieved code was 4 characters long
        {
          playerClass = receivedCode.substring(3, 4).toInt(); // Set the class to the recieved class
          Serial.println("clss: " + String(playerClass));
          SetupClass();

          gameDuration = 180 * (receivedCode.substring(1,2).toInt() + 1); // Set the time remaining and game duration to the received time
          Serial.println("tm lft" + String((gameDuration - (millis() / 1000 - gameStartTime))) + ", gameDuration: " + String(gameDuration));

          // Reset the death counter as a new game is starting
          int timesKilledByTeam1 = 0;
          int timesKilledByTeam2 = 0;
          int timesKilledByTeam3 = 0;
          int timesKilledByTeam4 = 0;
          int timesKilledByTeam5 = 0;
          int timesKilledByTeam6 = 0;
          int timesKilledByTeam7 = 0;
          int timesKilledByTeam8 = 0;

          health = 100;

          switch (receivedCode.substring(0, 1).toInt()) // Do operations based on the received game mode
          {
              case (1): // TDM
                Serial.println("TDM");
                gameMode = 1;
                teamOrPlayer = receivedCode.substring(2, 3).toInt();
                respawn = true;
                Play(); // Call play with received team and respawn on
                break;

              case (2): //FFA
                gameMode = 2;
                Serial.println("FFA");
                respawn = true;
                teamOrPlayer = playerNumber;
                Play(); // Call play with player number and respawn on
                break;

              case (3): // LTS
                gameMode = 3;
                Serial.println("LTS");
                respawn = false;
                teamOrPlayer = receivedCode.substring(2, 3).toInt();
                //Play(); // Call play with received team and respawn off
                break;

              case (4): // LPS
                gameMode = 4;
                Serial.println("LPS");
                respawn = false;
                teamOrPlayer = playerNumber;
                //Play(); // Call play with player numebr and respawn off
                break;

              default:
                Serial.println("Unknown Gamemode");
                break;
          }

        }

    }

// End of code 2

I know this code is a mess, I should not be using global variables and there should be more subroutines, but I wrote most of it before remembering about them :/

If I run the sketch and don't "shoot" on that reset, the code works fully as intended, but the "times killed by player x" variables section I haven't got to yet.

Extra information which I don't think is relevant:

There is a third Arduino which allows you to choose a code and send it, or send the code "50". This is the "base" which someone must return to in order to respawn, as it's the only thing which can send the code "50". The codes it can send are explained below:

It sends a 4-digit number, but it's read as 4 separate numbers, for example, consider the code "rspq". The r is the game mode (1=team respawn, 2=free for all, 3=last team standing, 4=last player standing), s is the duration of the game (time(s) = 3 * (s + 1), resulting in possible times of 3,6,9...30), p is the team that that player is on (when playing a team game)(when not playing a team game it just uses the player ID stored on that particular gun) and q is the class (1=medic, 2=assault, 3=sniper).

There is a lot to say so if you have any questions just ask.

Any help/ideas would be appreciated, thanks in advance.

body: It would appear that the audio aspect of my larger program was interfering with the IR receiver, as every time I send IR I also play a sound. It was the sound which was stopping the receiver, not the IR transmitter. When I removed the sound from the sketch, it worked as intended. Thanks timemage for your help.


sender: user

message:
2 stepper cnc inaccurate

I'm building a simple cnc machine that just writes letters. It uses 2 steppers for x and y axis.

Here is how it works

1. generate letters in c# and convert them to list of lines
2. send to arduino mov_xy line.x line.y as string for each line
3. on arduino convert to int, multiply by steps per mm and run with speedy stepper

It eventually builds up to accuracy problems.
If it's writing "ZWX", letter "X" would be slightly to the side.

Things i tried:
- 500000 baud rate
- accumulate remainder of float number of steps
- different usb cables
- different cnc machines

It is serial communication error?

Do i need to implement CRC?

Can UNO handle this?

Does SERIAL_8E1 do parity check automatically or do i need do something?

I went trough everything many times.
What am i missing here?

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

This image is generated directly from letter lines in c#, so i doubt the problem is on c# side.

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

sender: assistant

body:
I forgot to take care of negative steps in remainder accumulation.
This solved it.

    // x accum
    float resX = mmX * (float)X_STEPS_PER_MM;
    float lresX = (long)resX;
    _x_acum += resX - lresX;

    long extraStepsX = 0;
    while(_x_acum > 1.0f){
         _x_acum -= 1.0f;
         ++extraStepsX;
    }

    while(_x_acum < -1.0f){
         _x_acum += 1.0f;
        --extraStepsX;
    }
    // move stepper for lresX + extraSteps


message:
RF sniffer with Arduino

Hello programmers out in the world.
I am doing a capstone project for an RF sniffer to capture RF signals from Key fobs within an OEM manufacturing plant. I want to be able to decode this RF signal to show me what the battery state of the key fob is. I have the protocol, so I know what data I should be receiving. However, I have tried many libraries on the Arduino UNO and none have worked.
This Key fob specs are FSK modulation. Frequency of 433 Mhz, Bit rate -> 9.6Kbit/s, baud rate of 19.2Kbaud/s and coding is manchester.

Any help would be greatly appreciated.

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

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

body:
I actaully found this this week that I was suing ASK RF receiver module, when I needed FSK.
I have used RC Switch, and no luck, along with Radio head.
However as mentioned the key fob will not work with ASK. I am trying to find a library for FSK but no luck as of now.

-Pete


message:
How to use 3 digital input pins on Arduino Uno for frequency inputs and total the output?

I am working on a Arduino tachometer that reads the RPM of a BLDC motor. The motor circuit does not use the hall sensors so I would like to use them for RPM sensors. I have already hooked up an Uno board using one pin as an input with the internal pull up enabled and it works fine.The reason I want to use all 3 hall sensors is to increase the pulse count per revolution to steady the reading on my LCD display at lower speeds.
I have been searching for information on how to read 3 inputs, and totalize the pulses for this purpose but have not been able to find the information.

body:
Assuming that only one sensor will trigger each time then (as jsotola suggested) tie them together and connect the common output to an interrupt pin. Arduino UNO has interrupt functionality on pins 2, 3.

As an example for counting the pulses using pin2 on falling edge (modified from https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/):

    const byte interruptPin = 2;
    volatile int numPulses = 0; // change type of variable according your needs

    void setup() {
        pinMode(interruptPin, INPUT_PULLUP);
        attachInterrupt(digitalPinToInterrupt(interruptPin), sumPulses, FALLING);
        Serial.begin(9600);
    }

    void loop() {
        Serial.println(numPulses);
        delay(500);
    }

     void sumPulses { // keep the ISR as short as possible
        numPulses++;
     }


body:
An alternative method of frequency determination is to measure period and take the reciprocal. It can be extremely accurate and responsive at very low frequencies, so you don't need to combine multiple sensors just to increase the rate.

Note that you are not limited to measuring a single period; you can count the microseconds in N periods to increase resolution at high frequencies.


message:
Doing several things at the same time with functions, objects or interrupts?

First of all, thank you for taking the time to read this. I am a newbie, so apologies (done examples on arduino website, basic C++).

I'm trying to get an idea of what the best way to structure a sketch is, which needs to do several things at the same time. For example, reading an IMU sensor and using it to control the mouse, reading a button for on/off and let's say flashing an LED. I have repetitive injury so this is the project I'm trying to complete, but the principle should be scalable for more complex projects.

I've come across some great resources and my understanding is you can use:

 1. [functions (e.g. blink without delay)][1]
 2. [objects (cooperative multitasking)][2]

 3. [interrupts][3]
 4. [something like a RTOS][4]

Where my limits lie is understanding the benefits/limitations of these options and picking which one to focus on for my project. For example, if using functions is sufficient, why do people bother with interrupts and installing a RTOS?

I would appreciate any guidance for what an effective approach should look like.

Thanks again.

  [1]: https://forum.arduino.cc/index.php?topic=223286.0
  [2]: http://paulmurraycbr.github.io/ArduinoTheOOWay.html
  [3]: https://www.allaboutcircuits.com/technical-articles/using-interrupts-on-arduino/
  [4]: https://www.freertos.org/about-RTOS.html

body:
An RTOS may be a good option for running a complex application on a
quite powerful Arduino. Many Arduinos (the AVR-based ones), however, are
too limited to run complex applications, and the overhead of an RTOS is
quite significant for them. In this case you end up with two options:

* non-blocking programming
* interrupts

Whichever is best depends on the specific tasks you are managing.

### Non-blocking programming

This is best exemplified by the [Blink Without Delay][] Arduino
tutorial. The general principle is to break down you code into small
non-blocking tasks, and perform each one only when it is the right time
to do so. Breaking down the program logic into a set of non-blocking
tasks is not always completely trivial, but you can use a [Finite state
machine][fsm], which is a very powerful and general concept for doing so
in a systematic way.

Once all task are non-blocking, the main program loop then looks like
this pseudo-code:

```c++
void loop() {
    if (task_1_should_be_performed_now()) {
        perform_task_1();
    }
    if (task_2_should_be_performed_now()) {
        perform_task_2();
    }
    // etc...
}
```

Most of the time, all conditions are false, and the program swifts
through the tests completing the loop in a very short time.
Occasionally, it performs one of the tasks, which makes the loop longer
but, since the tasks never block, not very long anyway. Typical loop
time is highly dependent on the specifics of your code, but I would
expect it to be no more than one millisecond most of the time.

This is probably the most common pattern for multitasking on the
Arduino. You can encapsulate this logic in functions, objects,
libraries, etc. This is the approach I would recommend provided none of
your tasks is so urgent that it cannot wait for one loop iteration.

### Interrupts

Occasionally, you may have a task that is so urgent that it cannot wait
for the next loop iteration. It has to be performed right now. Or maybe
the loop takes a very long time because of a blocking call in a library
you have no control over. In those situations, an interrupt may be the
best option.

Interrupts come with some tricky programming issues, which require some
precautions on the part of the programmer:

* they block other interrupts, increasing their latency → interrupt
  service routines should be as short as possible

* they can cause problems with non-reentrant library functions → those
  functions should be avoided in interrupt context

* they can interact badly with the optimizer → variables used in both
  interrupt context and normal context should be qualified as
  `volatile`

* they can cause synchronization issues with the data shared with the
  main code → access to that data in normal context should be protected
  in critical sections.

For all these reasons, it is best to use interrupts only when needed,
i.e. only when a task cannot wait for the next iteration of `loop()`.

[Blink Without Delay]: https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
[fsm]: https://majenko.co.uk/blog/finite-state-machine


message:
Can I use the microchip of Arduino Uno as a standalone microcontroller

I want use the `ATmega328P` chip of the `Arduino Uno` board as a **standalone** device.

 - Is that possible?
 - Which pins are which on the Arduino board and the `ATmega328P`?
 - Do I need any external components?

body:
Yes it's possible. To use the ATmega328P to "emulate" an Arduino Uno board (without the USB part) you just need 3 ou 4 additional components: the oscillator, two capacitors and a resistor. Please take a look at: https://www.arduino.cc/en/Tutorial/BuiltInExamples/ArduinoToBreadboard for a schematic/breadboard.
The Atmega328P features itself the memory, cpu and flash so those components are already inside the chip. You can find the relation of the pins in this image: [![Pin matching][1]][1]

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


body:
You can check the [UNO's schematic](https://www.arduino.cc/en/uploads/Main/arduino-uno-schematic.pdf). You can use this as a starting position. You can leave out the things you don't need. You might for example have no need for a voltage regulator on your board.

You may also have a look at the [schematic of the Pro Mini](https://www.arduino.cc/en/uploads/Main/Arduino-Pro-Mini-schematic.pdf), which are a lot more bare-bones.


message:
Arduino - Function -> return Cstr instead of string

I have following function for my Arduino:

    String readLine() {
      String received = "";
      char ch;
      while (myFile.available()) {
        ch = myFile.read();
        if (ch == '\n' or ch == '\r') {
          if (ch == '\r')
          {
            //get rid of the \n
            myFile.read();
          }
          return String(received);
        } else {
          received += ch;
        }
      }
      myFile.close();
      hasFile = false;
      return received;
    }

This function is used to return a line from a text file on a SD card. Since I do have to do quite some things on the returned string, I would like to have it as cstr instead of string to increase performance. But I am not able to convert this function to one that returns a Cstr. I tried this but it does not work:

    char* readLine() {
      char* received = "";
      char ch;
      while (myFile.available()) {
        ch = myFile.read();
        if (ch == '\n' or ch == '\r') {
          if (ch == '\r')
          {
            //get rid of the \n
            myFile.read();
          }
          return received;
        } else {
          received += ch;
        }
      }
      return received;
    }

Currently I am converting it after the function returns it, by using `c_str()`. It works, but I dont like it and would like to return a Cstr in the first place.

How can this be done?

Thank you!

body:
You cannot work with c-strings like with `Strings`. You need to use the standard c-string functions (like `sprintf()`, `strcpy()` and siblings) or directly access the `char` array.

This gives the following problems with your code:

- See this line:

        char* received = "";

    Here you create a pointer to a constant empty string. But this will **NOT** create a buffer, where you can put data. If you want to define a buffer to put the data in, you need to define an array:

        char received[30] = "";

    where `30` is the size of the array and thus the buffer has space for 29 characters (30 minus the one character, that is needed for the terminating null character). Now you could use a counter variable to save the current position in the buffer and set the array elements to the received character:

        int position = 0;
        ...
        received[position] = ch;
        position++;

    Then, when you reached the end of the buffer or you received end of line, you would end the data in the buffer with the null character:

        if (ch == '\n' || ch == '\r' || position == 29) {
            if (ch == '\r')
            {
                //get rid of the \n
                myFile.read();
            }
            received[position] = '\0';

- Now you have the second problem: When defining a variable inside the function, it will become invalid, when you exit the function. You try to return a pointer to `char`, which will point to a non-valid memory location. Thus you cannot simply return an array, that was created inside the function (outside of dynamic allocation). Here commonly an external buffer is provided to the function by reference as a pointer. The function will then write into that buffer and does not need to return it.

        //defining the array outside of the function, for example at global scope
        #define BUFFER_SIZE  30
        char received[BUFFER_SIZE] = "";
        ...
        void readLine(char *buffer, int size) {
            ...
            // Here you can use buffer as a simple char array
            buffer[position] = ch;
        }

    Here I also provide the size of the array as parameter, so that the function can make sure not to exceed that (because that will give you bad and difficult to troubleshoot problems). Then, when the function has run, the read data is now in the `received` character array. This way you don't need to use multiple buffers and also don't need to copy data between buffers.


body:
One way is passing external buffer to readLine() to fill:

    size_t readLine(char * buff, size_t maxChars) {
      size_t pos = 0; // current position in buffer
      while (file.myFileAvalable()) {
        buff[pos] = file.read();
        if (buff[pos] == '\n' || buff[pos] == '\r') {
          buff[pos] = '\0';   // terminate string
          break;              // end the loop
        }
        if (++pos == maxChars-1) { // don't forget about nul terminal character
          buff[pos] = '\0';
          break;              // end the loop
        }
      }
      return pos; // return number of read characters (0 nothing was read)
    }

    /// ...

    char ssid[25] = {0}; // create buffer to store at most 24 characters + \0
    char pass[25] = {0}; // it'll also fill buffers by zeroes

    readLine(ssid, sizeof(ssid)-1);  // it'd be better to check how many characters was read
    readLine(pass, sizeof(pass)-1);  // same here

    WiFi.begin(ssid, pass);
    /// ... But it looks much worst than String, however it's much more efficient, as using += for Strings is quite heap unfriendly

**Big NO-NO is doing something like:**

    char* readLine() {
      char buff[50] = {0};
      // ... fill ...
      return buff;           // NO!!!! buffer doesn't exist after the return - you've got dangling pointer
    }
    // ...
    char * ssid = readLine(); // dangling pointer after that...
    char * pass = readLine(); // now the ssid location was overwritten for sure

**Another NO-NO:**

    char* readLine() {
      static char buff[50] = {0}; // one buffer for all calls, it won't get destroyed after the end... but
      // ... fill ...
      return buff;           // ok, buffer exists after the return,...
    }
    // ...
    char * ssid = readLine(); //
    char * pass = readLine(); // but surprise surprise, ssid and pass points to the same buffer and therefore the same data...


message:
Arduino : send data via satellite (or other solutions ? without GSM)

I'm a researcher and I'm looking to build a very tiny embedded system. I must to send data from the desert and above the ocean, to do that I think that my single option is to use satellite transmission (and not GSM).

Thus, I found Iridium Satellite (RockBLOCK) but my main issue is that their Arduino module is too big for my project (4cm of length and too heavy).

Do you know if there is other module to send data via satellite with Arduino ?
If not, do you know other microcontroller which can do that ? (Using Arduino is not mandatory for me)

Thank you a lot,
Sincerely.

body:
My two cents: A possibility might be LoRaWAN on the 2.4GHz spectrum, for which there are also satellites in orbit.

The LoRaWAN ("Long Range Wide-Area-Network") protocol is based on a chirp-spread-spectrum (CSS) modulation and has a very high range.

I've used LoRaWAN before but not on 2.4GHz or with a satelitte, so I can't comment on the practical feasibility. However, there are some materials from The Things Conference (by The Things Network, a leading developer of LoRa network servers).

 * https://www.youtube.com/watch?v=iwocSYupdIQ
 * https://www.youtube.com/watch?v=jlNyBDxpKUw
 * https://enterpriseiotinsights.com/20190618/channels/news/lora-shoots-for-75pc-of-iot-market
* https://enterpriseiotinsights.com/20200130/channels/news/lorawan-enters-2-4gh-plus-satellite-boost-network-sharing-embedded-security
* https://www.semtech.com/company/press/semtech-and-swarm-deliver-satellite-communications-with-lora

Also maybe other modules that can talk to the Iridium satellites suite you better. Sparkfun has a few
* https://www.sparkfun.com/products/13745
* https://www.sparkfun.com/products/16394


message:
Serial monitor window opens frozen

My serial monitor window opens frozen, without any output or possibility to input, or even activate the window.
Sketch is very simple, but behavior is same even with empty sketch, so I assume problem is not in sketch. I also checked if sketch is uploaded correctly by uploading simple sketch with blinking diode, which worked.

Same behavior with Arduino Nano and Uno.

I tried to reinstall IDE, uninstalled, removed and reinstalled serial driver (ch340) with no success.

I can see Serial monitor window only on windows taskbar, it won't activate after click.

Until now I haven't had any significant problems with IDE or serial monitor for years.

[![window state][1]][1]

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

body:
Try updating the java. Also check whether the device manager shows the USB serial port without any yellow warning sign on it.
If there is a current short in the usb port that specific port will be off for safety, restarting the computer should resolve that problem.


body: Unfortunaltely, nothing worked, and after hours of trying and googling I reinstalled windows, and now Serial Monitor works correctly.


message:
Can a 12V sensor connected to a 5V output signal of an Arduino Uno

I am doing a project for object detection. But my problem is I'm using a 12V photoelectric OMRON sensor to connect with 5V Digital PWM port 3 on Arduino using normal coding. Do I need an extra circuit to step down the voltage to 5V? Can it work because the only connection between the sensor and Arduino is the output signal, the VCC and Ground are from external power. [Link to the datasheet][1] Please help me

  [1]: https://www.ia.omron.com/product/item/721/

body:
For one, you need to connect the two grounds together.

Secondly, the 12V signal will indeed fry your Arduino. Lower the voltage to just below 5V, using a voltage divider circuit. You could for example use a combinations of a 2.2kOhm and a 1.5kOhm resistor, to get around 4.9V.


body:
My favorite solution for such an application is to use an optoisolation module. In this case, the signal can have a voltage of 12 V and the output of the optoisolation module can be connected to the input of the Arduino, where the input is configured as INPUT_PULLUP.
Example of the optoisolation module:

[![PC817][1]][1]

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

In this way it is possible to connect other types of sensors and switches and the solution is universal also for other development kits, e.g. with 3V3 logic.


message:
Drawing a line at a given angle

Im attempting a device that measures lean angle. I have an ESP8266 + MPU6050 + SSD1306 setup, and I've managed to build a shaky but somewhat functioning device.

What Id like to do is use the Adafruit_SSD1306 library to call the ``` display.drawLine(x, y, x1, y1, color) ``` function and have the line drawn to the measured angle output of the MPU6050.

The screen I'm using is 128 X 64

The MPU6050 is initially laying flat at 180 degrees, but is set and displayed as 0 degrees of tilt. The line is drawn vertically on the screen and pivots around x1 and y1 at 64, 64 respectively in the middle at the bottom of the screen.

If the MPU6050 pivots left like in the picture, the angle measurement itself is roughly correct, but the line indicator is showing more like 30 degrees than 45, and gets worse the larger the angle value.
[![line indicator][1]][1]

**My code:**
```
#include <Adafruit_MPU6050.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>

const int MPU_addr=0x68;
int16_t axis_X,axis_Y,axis_Z;

Adafruit_MPU6050 mpu;
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

int minVal=265;
int maxVal=402;

double x;
double y;
double z;
int tiltAngle;
double y2;

void setup(){
  Serial.begin(9600);
  Serial.println("MPU6050 OLED demo");

  if (!mpu.begin()) {
    Serial.println("Sensor init failed");
    while (1)
      yield();
  }
  Serial.println("Found a MPU-6050 sensor");

    // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ; // Don't proceed, loop forever
  }

  display.display();
  delay(500); // Pause for 2 seconds
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setRotation(0);
}
void loop(){
  display.clearDisplay();
  display.setCursor(0, 0);

  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);
  axis_X=Wire.read()<<8|Wire.read();
  axis_Y=Wire.read()<<8|Wire.read();
  axis_Z=Wire.read()<<8|Wire.read();
    int xAng = map(axis_X,minVal,maxVal,-90,90);
    int yAng = map(axis_Y,minVal,maxVal,-90,90);
    int zAng = map(axis_Z,minVal,maxVal,-90,90);

     x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
     y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
     z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

     tiltAngle = (int) x - 180; // we want the tilt angle to be 0 degrees
     display.println(" ");
     display.println(" ");
     display.println(" ");

     // display only positive angle values for either direction of tilt
     if(tiltAngle > 0){ display.print(tiltAngle);}
     else if (tiltAngle < 0) { display.print(tiltAngle * -1);}
     else {display.print(tiltAngle);}

     display.drawLine(-tiltAngle + 64, 0,64,64,WHITE);
     display.display();
     delay(100);
}
```

Im aware that for my first y co-ordinate I will need to use some kind of formula to get the line to move down from 0 (the top of the screen) as the lean angle gets greater. I'm hoping someone could point me in the right direction for drawing the line at the angle given by the MPU6050.

I did consider using case statements for each angle value and drawing the line with fixed co-ordinates based on each angle value. But that seems too compute intensive and could take up too much of the DRAM. Is anyone aware of a simple formula I could use? Thanks for reading.

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

body:
Use trigonometry (`sin()` and `cos()`) functions to get the right x and y coordinates.

I would consider replacing your `drawLine()` command with something like this (untested) assuming the `tiltAngle` is in degrees from -90 to +90 (with 0 degrees is straight up) and you want to draw a line at this angle from the origin (63, 63) with a radius of 64.

    float tiltAngleRad = tiltAngle * DEG_TO_RAD; // convert angle to radians
    int xEnd = 63 + 64 * sin (tiltAngleRad); // Ending x-coordinate offset & radius
    int yEnd = 63 - 64 * cos (tiltAngleRad); // Ending y-coordinate offset & radius
    display.drawLine (63, 63, xEnd, yEnd);

You might have to experiment with the offset and radius but I believe this will get you close yo what you want.


message:
Building a VU meter

I am building a VU meter with two 5v neopixel rings, two potentiometers, a headphone jack and an Arduino nano. Will 5 volts 1 amp cut it, or do I need more power? FYI I'll be powering it via a DC jack once I get it working.

body:
Normally the maximum amount of current a typical LED can withstand is 20 mA. This means per color and per LED.

So if you have 60 LEDs, than you get 60 (leds) * 3 (R/G/B colors) * 20 mA = 3,600 mA.
To give some headroom I would use a 4A or 5A adapter.

However, note that probably 5 mA or 10 mA per LED would be enough to be very good visible, unless you want it to be as bright as possible.


message:
Unable to make a really basic sketch work

I've been learning how to encapsulate my code within functions, and one of the examples I worked on is a simple INPUT_PULLUP button. When I upload the sketch from the [arduino website][1] everything works, so I know it's not a hardware issue. However, with the code below the button will just not go LOW.

I just don't see what the issue is, and I'm feeling really hopeless that I can't even get the simple thing done. I would be grateful for any advice.

  [1]: https://www.arduino.cc/en/Tutorial/BuiltInExamples/InputPullupSerial

    int button_pin = 2;
    int button_state = 0;

    void setup() {
      Serial.begin(9600);
      pinMode(button_pin, INPUT_PULLUP);
    }

    void loop() {
      Button();
    }

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

body:
    #define button_pin 2  //defining button pin as pin 2
    bool button_state = 0; //button state is either 0/1 so using bool
    void Button();
    void setup()
    {
        Serial.begin(9600);
        pinMode(button_pin, INPUT_PULLUP); //Setting input as input pullup
    }

    void loop()
    {
        Button();
    }

    void Button()
    {

        button_state = digitalRead(button_pin); //Read button state
        if (button_state == LOW)
        {
            Serial.println(button_state); //print button state when it is low
        }
    }

In your code, you have used `=` operator in place of `==` in the if loop. Just if you change it, it will start working also you can use my above code it is same as yours just I have made some minor changes such as using `bool` in place of int and use of `#define` in place of pin declaration where you used `int`


message:
ESP-32 Upload Files to SPIFFS via browser

I am using ESPAsyncWebServer Library in a ESP32 DevKit. I want to make a form in the browser in order to upload files in SPIFFS.

I have to notice that the whole device works perfectly. I connect to Wi-Fi, it uploads files via IDE etc.

Through searching in the net, I found this part of code that does not work.

    server.on("/upload-file", HTTP_GET, [](AsyncWebServerRequest* request) {
        String html = "
<form method='post' action='/upload-file'><input type='file'><button>Send</button></form>
";
        request->send(200, "text/html", html);
        });

    server.on("/upload-file", HTTP_POST, [](AsyncWebServerRequest* request) {
        AsyncWebServerResponse* response = request->beginResponse(200, "text/html", "hello world");
        response->addHeader("Connection", "close");
        request->send(response);
        }, handleUpload);
 server.onFileUpload(handleUpload);

The handleUpload function:

    void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
    if (!index) {
        request->_tempFile = SPIFFS.open("/" + filename, "w");
    }
    if (len) {
        request->_tempFile.write(data, len);
    }
    if (final) {
        request->_tempFile.close();
        request->redirect("/files");
    }
    }

It shows the form but the file doesn't upload.
Is there any idea on how can I make it work?

body:
I had the same problem and thanks to you, I did solve the problem!

Here is the full code,
My html code for the upload page, the form is in the <iframe> tag:
```html

<!DOCTYPE html>
<html>
<head>
  <title>File Upload Example</title>
</head>
<body>
  <h1>File Upload Example</h1>
<form method="POST" action="/upload" enctype="multipart/form-data" target="iframe"><input type="file" name="upload"><input type="submit" value="Upload"></form>
<iframe style="visibility: hidden;" src="http://" )+local_IPstr+"/Usm" name="iframe"></iframe>
</body>
</html>
```
code for ESP:
```c++

void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final){
if (!index) {
    request->_tempFile = SPIFFS.open("/" + filename, "w");
    Serial.println("1");
}
if (len) {
    request->_tempFile.write(data, len);
     Serial.println("2");
}
if (final) {
   Serial.println("3");
    request->_tempFile.close();
    request->redirect("/");
}
}

 controlserver.on("/upload", HTTP_POST, [](AsyncWebServerRequest *request) {
        request->send(200); }, handleUpload);

  controlserver.on("/UPL", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(200, "text/html", upl);
  });

  readFile(SPIFFS, "/11.txt"); // show the content of the uploaded file, obviously you should know the name of the uploaded file!
```

you can write a function like this to make sure the file was delivered:
```c++
  readFile(fs::FS &fs, const char * path){
  Serial.printf("Reading file: %s\r\n", path);
  File file = fs.open(path, "r");
  if(!file || file.isDirectory()){
    Serial.println("- empty file or failed to open file");
    return String();
  }
  Serial.println("- read from file:");
  String fileContent;
  while(file.available()){
    fileContent+=String((char)file.read());
  }
  file.close();
  Serial.println(fileContent);

}
```


message:
What motor to move a small telescope?

i just bought a hobby telescope, it works well for being nothing much than a toy, the very problem is that the gesrs that should keep it stable are all plastic and very hard to tighten while keeping it steady.

So I thought to let the gears wide open and move it with arduino: you point the object manually then with 4 buttons move it by small steps.

I've tried to use a couple of servos i had at home, mg90s 2kg 180°; while 180° is enough for the purpose, first i don't think 2kg is enough for the X axis motor, second one is not very precise (using the default library).
I know I can achieve better results calibrating the pulse manually, but maybe is better if I use better motors.

What motors (and why) would you reccomand?
Servo or stepper?

Being for a hobby the budget is low, so very max 50$?

body:
I wouldn't use a servo for this. You don't have very fine control over the angle with a servo. Also with a typical telescope the focus is more on rather slow and precise movements, instead of fast ones.

Instead I would use a stepper motor. Depending on your exact requirements, these can be rather cheap to rather expensive.

Here also the mechanics come into play. The motor should not be attached directly to the axis, but instead through some gears (the axis of the telescope having the larger gear). That will allow for smaller, more precise movements and also lower the needed torque for the motor. Of course this depends on your actual telescope hardware, meaning if you can put a gear right to the axis. If not, you could limit the motor driven movement a bit and install a level, which then could be pushed or pulled by a nut on a threaded rod, which gets driven by the servo motor. This would be rather easy to implement, though you may need to correct for the different rotation behavior, when you get to the outer sides of the movement (for the actuator being linear, while the resulting movement is circular), by some mathematics in your code.

Since you want to keep your costs very low, you might wanna use the 28BYJ-48 stepper motor (including the fitting driver). In terms of stepper motors they are rather bad, but they are really really cheap and - depending on the gear ratio/level length/thread pitch - it might not matter that much for you. You could always update to a better stepper motor in the future.


message:
Is it possible to write data to a fat file system on SPI flash using an arduino?

I have an [SPI flash based mp3 module][1] and was wondering whether its possible to write to the flash chip using a microcontroller(arduino). the IC supports FAT16/FAT32 file systems. I have researched arduino and the fat file system but they are all in relation to SD cards which operate differently as far as i understand. Is it possible to write data to a fat file system on SPI flash using an arduino?

  [1]: http://www.icstation.com/player-module-audio-voice-board-8bit-uart-contorl-4mbytes-flash-voice-playback-module-p-13454.html

body:
The first and most important problem is not the filesystem. Currently on the board the USB port is connected to the internal MCU, which in turn is connected via SPI to the flash chip. The internal MCU is the master on the SPI bus. But the SPI bus does not support multiple masters on one bus. So just connecting the external MCU to the SPI lines as master would not work.

I see 2 possible ways to go here:

- You can unsolder the flash chip from the board and add a fitting multiplexer chip, which can switch the SPI lines between the two masters. That effectively gives you only one master on the SPI bus at any time. This way would be rather hacky and difficult for a beginner. It might also be important to keep an eye on the capacitance of the bus, since it might run with rather high speed. A too high capacitance (for example through using a breadboard) might result in erroneous communication.

    Then you could use one of the FAT libraries. I don't know them in detail, but I think you could also use them for a simple SPI flash chip. You just would need to implement the lower level access functions, that the FAT library needs.

- Or you could try to use a USB host board with your external MCU and try to write data through the USB port. I don't have much experience with USB host boards, so I cannot really tell you, if and how exactly this is possible with the available hardware (the board will most likely implement an USB interface like a simple flash USB stick).

All in all I think, this would be rather hacky. Your board is not really made for changing the data through another microcontroller. Depending on what exactly you want to achieve, you might want to go to a different hardware setup.


message:
IRremote and PCM sound libraries interfering

I have a simple sketch which sends IR codes, plays a sound and toggles an LED when you press a button and toggles another LED when it receives that code. The idea is that I have two Arduinos with this same sketch and when you press the button on one, the LED is toggled and so is another LED on the other Arduino. This program works as intended when the sound is not included.

Here is the sketch:
~~~

#include <IRremote.h> // For the IR transmition and receiving
#include <PCM.h> // For the audio output

IRsend irsend; // Setup the IR transmitter
const int receiver = 8; // Initialize pin 13 as recevier pin.
IRrecv irrecv(receiver); // Create a new instance of receiver
decode_results results;

// Declare arrays to hold sound notes to play
const unsigned char gunShot[] PROGMEM = {}; // There is a huge list of numbers in this array, but I removed them to make the code easier to read

const unsigned char gunClick[] PROGMEM = {}; // There is a huge list of numbers in this array, but I removed them to make the code easier to read

// declare consants
const int button = 13;
const int greenLight = 7;
const int yellowLight = 2;
const int timeBetweenTransmittion = 800; // At least 800 milliseconds between two transmissions
// The speaker is fixed on pin 11

// declare variables
bool toggleGreen = true; // Bool variables to toggle the lights
bool toggleYellow = true;
long int previousTransmittion = 0; // Long int to store the timestamp in millis of the previous transmission

// put your setup code in here, to run once:
void setup()
{
  pinMode(button, INPUT_PULLUP); // Setup the button with an internal pullup resistor
  Serial.begin(9600);
  irrecv.enableIRIn(); // Enable the receiver
  Serial.println("start");
}

// put your main code in here, to run repeatedly:
void loop() {
  if (not digitalRead(button) && millis() > previousTransmittion + timeBetweenTransmittion) // If the button is pressed and it's been enought time since the last transmittion
  {
    Serial.println("send!");

    // Different orders of these lines of code were tried:

    //startPlayback(gunShot, sizeof(gunShot)); // Play shot before sending the code and enabling the receiver (play command 1 for reference)
    //delay(250);

    irsend.sendNEC(1367857, 32); // Send the code

    //startPlayback(gunShot, sizeof(gunShot)); // Play shot between sending the code and enabling the receiver (play command 2 for reference)
    //delay(250);

    irrecv.enableIRIn(); // Sending ir stops the receiver so start the receiver again

    startPlayback(gunShot, sizeof(gunShot)); // Play shot after sending the code and enabling the receiver (play command 3 for reference)
    delay(250);

    // Toggle the yellow light
    digitalWrite(yellowLight, toggleYellow);
    toggleYellow = not toggleYellow;

    previousTransmittion = millis(); // Set the record for latest transmittion to the currnt time
  }

  if (irrecv.decode(&results)) // If we have received an IR signal
  {
    Serial.println (String(results.value, HEX)); // Display HEX results
    if (String(results.value, DEC) == "1367857") // If the code is the right one
    {
      Serial.println("correct code");

      // toggle the green light
      digitalWrite(greenLight, toggleGreen);
      toggleGreen = not toggleGreen;
    }
    irrecv.resume(); // Prepare the receiver for the next code
 }
}

~~~
// End of sketch

As you can see, I tried putting the play sound line before, between and after the IR transmission lines of code. The delays are there so I can see if the audio starts to play and stops or if it just never plays. Here is what I found from all the combinations:

- In all the combinations (play command 1, 2 and 3), The IR receiver worked as intended if used BEFORE ever pressing the button.

- None of the combinations stop the loop as if I put <Serial.println("loop");> at the start of the loop() routine, it continues to print "loop", regardless of what I do.

- In play command 1 and 2, the sound plays when I press the button, but stops after the 250ms delay. Once the button has been pressed once, it doesn't do anything when I press it again (doesn't print "send!" or toggle the light). The receiver receives one more code after pressing the button, but always prints the code "2a", regardless of what button on my tv remote I press (the tv remote usually prints a 6 character hex code). After it prints "2a", it doesn't receive any more codes.

- Play command 3 plays the full sound and sends the right code, and allows me to do it as many times as I want (the button still works after pressing it more than once). However the receiver still no longer works after the first time I press the button. It doesn't receive "2a" the first time after pressing the button unlike the first 2.

I am using the libraries IRremote by shirriff, z3t0 and ArminJo (VERSION 2.6.1) and PCM by David Mellis, Michael Smith (VERSION 1.0.0) (http://highlowtech.org/?p=1963). I don't know if there is a simple way around this problem or if these libraries just cannot be used together.

I have the speaker on pin 11.

If you need anything clarifying please ask. Any help would be appreciated, thanks in advance.

body: The PCM library uses timer 1, and timer 2. The IRremote library uses timer 1. So they both need timer 1. So there's a conflict. So you can't use both libraries at the same time, unfortunately.


body:
It works for me if i put a delay after `startPlayback` followed by a `irrecv.enableIRIn();`

    startPlayback(sample, sizeof(sample));
    delay(1000); // delay needed as long audio is playing
    irrecv.enableIRIn(); // enable input from IR receiver after using PCM library startPlayback


message:
Multiple IR Sensors with Arduino

I am fairly new to working with sensors and Arduino. I am working on a project using Max MPS to control the volume of three audio files. There will be three framed photos, each having its own IR sensor and audio file. So when someone gets closer to the sensor, the volume of the corresponding file gets louder. Is this doable? The samples I have seen with the board I have and an IR sensor only use one. I'm assuming I'll be able to use the breadboard I have to add more sensors like I've done in the past with photocell sensors but I have yet to test it since it's in the mail. Just hoping to get ahead of any issues I may face and see if I should order any other equipment.

I ordered 3 of these [IR sensors][1] and this is the [Arduino kit][2] I am working with.

Sorry if I may not be describing it in enough detail, but thanks in advance!

[![Arduino Board example][3]][3]

  [1]: https://www.amazon.com/gp/product/B07WQWHNDW/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1
  [2]: https://www.adafruit.com/product/193
  [3]: https://i.stack.imgur.com/g0HXH.jpg

body:
technically yes, there is no reason you can't do that project but the issues will come in how complex you wish to make system. For example, it shouldn't be too hard to hook up the three sensors to three analogue Pins on the Arduino and then have the Arduino constantly loop to check the voltage of the sensors, from which, you would tell it to 'do something' when one of the IR sensors voltage is above or below a certain value. What you then choose to do is up to you, if it's just to turn on a light then it can be done fairly quickly once you have all the components. For controlling the Audio in the file, I personally have no experience with this.

What might be better is first checking to see if you can Adjust the audio in one of your files using an Arduino (you may need to use bluetooth or have something on your PC communicate with your Arduino via UART through the USB).

Generally, with new projects, it's a good idea to figure out a solid plan for exactly what you want to do, so I would write down in detail what you want the system to do and then go through each part to see if it's possible


message:
What happens when you call malloc()/free()/new/delete?

So I [understand][1] [that generally][2] [speaking, dynamic allocation should be avoided][3]. My question isn't how or why, but *what* happens when you call a function that allocates memory?

On Windows or Linux, when a program allocates memory, a whole bunch of stuff happens, things like virtualisation and security related features that have no relevance to arduino, and the bit that I'm interested in, memory management:

There will be some code, that will look at the alignment and size requirements of the allocation request, look at the pool of memory it has access to, find a space big enough, make a note of the allocation (which also uses some amount of memory) and then return a pointer to the allocated space back to the calling function.

Is there a custom malloc implementation for each device, or does it come with the arduino toolchain (and does that mean Arduino has a different implementation from Teensy, or avr from sam?), or is there some magical default implementation supplied by the compiler? What kind of memory overhead is incurred with every allocation? How easy is it to override this functionality and implement your own (out of morbid curiosity or tendency towards masochistic endeavours)?

  [1]: https://arduino.stackexchange.com/questions/682/is-using-malloc-and-free-a-really-bad-idea-on-arduino
  [2]: https://arduino.stackexchange.com/questions/12821/malloc-with-objects-in-arduino-libraries
  [3]: https://arduino.stackexchange.com/questions/77061/why-is-it-considered-bad-practice-to-use-the-new-keyword-in-arduino

body:
There are some hardware-specific abstractions (they mostly define the maximum memory available), but otherwise these are functions are implemented by the C/C++ runtime (on arduinos an implementation called "NewLib") and usually "just work". You might want to take a look at [this question][1], where quite a bit of background is given on the SAM implementation of the hardware abstractions (because it's broken).

And yes, of course using malloc/free has some considerable overhead, which is one reason why it's not the recommended way of allocating memory on microcontrollers. But the logic behind it is mostly the same whether there's 2k of memory or 2G. And the _memory model_ of modern microcontrollers (at least the 32 bit ones) is very similar to the one seen in 32 bit Windows or Linux apps.

  [1]: https://arduino.stackexchange.com/questions/80535/memory-allocation-on-arduino-due-never-returns-null


message:
How to unbrick an Arduino Mega+ESP8266 Wifi

I have a [Jaycar XC4421 - Arduino Mega + Wifi][1] which I think have somehow managed to screw up the boot loader.

I have an [XC4627 USP-ISP Programmer][2] (and the XC4613 adaptor) which I have previously used to successfully burn boot loaders and update sketches in the past using the Arduino IDE.

However, on this occasion, after trying to reset the bootloader from the IDE, i can no longer upload sketches from the IDE using the inbuilt "upload" function of the IDE (I get timeouts) nor can I upload the sketch using the USB-ISP Programmer.

The symptoms as they currently stand with the USB connected to the 2560 (switches 3 & 4 on, all others off):

* If I burn the bootloader (selected board in IDE is "Arduino Mega or Mega 2560"), this appears to work, but uploading sketches still does not work. After burning the bootloader, the builtin LED blinks at an odd cycle of roughly 400ms off, 400ms on, 200ms off, 200ms on.
* The board is recognised in the IDE and appears as COM12
* If try to upload the "blink" sketch (ctrl-U), I get timeout messages (see transcript below)
* If I connect the USB-ISP and upload the blink sketch (ctrl-shift-U), the upload appears to work, but the sketch is never run (i.e. the builtin LED doesn't blink).
* After uploading the blink sketch (via the USB-ISP programmer) the aforementioned odd blinking of the builtin LED completely stops (i.e. no blinking at all).
* There is no hardware other than the USB-ISP programmer connected to the ICSP pins on the Arduino.
* If I reset the DIP switches so that just 5 & 6 are on (USB->ESP) I am able to interact just fine with the "AT program" that was originally supplied on ESP side of the board.

My suspicion is that the Arduino Mega 2560 bootloader code is not completely compatible with the Arduino Mega + WiFi board. I don't think that suspicion makes much sense, but I'm out of ideas!

Where can I get the correct bootloader for this device? Alternatively, how can I correctly unbrick this?

Transcript from "upload blink sketch" showing timeout:

```
C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\gmc\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\gmc\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\gmc\Documents\Arduino\libraries -fqbn=arduino:avr:mega:cpu=atmega2560 -vid-pid=1A86_7523 -ide-version=10813 -build-path C:\Users\gmc\AppData\Local\Temp\arduino_build_510155 -warnings=none -build-cache C:\Users\gmc\AppData\Local\Temp\arduino_cache_341521 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -verbose C:\Users\gmc\AppData\Local\Temp\arduino_modified_sketch_481876\Blink.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\gmc\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\gmc\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\gmc\Documents\Arduino\libraries -fqbn=arduino:avr:mega:cpu=atmega2560 -vid-pid=1A86_7523 -ide-version=10813 -build-path C:\Users\gmc\AppData\Local\Temp\arduino_build_510155 -warnings=none -build-cache C:\Users\gmc\AppData\Local\Temp\arduino_cache_341521 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -verbose C:\Users\gmc\AppData\Local\Temp\arduino_modified_sketch_481876\Blink.ino
Using board 'mega' from platform in folder: C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3
Using core 'arduino' from platform in folder: C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3
Warning: Board arduino:avr:ATmega328p-8 doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328P-8
Detecting libraries used...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\cores\\arduino" "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\variants\\mega" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
Generating function prototypes...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\cores\\arduino" "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\variants\\mega" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp" -o "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\preproc\\ctags_target_for_gcc_minus_e.cpp" -DARDUINO_LIB_DISCOVERY_PHASE
"C:\\Program Files (x86)\\Arduino\\tools-builder\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\cores\\arduino" "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\variants\\mega" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp" -o "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp.o"
Compiling libraries...
Compiling core...
Using precompiled core: C:\Users\gmc\AppData\Local\Temp\arduino_cache_341521\core\core_arduino_avr_mega_cpu_atmega2560_995451215dbc0ff7e2274fbcd94e62ea.a
Linking everything together...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega2560 -o "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp.o" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/..\\arduino_cache_341521\\core\\core_arduino_avr_mega_cpu_atmega2560_995451215dbc0ff7e2274fbcd94e62ea.a" "-LC:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155" -lm
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.eep"
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.hex"
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf"
Sketch uses 2684 bytes (1%) of program storage space. Maximum is 253952 bytes.
Global variables use 194 bytes (2%) of dynamic memory, leaving 7998 bytes for local variables. Maximum is 8192 bytes.
C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega2560 -cwiring -PCOM12 -b115200 -D -Uflash:w:C:\Users\gmc\AppData\Local\Temp\arduino_build_510155/Blink.ino.hex:i

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM12
         Using Programmer              : wiring
         Overriding Baud Rate          : 115200
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer

avrdude done.  Thank you.

An error occurred while uploading the sketch

```

Transcript from "Upload blink sketch using programmer":

```
C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\gmc\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\gmc\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\gmc\Documents\Arduino\libraries -fqbn=arduino:avr:mega:cpu=atmega2560 -vid-pid=1A86_7523 -ide-version=10813 -build-path C:\Users\gmc\AppData\Local\Temp\arduino_build_510155 -warnings=none -build-cache C:\Users\gmc\AppData\Local\Temp\arduino_cache_341521 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -verbose C:\Users\gmc\AppData\Local\Temp\arduino_modified_sketch_753905\Blink.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\gmc\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\gmc\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\gmc\Documents\Arduino\libraries -fqbn=arduino:avr:mega:cpu=atmega2560 -vid-pid=1A86_7523 -ide-version=10813 -build-path C:\Users\gmc\AppData\Local\Temp\arduino_build_510155 -warnings=none -build-cache C:\Users\gmc\AppData\Local\Temp\arduino_cache_341521 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7 -prefs=runtime.tools.avrdude.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.3.0 -verbose C:\Users\gmc\AppData\Local\Temp\arduino_modified_sketch_753905\Blink.ino
Using board 'mega' from platform in folder: C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3
Using core 'arduino' from platform in folder: C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.3
Warning: Board arduino:avr:ATmega328p-8 doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328P-8
Detecting libraries used...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\cores\\arduino" "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\variants\\mega" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
Generating function prototypes...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\cores\\arduino" "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\variants\\mega" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp" -o "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\preproc\\ctags_target_for_gcc_minus_e.cpp" -DARDUINO_LIB_DISCOVERY_PHASE
"C:\\Program Files (x86)\\Arduino\\tools-builder\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\cores\\arduino" "-IC:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.3\\variants\\mega" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp" -o "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp.o"
Compiling libraries...
Compiling core...
Using precompiled core: C:\Users\gmc\AppData\Local\Temp\arduino_cache_341521\core\core_arduino_avr_mega_cpu_atmega2560_995451215dbc0ff7e2274fbcd94e62ea.a
Linking everything together...
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega2560 -o "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155\\sketch\\Blink.ino.cpp.o" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/..\\arduino_cache_341521\\core\\core_arduino_avr_mega_cpu_atmega2560_995451215dbc0ff7e2274fbcd94e62ea.a" "-LC:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155" -lm
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.eep"
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf" "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.hex"
"C:\\Users\\gmc\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-size" -A "C:\\Users\\gmc\\AppData\\Local\\Temp\\arduino_build_510155/Blink.ino.elf"
Sketch uses 2684 bytes (1%) of program storage space. Maximum is 253952 bytes.
Global variables use 194 bytes (2%) of dynamic memory, leaving 7998 bytes for local variables. Maximum is 8192 bytes.
C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega2560 -cusbasp -Pusb -Uflash:w:C:\Users\gmc\AppData\Local\Temp\arduino_build_510155/Blink.ino.hex:i

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\gmc\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : usb
         Using Programmer              : usbasp
         AVR Part                      : ATmega2560
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PA0
         RESET disposition             : dedicated
         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    10     8    0 no       4096    8      0  9000  9000 0x00 0x00
           flash         65    10   256    0 yes    262144  256   1024  4500  4500 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
           lock           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
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : usbasp
         Description     : USBasp, http://www.fischl.de/usbasp/

avrdude: auto set sck period (because given equals null)
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9801 (probably m2560)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: auto set sck period (because given equals null)
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: reading input file "C:\Users\gmc\AppData\Local\Temp\arduino_build_510155/Blink.ino.hex"
avrdude: writing flash (2684 bytes):

Writing | ################################################## | 100% 1.69s

avrdude: 2684 bytes of flash written
avrdude: verifying flash memory against C:\Users\gmc\AppData\Local\Temp\arduino_build_510155/Blink.ino.hex:
avrdude: load data flash data from input file C:\Users\gmc\AppData\Local\Temp\arduino_build_510155/Blink.ino.hex:
avrdude: input file C:\Users\gmc\AppData\Local\Temp\arduino_build_510155/Blink.ino.hex contains 2684 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 1.43s

avrdude: verifying ...
avrdude: 2684 bytes of flash verified

avrdude done.  Thank you.

```

  [1]: https://www.jaycar.com.au/mega-with-wi-fi/p/XC4421
  [2]: https://www.jaycar.com.au/isp-programmer-for-arduino-and-avr/p/XC4627

body:
Well after "working" on this all day, it turns out that the solution was to use the "[Arduino as an ISP][1]" solution as described on the arduino.cc website.

Why the USB-ISP solution did not work is not immediately obvious as I have used it successfully before - just not with this board!

FWIW, the blinking sequence I observed when burning the bootloader via the USB-ISP programmer also occurred after loading the bootloader via the "Arduino as ISP" solution. I don't know if the sequence was identical, but it certainly was similar. I then tried uploading the blink sketch using the "inbuilt" upload (ctrl-U) and the inbuilt LED blinked "correctly" at a 1s on 1s off cycle as per the standard blink sketch is programmed to do.

Oh well, hopefully this "answer" will help others.

  [1]: https://www.arduino.cc/en/Tutorial/BuiltInExamples/ArduinoISP/