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

Your code doesn't compile with the plain "IRRemote" library from the manager, at least not with the version I have installed.  Rather than guess at which library/fork/version, I figured I'd ask, which is it?

I have IRremote by shirriff, z3t0 and ArminJo. I just updated it to 3.0.0 although I'm not sure what version I had before updating, 2.6 or something... It now doesn't compile :/, do you know why that is? Thanks

I have used the website: https://github.com/Arduino-IRremote/Arduino-IRremote to update my code to the 3.0 version but there is still one line which returns an error: IRsend.sendNECMSB(shootCode, 32); gives the error: expected unqualified-id before '.' token. Do you know how to fix that or will I need to send you the whole sketch again now I have updated it?

I'm not sure I want to go down that rabbit hole in comments.  I just needed to know how to get your original code to compile.  I installed 2.6.1 and it compiles.

Okay, 2.6.1 sounds likely, but once an Arduino sends an IR code, it no longer receives them even though I have the enable ir line in it. Any ideas?

That sort of thing goes in the question.  Which you already have in the question.  Which I've read already.  What I'm wondering is exactly where in your code does it stop?  If you have this connected to serial you can sprinkle your code with Serial.println(__LINE__); see line numbers print.  Move them around until you've narrowed down the exact line (or lines if its stuck in a loop in code you wrote) where the code stops executing.

The code never gets stuck as such, after the "game" has ended it returns to the main loop and works fine. Even if I have send IR in that loop, the code doesn't get stuck somewhere, it just disables the receiver so more IR cannot be received.

Well, I have it compiled and uploaded to a board, but I have no practical way to test it to even see what you're seeing.  I'd replace the IR receiving code with Serial input for testing, but I expect having done that the problem will be gone or different.  If you were on IRC I'd take you through transforming the code into something cleaner, but there's not really a lot I can do here in this format.  I do think it's nice that you want to do something for your cousins though.  If you cut this down into something more managable someone (maybe me) will have useful input.

Thanks, I tried using the serial input and as you expected, the problem disappeared. What's IRC? The problem is when I cut it down into a smaller program I don't have the same problem, I'll try reducing the contents of the program bit by bit (removing sound, then LCD etc) to see if I can identify what makes it work in my small sketch but not the large project. Thanks again.

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.


text:
NRF24L01+PA+LNA communication problem
I'm trying to communicate between two NRF24L01+PA+LNA modules.
I know that NRF24L01+PA+LNA modules are consuming a lot of power and here is my 3.3V power circuit.

The LM317 datasheet says it can output up to 1.5 Amp.
I'm not using Arduino, I'm using STM32F103 blue pill and I'm powering it from this single LM317 linear voltage regulator.
I'm using 1100 mAh, 8.4V LIPO battery, one for Transmitter module(NRF24L01+PA+LNA and STM32 Blue Pill) and second one for receiver module (also with NRF24L01+PA+LNA and STM32 Blue Pill).
So my problem is that, when I'm TOUCHING the Transmitter's antenna somewhere in the middle with my FINGERS, then it transmits; If I'm not touching the antenna, it does not transmit.
I also added additional 100uF polar capacitors between NRF24L01+PA+LNA's VCC and GND, but it does not help.
What else can I do?

source: Stack Exchange

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

sort: votes


text:
Send sensor data through GATT with Adafruit Bluefruit
I have the BLE Module Adafruit ItsyBitsy nRF52840 Express and I want to send sensor values from a Hallsensor to my computer. I was able to have the right data checking with the Serial monitor.
int adcin = A1;
int adcvalue = 0;
float mv_per_lsb = 1200.0F/4096.0F; // 10-bit ADC with 3.6V input range
double freq = 100;
uint32_t lastMicros = 0;  //variable to track sampling frequency
double microseconds = 1000000.0;
double interval = microseconds/freq;

void setup()
{
  Serial.begin(115200);
  // Set the analog reference to 3.0V (default = 3.6V)
  analogReference(AR_INTERNAL_1_2);
  // Set the resolution to 12-bit (0..4095)
  analogReadResolution(12); // Can be 8, 10, 12 or 14
  // Let the ADC settle
  delay(1);
}

void loop() {

  // Get a fresh ADC value after intervall (1/freq)
  if (micros()-lastMicros >= interval)
  {
    adcvalue = analogRead(adcin);
    lastMicros = micros();

    // Display the results
    Serial.print(lastMicros);
    Serial.print(" [");
    Serial.print((float)adcvalue * mv_per_lsb);
    Serial.println(" mV]");
  }
}

Then I tried to send these values through BLE connectin to my computer. So I knew I had to create a service and a characteristic for the GATT profile. But using the guide from adafruit was not really helpful. Right know I saw that with the following code I was able to see the module on my computer and read the characteristic I made. But it seems to just give me random Hex values rather than my sensor data.
#include <bluefruit.h>

BLEService        myService = BLEService(0x187A);
BLECharacteristic myChar = BLECharacteristic(0x184D);

BLEDis bledis;    // DIS (Device Information Service) helper class instance

int adcin = A1;
int adcvalue = 0;
float mv_per_lsb = 1200.0F/4096.0F; // 10-bit ADC with 3.6V input range
double freq = 100;
uint32_t lastMicros = 0;  //variable to track sampling frequency
double microseconds = 1000000.0;
double interval = microseconds/freq;
float volt = 0;

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

  //Setup for data acquisition
  // Set the analog reference to 3.0V (default = 3.6V)
  analogReference(AR_INTERNAL_1_2);
  // Set the resolution to 12-bit (0..4095)
  analogReadResolution(12); // Can be 8, 10, 12 or 14
  // Let the ADC settle
  delay(1);

  Serial.println("BLE data acquisition");
  Serial.println("-----------------------\n");

  // Initialise the Bluefruit module
  Serial.println("Initialise the Bluefruit nRF52 module");
  Bluefruit.begin();

  // Set the advertised device name (keep it short!)
  Serial.println("Setting Device Name to 'Adafruit_BLE'");
  Bluefruit.setName("Adafruit_BLE");

  // Set the connect/disconnect callback handlers
  Bluefruit.Periph.setConnectCallback(connect_callback);
  Bluefruit.Periph.setDisconnectCallback(disconnect_callback);

  // Configure and Start the Device Information Service
  Serial.println("Configuring the Device Information Service");
  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit");
  bledis.begin();

  // Setup the BLEService and BLECharacteristic classes
  Serial.println("Configuring the custom Service");
  setupSer();

  // Setup the advertising packet(s)
  Serial.println("Setting up the advertising payload(s)");
  startAdv();

  Serial.println("Ready");
  Serial.println("\nAdvertising");
}

void startAdv(void)
{
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();

  // Include custom Service UUID
  Bluefruit.Advertising.addService(myService);

  // Include Name
  Bluefruit.Advertising.addName();

  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds
}

void setupSer(void)
{
  myService.begin();

  myChar.setProperties(CHR_PROPS_READ);
  myChar.setPermission(SECMODE_OPEN, SECMODE_OPEN);
  myChar.setFixedLen(4);
  myChar.begin();
}

void connect_callback(uint16_t conn_handle)
{
  // Get the reference to current connection
  BLEConnection* connection = Bluefruit.Connection(conn_handle);

  char central_name[32] = { 0 };
  connection->getPeerName(central_name, sizeof(central_name));

  Serial.print("Connected to ");
  Serial.println(central_name);
}

void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
  (void) conn_handle;
  (void) reason;

  Serial.print("Disconnected, reason = 0x"); Serial.println(reason, HEX);
  Serial.println("Advertising!");
}

void loop()
{
  // Get a fresh ADC value after intervall (1/freq)
  if (micros()-lastMicros >= interval)
  {
    adcvalue = analogRead(adcin);
    lastMicros = micros();
    volt = (float)adcvalue * mv_per_lsb;
    // Display the results
    Serial.print(adcvalue);
    Serial.print(" [");
    Serial.print(volt);
    Serial.println(" mV]");
    myChar.write16(volt);
  }
}

I really got confusing with how to write my sensor values to the characteristic.
Does anyone know how I can achieve that?
Cheers

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


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

generate letters in c# and convert them to list of lines
send to arduino mov_xy line.x line.y as string for each line
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?

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

reduce the complexity of the problem ... instead of ZWX, try engraving three simple squares

Instead of actually driving the motors, you could calculate the position. That would rule out inaccuracy from the motors. Send shapes, that return to the starting point. Add up all steps (the actual steps, after the conversion from the float number), as your CNC code would do with the motors. Then display the endposition, that comes out of your calculations. That would show the accuracy of the calculation part and you can see, if thats the problem.

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


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

Which libraries have you tried how? Please include one or two simple code examples, that you tried, with the most promising libraries. And are you sure, that you have a fitting receiver module? The datasheet doesn't say 433MHz, but 433.92MHz. Your module might not be tuned to that frequency (433MHz is more a complete band instead of a singe frequency).

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


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

if the sensors have open collector outputs, then you can connect them all together to one input

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++;
 }

The hall outputs on the BLDC motors are sinking so two of the outputs are high at any time so parallel won't work. I may have to get a dual shaft motor and add a pickup with a higher PPR count on the rear shaft to achieve the results I am looking for. Thank you for your suggestions though.

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.


text:
How to avoid MQTT reconnect Loop
I have the following code designed to allow me to control my device from my website using mqtt broker while internet is available. I also built in a local webserver to control the device in case of internet outage given I'm still connected to the same router my device is connected to.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

int ledPin = 2;

const char* ssid = "SSID";
const char* password = "PASS";
const char* mqtt_server = "MQTTSERVER";
const char* mqtt_user = "MQTTUSER";
const char* mqtt_pass = "MQTTPASS";
const char* mqtt_topic = "topic";
String mqttpayload;

WiFiServer server(80);
WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);  pinMode(ledPin, OUTPUT);  digitalWrite(ledPin, LOW);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) { delay(100); Serial.print(".");  }  Serial.println("");

  Serial.print("Connected to WiFi");

  client.setServer(mqtt_server, 1883);    server.begin();
}

void loop() {
  client.setCallback(callback);
  reconnect();
  if ( mqttpayload == "OFF" ) {   digitalWrite(ledPin, HIGH); Serial.println("Switced OFF"); }
  if ( mqttpayload == "ON" ) {   digitalWrite(ledPin, LOW);  Serial.println("Switced ON"); }
  mqttpayload = "";

  WiFiClient cclient = server.available();
  if (!cclient) {  return;  }  while(!cclient.available()){  }
  String request = cclient.readStringUntil('\r');  Serial.println(request);  cclient.flush();

  int value = HIGH;
  if (request.indexOf("/LED=ON") != -1)   {
    digitalWrite(ledPin, LOW);    value = LOW;      Serial.println("Publish message: ON");    reconnect();  client.publish(mqtt_topic, "ON", true);
  }
  if (request.indexOf("/LED=OFF") != -1)  {
    digitalWrite(ledPin, HIGH);   value = HIGH;     Serial.println("Publish message: OFF");    reconnect(); client.publish(mqtt_topic, "OFF", true);
  }

  cclient.println("HTTP/1.1 200 OK");
  cclient.println("Content-Type: text/html");
  cclient.println("");
  cclient.println("<!DOCTYPE HTML>");
  cclient.println("");
  cclient.print("LED status: ");

  if(value == HIGH) {    cclient.print("OFF");  } else {    cclient.print("ON");  }
  cclient.println("

");
  cclient.println("Turn ON
");
  cclient.println("Turn OFF
");
  cclient.println("");
  Serial.println("");
}

void callback(char* topic, byte* payload, unsigned int length) {
  for (int i = 0; i < length; i++) {     mqttpayload += (char)payload[i]; }
}

void reconnect() {
  if (!client.connected()) {
    while (!client.connected()) {
      Serial.print("MQTT..");
      if (client.connect("2021", mqtt_user, mqtt_pass)) {
        Serial.println("MQTT connected");        client.subscribe(mqtt_topic);
      } else { error(); }
    }
  }
  client.loop();
}

void error() {  Serial.print("failed, rc=");      Serial.print(client.state());      Serial.println(" try again in 5 seconds");      delay(5000);   }

The problem lies when I test it while connected to my router with no internet. The code loops trying to connect to MQTT server and get stuck which doesn't allow me to send local HTTP requests.
I tried modifying the MQTT reconnect loop to the one below, which solves the problem but introduces another issue which is delaying the HTTP requests up to 6-9 seconds.
void reconnect() {
 if (client.connect("2021", mqtt_user, mqtt_pass)) {
  Serial.println("MQTT connected");
  client.subscribe(mqtt_topic);
 } else { error(); }
 client.loop();
}

So the question here, what should I do to get around this issue?

You should only try connecting to your MQTT server when there's no active connection. With your second piece of code you are (re)connecting every iteration of your loop() and this might introduce the delay you seem to be experiencing. Place an if (!client.connected) { ... } around the if (client.connect()) { .. } code.

@StarCat if you look at the main code, it's there, and this is what makes it troublesome to me. if internet connectivity is lost, this will hold Arduino from receiving my HTTP requests.

You could throttle the amount of reconnect attempts by only calling reconnect() every few seconds and not continuously. I've had good results with checking once every 30 seconds. If you do that, you should call client.loop() from your main loop() and not from reconnect().

It's quite simple: on each iteration of loop() if the client isn't connected then try to connect. Not while the client isn't connected then try to connect. Only try once each time through.

You could look at the PubSubClient example mqtt_reconnect_nonblocking which might be what you're looking for. It only tries to connect when there's no connection (I assumed your code already did this, but it looks like it doesn't).

In the loop, check the network first, you can also ping to internet to make sure the internet is available. If negative, just skip reconnecting and try to check the internet connection or try another way to connect to MQTT or esp.


text:
AT42QT1070 sensor output issues in standalone mode
Also when I am trying to see the data read on pins in serial monitor, it is not reading as required. The code i am using is as follows:
const int tuch_Pin0=18;
const int tuch_Pin1=19;
const int tuch_Pin2=21;
const int tuch_Pin3=22;
const int tuch_Pin4=32;

int State1=0;
int State2=0;
int State3=0;
int State4=0;
int State5=0;

void setup() {
  Serial.begin(38400);
  pinMode( tuch_Pin0,INPUT);
  pinMode( tuch_Pin1,INPUT);
  pinMode( tuch_Pin2,INPUT);
  pinMode( tuch_Pin3,INPUT);
  pinMode( tuch_Pin4,INPUT);
}

void loop() {

    State1= digitalRead(tuch_Pin0);
    State2= digitalRead(tuch_Pin1);
    State3= digitalRead(tuch_Pin2);
    State4= digitalRead(tuch_Pin3);
    State5= digitalRead(tuch_Pin4);

    if( State1!=0){

         Serial.println("Touch0 press");
    }
    else if(State2!=0)
    {
      Serial.println("Touch1 press");
    }
     else if(State3!=0)
     {
         Serial.println("Touch2 press");
     }

     else if(State4!=0)
     {
       Serial.println("Touch3 press");
     }
   else if ( State5!=0)
   {
    Serial.println("Touch4 press");
   }
   else
   {
    Serial.println("please press any key");
   }
   delay(100);
}

.....................the output it shows is... touch press 0.. without any touch and shows press any key when I touch any pin. Where I am wrong? Any solution, please?

Is it possible that multiple pads are touched at once? Then you shouldn't use else if but only if. Are you using a sensor board or did you build your own? What is the wireup? Do you maybe need to invert the logic so that 0 means pressed and 1 means unpressed?

it would make more sense to name the state variables State0, State1, etc


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

functions (e.g. blink without delay)

objects (cooperative multitasking)

interrupts

something like a RTOS

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.

Functions and objects have nothing to do with “doing several things at the same time”, they are just ways to encapsulate some logic. In both cases you are doing non-blocking programming. The most useful programming paradigm for non-blocking programming is the finite state machine.

Please read up about the concept of "real time". This does not mean that something is fast, it just means it is fast enough (based on whatever standards you apply). For instance, if your blinking led has a skew of a few milliseconds, you won't notice - it is irrelevant.

Thanks for the link, I'm going through it today.

as long as you follow the examples, and non of your code uses delay(), it should naturally do many things at once, CPU time and memory allowing. For what you describe, it's hard to imagine even an UNO not being up to task.

Thank you Davis for the comment

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, 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:
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().

Hi Edgar, I really appreciate you taking the time and effort to respond in such a helpful way. I'll follow the link and take the rest of the day to absorb the content. Thank you very much. Just to confirm a couple of quick points. You're implying that from a multitasking perspective it makes no difference whether I encapsulate the code in functions or objects? What would be an example of a task which cannot wait for a loop iteration? Would a press of a button to perform an action such as switching analog sensor read on/off qualify?

if i may; streaming audio, some wifi interactions, capturing hi-rate ADC samples, etc. Look into interrupts, which are basically events that can cut in line for real-time handling of stuff like button presses. Your analog sensor doesn't mind waiting a ms to take another sample.

@ZhelyazkoGrudov: 1. An object is just a convenient way to encapsulate functions (called methods) together with data. The right level of encapsulation can help make your code cleaner and easier to maintain, but it has no relevance vs. the multitasking approach. 2. For detecting a button press, you may need to use interrupts if the button is going to be operated by Quicksilver. If the operator is a regular human, a millisecond or two of latency makes no difference.

Such a good answer! Maybe I am designing a project for the avengers, you never know... In all seriousness, thanks for the explanation.


text:
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?

Does this answer your question? How do I convert Arduino to an ATmega328P-based project?

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:

you might also consider running it at 8Mhz w/o an xtal if you want simplicity, but a nano or pro micro would be easier.

You can check the UNO's schematic. 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, which are a lot more bare-bones.


text:
Fresh install getting Assembler Error
I am using Raspberry Pi 4 to connect via usb to program ardino Nano, I intend to communicate with the nano via i2c, but this is irrelivant.
With a fresh install of Arduino for ARM 32 bit I get this error when tring to compile a default (fresh) script:
Arduino: 1.8.13 (Linux), Board: "Arduino Nano, ATmega328P"

/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/arduino-builder -dump-prefs -logger=machine -hardware /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware -tools /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/tools-builder -tools /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -built-in-libraries /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/libraries -libraries /root/Arduino/libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10813 -build-path /tmp/arduino_build_228832 -warnings=none -build-cache /tmp/arduino_cache_202507 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avrdude.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -verbose /tmp/untitled1895295462.tmp/sketch_feb16a/sketch_feb16a.ino
/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/arduino-builder -compile -logger=machine -hardware /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware -tools /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/tools-builder -tools /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -built-in-libraries /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/libraries -libraries /root/Arduino/libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10813 -build-path /tmp/arduino_build_228832 -warnings=none -build-cache /tmp/arduino_cache_202507 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avrdude.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.arduinoOTA.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr -verbose /tmp/untitled1895295462.tmp/sketch_feb16a/sketch_feb16a.ino
Using board 'nano' from platform in folder: /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr
Using core 'arduino' from platform in folder: /home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr
Detecting libraries used...
/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr/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=atmega328p -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr/cores/arduino -I/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr/variants/eightanaloginputs /tmp/arduino_build_228832/sketch/sketch_feb16a.ino.cpp -o /dev/null -DARDUINO_LIB_DISCOVERY_PHASE
Generating function prototypes...
/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr/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=atmega328p -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr/cores/arduino -I/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr/variants/eightanaloginputs /tmp/arduino_build_228832/sketch/sketch_feb16a.ino.cpp -o /tmp/arduino_build_228832/preproc/ctags_target_for_gcc_minus_e.cpp -DARDUINO_LIB_DISCOVERY_PHASE
/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/tools-builder/ctags/5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /tmp/arduino_build_228832/preproc/ctags_target_for_gcc_minus_e.cpp
Compiling sketch...
/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/tools/avr/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=atmega328p -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr/cores/arduino -I/home/pi/Desktop/arduino_32_bit/arduino-1.8.13/hardware/arduino/avr/variants/eightanaloginputs /tmp/arduino_build_228832/sketch/sketch_feb16a.ino.cpp -o /tmp/arduino_build_228832/sketch/sketch_feb16a.ino.cpp.o
Assembler messages:
Error: unrecognized option -mmcu=avr5
exit status 1
Error compiling for board Arduino Nano.

I am not sure if it's related, but when I try sudo ./install.sh I get the result
pi@raspberrypi:~/Desktop/arduino_32_bit/arduino-1.8.13 $ sudo ./install.sh
Adding desktop shortcut, menu item and file associations for Arduino IDE...

touch: cannot touch '/root/.config/mimeapps.list': No such file or directory
/usr/bin/xdg-mime: 848: /usr/bin/xdg-mime: cannot create /root/.config/mimeapps.list.new: Directory nonexistent

 done!

But arduino studios runs by the script in the folder. I have tried selecting different Programmers with the same result.
I am using arduino arm 32 bit as the 64 bit arm version does install with no error, but it does not start with the script.
Thanks in advance for any ideas on how I can fix this

I would download the Linux ARM 32 IDE and look at something in it to troubleshoot, but their donation screen doesn't want to let me by today.

If you follow the menu back to downloads page, then try again it lets you past.
Or click https://downloads.arduino.cc/arduino-1.8.13-linuxarm.tar.xz

Familiar with that.  Went through  quite a few times.  They're just getting more obnoxious with it.

Well, you can try getting it to download a different version of the AVR core files in the package manager.  Or perhaps dig around in the result of running strace -f on an execution of avr-g++ with file containing nothing but int main(){}  See what (avr-)as it is running.  Kind of sounds like it's locating the wrong assembler, assuming it's really the assembler and not the linker that's actually complaining.

Thank you for your reply timemage, I installed an old version of Arduino (1.8.6) and I use the old bootloader and it works. (Probably should have tried that first, whoops)
Sorry, I'm too new to Linux and avr to know how to run an execution of avr-g++

Finding the the last working core or IDE version may be useful to someone wants to troubleshoot this to a definitive answer.


text:
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!

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.

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


text:
How to install CH340G in iOS
I have bought a new Arduino UNO and it works on CH340G. I want to code it using iOS phone, don't have a PC is there any way to install CH340G driver for iOS.

your question is about the IOS, not about the arduino ... do a search for IOS ch430g driver ... if you find it, install it, otherwise you are out of luck .... do you even have a USB port on your phone?

You may have better luck searching for "CH340G" rather than "CH430G" as you'd had it in your original revision.  I wouldn't expect much though.


text:
Controlling Offline ESP8266 from secure website
I want to control my ESP8266 device from my secure website via 2 different ways:

if ESP8266 is connected to internet, commands between website and device will sent over MQTT which as working perfectly as I want to be.
if ESP8266 is disconnected from internet, commands should be handled through HTTP request to local webserver. (Given I'm connected to the same router).

So the website coded this way:
if ( there is internet ) {
Publish MQTT command
} else {
Send HTTP request
}
When I tested sending HTTP requests: http://192.168.100.100/?led=on
I get error message saying Mixed content is blocked given my website is secure while local webserver is not.
Then I tried setting up a secure local webserver on my ESP8266:

With Firefox: It's working perfectly.

With Chrome:
GET https://192.168.100.100/?led=off net::ERR_CERT_AUTHORITY_INVALID

With IPhone Safari: It is not working and I have no mean to debug right now. But I'm suspecting security issues with local webserver.

As I'm targeting IPhone users, and looking for a solution to improve local webserver security or trying another approach.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266WebServerSecure.h>

const char *dname = "esp8266";
const char* ssid = "SSID";
const char* password = "PASS";

BearSSL::ESP8266WebServerSecure server(443);
ESP8266WebServer serverHTTP(80);

int ledPin = 2;

WiFiClient espClient;
PubSubClient client(espClient);
WiFiManager wm;

int value;

static const char serverCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIC6jCCAlOgAwIBAgIUZIw0cBcWDPJZe8ZIDu6bDqdwwvwwDQYJKoZIhvcNAQEL
BQAwejELMAkGA1UEBhMCUk8xCjAIBgNVBAgMAUIxEjAQBgNVBAcMCUJ1Y2hhcmVz
dDEbMBkGA1UECgwST25lVHJhbnNpc3RvciBbUk9dMRYwFAYDVQQLDA1PbmVUcmFu
c2lzdG9yMRYwFAYDVQQDDA1lc3A4MjY2LmxvY2FsMB4XDTE5MDQxMzE1NTMzOFoX
DTIwMDQxMjE1NTMzOFowejELMAkGA1UEBhMCUk8xCjAIBgNVBAgMAUIxEjAQBgNV
BAcMCUJ1Y2hhcmVzdDEbMBkGA1UECgwST25lVHJhbnNpc3RvciBbUk9dMRYwFAYD
VQQLDA1PbmVUcmFuc2lzdG9yMRYwFAYDVQQDDA1lc3A4MjY2LmxvY2FsMIGfMA0G
CSqGSIb3DQEBAQUAA4GNADCBiQKBgQCiZmrefwe6AwQc5BO+T/18IVyJJ007EASn
HocT7ODkL2HNgIKuQCnPimiysLh29tL1rRoE4v7qtpV4069BrMo2XqFvZkfbZo/c
qMcLJi43jSvWVUaWvk8ELlXNR/PX4627MilhC4bLD57VB7Q2AF4jrAVhBLzClqg0
RyCS1yab+wIDAQABo20wazAdBgNVHQ4EFgQUYvIljCgcnOfeRn1CILrj38c7Ke4w
HwYDVR0jBBgwFoAUYvIljCgcnOfeRn1CILrj38c7Ke4wDwYDVR0TAQH/BAUwAwEB
/zAYBgNVHREEETAPgg1lc3A4MjY2LmxvY2FsMA0GCSqGSIb3DQEBCwUAA4GBAI+L
mejdOgSCmsmhT0SQv5bt4Cw3PFdBj3EMFltoDsMkrJ/ot0PumdPj8Mukf0ShuBlL
alf/hel7pkwMbXJrQyt3+EN/u4SjjZZJT21Zbxbmo1BB/vy1fkugfY4F3JavVAQ/
F49UaclGs77AVkDYwKlRh5VWhmnfuXPN6NXkfV+z
-----END CERTIFICATE-----
)EOF";

static const char serverKey[] PROGMEM =  R"EOF(
-----BEGIN PRIVATE KEY-----
MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKJmat5/B7oDBBzk
E75P/XwhXIknTTsQBKcehxPs4OQvYc2Agq5AKc+KaLKwuHb20vWtGgTi/uq2lXjT
r0GsyjZeoW9mR9tmj9yoxwsmLjeNK9ZVRpa+TwQuVc1H89fjrbsyKWELhssPntUH
tDYAXiOsBWEEvMKWqDRHIJLXJpv7AgMBAAECgYA5Syqu3mAKdt/vlWOFw9CpB1gP
JydvC+KoVvPOysY4mqLFjm4MLaTSjIENcZ1SkxewBubkDHVktw+atgvhfqVD4xnC
ewMpuN6Rku5A6EELhUoDrgMEt6M9D/0/iPaMm3VDtLXJq5SuKTpnM+vyE4/uM2Gu
4COfL4GQ0A5KWTzGcQJBANfpU/kwdZf8/oaOvpNZPGRsryjIXXuWMzKKM+M1RqSA
UQV596MGXjo8k8YG/A99rTmVhbeTMC2/7gIyGTePe/kCQQDAjZg2Ujz7wY3gf1Fi
ZETL7DHsss74sZyWZI490yIX0TQqKpXqEIKlkV+UZTOoSZiAaUyPjokblPmTkKfu
uMyTAkBIBjfS+o1fxC+L53Y/ZRc2UOMlcaFtpq8xftTMSGtmWL+uWf93zJoGR0rs
VkwjRsNQYEaY9Gqv+ESHSvsKg7zRAkEAoOLuhpzqVZThHe5jqumKzjS5dkPlScjl
xIeaji/msa3cf0r73goTj5HLIev5YKi1or3Y+a4oA4LTkifxGTcRvwJBAJB+qUE6
y8y+4yxStsWu362tn2o4EjyPL2UGc40wtlQng2GzPZ20+xVYcLxsJXE5/Jqg8IeI
elVVC46RfjDK9G0=
-----END PRIVATE KEY-----
)EOF";

void showWebpage() {
  int ledStatus = digitalRead(ledPin);

  if (server.hasArg("led")) {
    String status = server.arg("led");
    if (status == "off") {
      digitalWrite(ledPin, HIGH);
      ledStatus = 1;
    }
    else if (status == "on") {
      digitalWrite(ledPin, LOW);
      ledStatus = 0;
    }
  }

  String content = "<!DOCTYPE html>";
  content += "<title>ESP8266 Test Server</title>";
  content += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">";
  content += "<link rel=\"shortcut icon\" href=\"data:image/x-icon;base64,AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA/4QAAAAA/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARAiIgEQAiAQASAAEAEgAhABAgAQASACARAAIBEQIiAQASACAQACABABIAIAEAAgARACIAABAAIAAAAAAAAAAAAAAAAAAAAAEREAERAAEAAQAAAAAQAQABAAAAABABAAERAAARAAERAQAAAQAAAQARAAABAAABABEREAAREAERCQmQAAZ2YAAGtmAACdEQAAZrsAAGbdAACZ7gAA//8AAP//AAAMdwAAf7cAAH+3AAAecQAAffYAAH32AAAOMQAA\" />";
  content += "";
  content += "";
  content += "
ESP8266 HTTPS Server
<form action=\"/\" method=\"get\">
ledPin LED Status:";

  if (ledStatus) content += " Turned off";
  else content += " Turned on";

  content += "
";

  if (ledStatus) content += "<input type=\"submit\" value=\"on\" name=\"led\">";
  else content += "<input type=\"submit\" value=\"off\" name=\"led\">";

  content += "</form>";

  content += "
";
  time_t now = time(NULL);
  content += ctime(&now);
  content += "
";

  content += "
For more information see OneTransistor.
";

  server.sendHeader("Access-Control-Allow-Origin", "*");
  server.sendHeader("Access-Control-Max-Age", "10000");
  server.sendHeader("Access-Control-Allow-Methods", "PUT,POST,GET,OPTIONS");
  server.sendHeader("Access-Control-Allow-Headers", "*");
  server.send(200, "text/html", content);
}

void secureRedirect() {
  serverHTTP.sendHeader("Location", String("https://esp8266.local"), true);
  serverHTTP.send(301, "text/plain", "");
}

void setup() {
  Serial.begin(115200);  pinMode(ledPin, OUTPUT);  digitalWrite(ledPin, LOW);

    // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {    delay(1000);    Serial.println("Connecting to WiFi..");  }
  Serial.print("Connected to WiFi: ");  Serial.println(WiFi.SSID());
  Serial.print("IP: ");  Serial.println(WiFi.localIP());

  Serial.print("Server can be accessed at https://");
  Serial.print(WiFi.localIP());
  if (MDNS.begin(dname)) {
   Serial.print(" or at https://");
   Serial.print(dname);
   Serial.println(".local");
  }

  serverHTTP.on("/", secureRedirect);
  serverHTTP.begin();

  server.getServer().setRSACert(new BearSSL::X509List(serverCert), new BearSSL::PrivateKey(serverKey));
  server.on("/", showWebpage);
  server.begin();

}

void loop() {
  serverHTTP.handleClient();
  server.handleClient();
  MDNS.update();
  delay(1000);
}

Are you using self-signed certificates?

@Majenko Yes it is self signed

That's probably your problem then: you don't have a valid CA. You should get a proper certificate. letsencrypt.org do them for free, but I usually use certbot to generate and install them automatically - not sure how you'd get the raw certificate files.

The commonly accepted method for this seems to be to either run your own CA and import that into the systems that will access your devices, or manually import and trust each certificate for your devices into the phone/computer that wants to access it. There is no simple way of using a public CA since they generally need authentication against the domain live on the server, which you can't do.

Where is your website hosted? Did any of the suggestions to your previous question help in any way?

@Gerben it's hosted on a VPS server with SSL. no none of the suggestions were helpful. I believe I have to have secured local webserver but don't know how?

I would suggest not using SSL on your ESP8266 at all. Instead make "background" connections (for example with curl in PHP) from your web server to the esp8266.

@Majenko the whole point of this is to be able to communicate while offline. thus, can't use php.

Why are you even trying to use SSl for an internal site anyway?

@Majenko removing SSL will be my last resort if this can't be sorted.

Well, you can't really use a public CA on internal sites, and you don't want to run your own CA or import certificates into your browsers, so that only leaves ditching SSL. Which is pointless in a closed network anyway.


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

This would probably be better asked on the electronics stack exchange. If you post there, you might as well list all of your requirements up front rather than people discovering them as their comments and answers are rejected.

i agree with @timemage ... any useful answers would reach a wider audience in future research ... the other place might be https://iot.stackexchange.com/questions .... the bottom line is, that this question is unrelated to the Arduino, so it is off topic here

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

Thank you a lot for your answer ! I will check that


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

Is it uploading at all?

Yes, sketch is correctly uploaded, I tried to upload another simple sketch with blinking LED, which worked.

IDE version? Did you get it through the website or the windows store? If you get it from the website, which file did you use?

I got it from windows store, version is 1.8.13 (Windows Store 1.8.42.0)

Do you anything plugged in or connected to the Arduino besides the USB cable to the PC?

No, but I tried it both, with connected MH sensor series flying fish and without on Nano, and with and without 2.4"TFT LCD shield on Uno with same result, meanwhile I tried both arduinos on another PC, where they work normally

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.

Until now I haven't had Java installed, no change in behavior after installation. I restarted computer many times in the process. Driver is correctly installed, and device in device manager is working correctly both with old and new driver.

The IDE runs on a JVM bundled with the IDE.

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


text:
U-blox GPS module (and TinyGPS library): altitude data getting stuck at strange values
We have built a HAB (high-altitude balloon) tracker based on an Arduino and a U-blox GPS module, but we have a sporadic issue where the altitude data gets stuck at odd (usually low) values. The altitude data of two flights are shown below, showing the issue. All other data (lat, long, time etc) is correct, it's just altitude we have the issue with. We would expect a linear increase in altitude, then a quick drop once it bursts. The squares on the graph mark the data points, so it's not just a case of us missing the data. Sometimes it gets stuck at the current value, and sometimes it just gets stuck at a nonsense value.
For example, in both cases the value is initially stuck at about 270m, which is correct for our launch site. However, it then gets stuck at other nonsense values for a long time (less than 500m) before it starts correctly reporting the altitude. In the 2018 chart you can see that the value drops to 0 for a while.
We have searched online and asked on some forums where people often use the U-blox GPS module, but it doesn't seem to be an issue others have come across. Also, the flights shown here were done on 2 different sets of hardware (Arduino and GPS module), with the 2019 flight using brand new components, so we don't think it's a hardware issue. It's not a transmission issue, as one data set is what was recorded by receivers and uploaded to HABHub, and the other is what was stored on the SD card and recovered after the flight. The same code was used for both, so that is our current suspect. The code had been used in previous years without problem, with only minor modifications between years.
The whole code is pasted below, I have highlighted the main loop with ####### as this is where the reading of the GPS occurs. Some notes on the code:

This is the code I've inherited, so I can't necessarily say why things have been done in a certain way.
The TinyGPS library looks like it hasn't been updated since this was written (2014ish I think).
I am considering re-writing the code from scratch, but I want to make sure I understand the cause of this issue if possible so I can avoid it in the future.

The current hardware is an Elegoo Mega2560 R3 and a u-blox NEO-6M GPS module.
Are we doing something wrong with reading/storing/processing the altitude data?
Edit to add more information and observations:
The code takes time, lat, long, altitude from the GPS module, along with the packet counter, callsign and checksum and assembles them into a string, which is transmitted via radio and stored on the SD card. The string has the following format:
$$Callsign,PacketNumber,HHMMSS,lat,long,alt*Checksum
Here's an example packet:
$$XXXXXXXX,1377,121226,51.545547,-1.296546,23*DE62
These packets are generated every 11-12s and stored and transmitted.
During the periods of incorrect data, the packets appear fine: counter and time increasing, lat and long giving sensible values, just with a nonsense altitude (in this example, 23m). In the 2018 flight, the altitude is stuck at 267m (the altitude of the launch site) for about 40minutes, even though we have seen it ascend into the clouds. The value then drops to 23m and stays there for over an hour, before briefly jumping to 117m for a couple of minutes before jumping to 15,669m, and from then on reports sensible data (until the drop to 0 during the descent).
What I have just noticed while inspecting the logs is that every time the altitude value jumps to a new nonsense value (either from a sensible value or a nonsense one), the packet that reports the new altitude value is corrupted in some manner! This is true even in the data logged on the SD card, so it is not something that has been introduced by transmitting it, but an issue with generating the string.
Below are 3 adjacent packets received, showing a jump between 2 (nonsense) altitude values:
$$XXXXXXXX,1377,121226,51.545547,-1.296546,23*DE62
$$XXXXXXXX,1379,121226,5.216667,-0.583333,117*CDB2
$$XXXXXXXX,1381,121248,51.547260,-1.293762,117*80C5
Note that the packet counter has increased correctly (by 2, but it's "supposed" to do that, it's not an error), but the timestamp is identical in the first and second packets, and the timestamp of the 3rd is 22s later (they should be every 11s). Also, the second packet (the one with the new altitude), reports a nonsense lat and/or long value. Packets then continue to be sensible (except for the altitude), until at some point it starts reporting correct altitude. Looking though both logs, I can see that this happens every time we get a new nonsense altitude.
Any suggestion as to what is messing up acquiring the altitude data and/or assembling the string? I notice that altitude is handled differently in the code compared to lat/long/time, but I am not aware of the reason for this.

//434.25MHz USB RTTY 50 Baud 500Hz shift ASCII-7 no parity 2 stop bits

#include <TinyGPS.h>
#include <SD.h>
#include <string.h>
#include <util/crc16.h>
#include <Arduino.h>

#define TempAPin A8
#define TempBPin A12
#define PresAPin A10
#define PresBPin A13
#define BatteryVoltagePin A7
#define GreenLED 11
#define RedLED 13
#define RADIOPIN 10
#define RADIOEN 9
int RADIOHIGH = 110;
int RADIOLOW = 100;

int sentance_id = 0;

char UKHAS[80];
char logString[100];
char datastring[80];
char slat[10];
char slon[10];
File myFile; //SD card setup

unsigned int TempA = 0;
unsigned int TempB = 0;
unsigned int PresA = 0;
unsigned int PresB = 0;
unsigned int BatteryVoltage = 0;

long lat, lon, alt;
unsigned long date, oldtime, time, fix_age, vel, bearing;
unsigned char dop, sats;
int year;
byte month, day, hour, minute, second, hundredths;

byte gps_set_sucess = 0 ;

TinyGPS gps;

void setup()
{
  delay(1000);
  Serial.begin(9600);
  //Serial2.begin(9600); //Bluetooth
  analogReference(DEFAULT);

  pinMode(RedLED, OUTPUT);
  pinMode(GreenLED, OUTPUT);
  digitalWrite(RedLED, HIGH);// Switch both on until GPS module is configured
  digitalWrite(GreenLED, HIGH);
  Serial.println("PROGRAM START");
  SetupGPS();
  digitalWrite(GreenLED, LOW);
  delay(1000);

  //SD setup
  //pinMode(10, OUTPUT); //Required for SPI CS to work
  //if (!SD.begin(10)) {
    pinMode(53, OUTPUT); //Required for SPI CS to work
  if (!SD.begin(53)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("SD card initialization done.");
  delay(1000);
  //radio setup
   pinMode(RADIOPIN,OUTPUT);
   pinMode(RADIOEN,OUTPUT);
   setPwmFrequency(RADIOPIN, 1);
   digitalWrite(RADIOEN,HIGH);
   Serial.println("FREE RAM:");
   Serial.println(freeRam() );
}

void SetupGPS(void)
{
   // START OUR SERIAL DEBUG PORT
  Serial.println("Initialising GPS....");
  //
  // THE FOLLOWING COMMAND SWITCHES MODULE TO 4800 BAUD
  // THEN SWITCHES THE SOFTWARE SERIAL TO 4,800 BAUD
  //
  Serial3.begin(9600);
  Serial3.print("$PUBX,41,1,0007,0003,4800,0*13\r\n");
  delay(2000);
  Serial3.begin(4800);
  //Serial3.flush();

  //  THIS COMMAND SETS FLIGHT MODE AND CONFIRMS IT
  Serial.println("Setting uBlox nav mode: ");
  uint8_t setNav[] = {
    0xB5, 0x62, 0x06, 0x24, 0x24, 0x00, 0xFF, 0xFF, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 0x05, 0x00, 0xFA, 0x00, 0xFA, 0x00, 0x64, 0x00, 0x2C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0xDC                        };
  while(!gps_set_sucess)
  {
    sendUBX(setNav, sizeof(setNav)/sizeof(uint8_t));
    gps_set_sucess=getUBX_ACK(setNav);
  }
  gps_set_sucess=0;
}

unsigned int charsToInt(unsigned char loByte, unsigned char hiByte)
{
  unsigned int temp = 0;
  temp = loByte + (hiByte<<8);
  return temp;
}

unsigned char lo(unsigned int input)
{
  unsigned char temp = 0;
  temp = (unsigned char)(input & 0xFF);
  return temp;
}

unsigned char hi(unsigned int input)
{
  unsigned char temp = 0;
  temp = (unsigned char)((input>>8) & 0xFF);
  return temp;
}

###################################################################################
void loop()
{
  unsigned char b = 0;
  long int counter = 10000;
  int x = 0;
  int mem;
  while(1)
  {
    counter--;
    x = counter % 10000;
    if (x == 1)
    {
      Serial.println(counter);
    }

    if (counter==0)
    {

      counter = 100000;
      digitalWrite(GreenLED, LOW);
      digitalWrite(RedLED, HIGH);
      readSensors();
      sprintf(logString, "NOGPS,%i,%lu,0,0,0,%i,%i,%i,%i", sentance_id++, time, TempA, TempB, PresA, PresB);
      Serial.println(logString);
      writeSD();

     sprintf(UKHAS,  "&&XXXXXXXX,%i,NOGPS", sentance_id);

      Serial.println(UKHAS);

      writeRADIO();

    }
    if(Serial3.available() & 0)
    {

       b=Serial3.read();

       if (gps.encode(b))
       {
        Serial.println("TEST");
         counter = 1000000;
         digitalWrite(GreenLED, HIGH);
         digitalWrite(RedLED, LOW);
         //Serial.println("Got valid GPS data");
         // read values from the gps.
         gps.get_position(&lat, &lon, &fix_age);
         gps.get_datetime(&date, &time, &fix_age);
         alt = gps.altitude();
         Serial.print("alt=");
           Serial.println(alt);
         vel = gps.speed();
         bearing = gps.course();
         gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &fix_age);
         readSensors();
         //if (time > (oldtime + 1000))
         //{
           // print the details to BT and SD every 10 seconds
           oldtime = time;
           // comaptible comms protocol: http://ukhas.org.uk/communication:protocol
       sentance_id++; //count number of packets
           char timeS[10] = {time/100};
           char hour[10];

           alt = alt / 100; //convert from cm to m
           //if (alt > 50000){ //if nonsense altitude
          //   alt = -1;
          // }
           double dlat = double(lat);
          //char slat[10];
           dtostrf(dlat/1000000, 8, 6, slat);
           if (lon > 0){ //if west of meridian
             lon = lon * -1;
           }
           double dlon = double(lon);
           //char slon[10];
           dtostrf(dlon/1000000, 8, 6, slon);
           sprintf(UKHAS, "$$XXXXXXXX,%i,%06lu,%s,%s,%lu", sentance_id, time/100, slat, slon, alt);
           //sprintf(UKHAS, "$$XXXXXXXX,%i,%lu:%lu:%lu,%s,%s,%lu", sentance_id, hour, minute, second, slat, slon, alt);
           //change time format
             sprintf(logString, "LOG,%i,%lu,%s,%s,%lu,%i,%i,%i,%i", sentance_id++, time, slat, slon, alt, TempA, TempB, PresA, PresB);
           Serial.println(logString); //debug
           //Serial2.println(logString); //Bluetooth
           Serial.println(UKHAS); //debug
           //50 buad 500Hz
           writeSD();
           writeRADIO();
         //}
       }
    }//if GPS available
  }//while(1)
}//loop
###########################################################################
void writeRADIO()
{
 //digitalWrite(RADIOEN,HIGH);
 //delay(10);
 //Serial.println(UKHAS);

 snprintf(datastring,80,UKHAS); // Puts the text in the datastring

 unsigned int CHECKSUM = gps_CRC16_checksum(datastring); // Calculates the checksum for this datastring

 char checksum_str[8];

 sprintf(checksum_str, "*%04X\n", CHECKSUM);

 strcat(datastring,checksum_str);
Serial.println(datastring);
 rtty_txstring (datastring);

Serial.println("MS");
 //digitalWrite(RADIOEN,LOW);
}

void writeSD() //write sensor log to file on SD card
{
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
  myFile = SD.open("log.txt", FILE_WRITE);
  // if the file opened okay, write to it:

  if (myFile) {
    Serial.print("Writing to SD card");
    //write full telemetry packet
     myFile.println(logString);

    //close the file:
    myFile.close();
    Serial.println("done.");
  }
   else {
     //if the file didn't open, print an error:
    Serial.println("error opening SD card file");
  }
}

void readSensors()
{
  TempA = analogRead(TempAPin);
  TempB = analogRead(TempBPin);
  PresA = analogRead(PresAPin);
  PresB = analogRead(PresBPin);
  BatteryVoltage = analogRead(BatteryVoltagePin);
}

void rtty_txstring (char * string)
{

/* Simple function to sent a char at a time to
 ** rtty_txbyte function.
 ** NB Each char is one byte (8 Bits)
 */

char c;

c = *string++;

while ( c != '\0')
 {
 rtty_txbyte (c);
 c = *string++;
 }
}
void rtty_txbyte (char c)
{
 /* Simple function to sent each bit of a char to
 ** rtty_txbit function.
 ** NB The bits are sent Least Significant Bit first
 **
 ** All chars should be preceded with a 0 and
 ** proceed with a 1. 0 = Start bit; 1 = Stop bit
 **
 */

int i;

rtty_txbit (0); // Start bit

// Send bits for for char LSB first

for (i=0;i<7;i++) // Change this here 7 or 8 for ASCII-7 / ASCII-8
 {
 if (c & 1) rtty_txbit(1);

else rtty_txbit(0);

c = c >> 1;

}
rtty_txbit (1); // Stop bit
rtty_txbit (1); // Stop bit
}

void rtty_txbit (int bit)
{
 if (bit)
 {
 // high
 analogWrite(RADIOPIN,115);
 }
 else
 {
 // low
 analogWrite(RADIOPIN,100);
 }

// delayMicroseconds(3370); // 300 baud
 delayMicroseconds(10000); // For 50 Baud uncomment this and the line below.
 delayMicroseconds(10150); // You can't do 20150 it just doesn't work as the
 // largest value that will produce an accurate delay is 16383
 // See : http://arduino.cc/en/Reference/DelayMicroseconds

}

uint16_t gps_CRC16_checksum (char *string)
{
 size_t i;
 uint16_t crc;
 uint8_t c;

crc = 0xFFFF;

// Calculate checksum ignoring the first two $s
 for (i = 2; i < strlen(string); i++)
 {
 c = string[i];
 crc = _crc_xmodem_update (crc, c);
 }

return crc;
}

void setPwmFrequency(int pin, int divisor) {
 byte mode;
 if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
 switch(divisor) {
 case 1:
 mode = 0x01;
 break;
 case 8:
 mode = 0x02;
 break;
 case 64:
 mode = 0x03;
 break;
 case 256:
 mode = 0x04;
 break;
 case 1024:
 mode = 0x05;
 break;
 default:
 return;
 }
 if(pin == 5) {
 TCCR3B = TCCR3B & 0b11111000 | mode;
 }
 else {
 TCCR2B = TCCR2B & 0b11111000 | mode;
 }
 }
 else if(pin == 3 || pin == 11) {
 switch(divisor) {
 case 1:
 mode = 0x01;
 break;
 case 8:
 mode = 0x02;
 break;
 case 32:
 mode = 0x03;
 break;
 case 64:
 mode = 0x04;
 break;
 case 128:
 mode = 0x05;
 break;
 case 256:
 mode = 0x06;
 break;
 case 1024:
 mode = 0x7;
 break;
 default:
 return;
 }
  TCCR3B = TCCR3B & 0b11111000 | mode;
 }
}

// Send a byte array of UBX protocol to the GPS
void sendUBX(uint8_t *MSG, uint8_t len) {
  for(int i=0; i<len; i++) {
    Serial3.write(MSG[i]);
    Serial.print(MSG[i], HEX);
  }
  Serial3.println();
}

// Calculate expected UBX ACK packet and parse UBX response from GPS
boolean getUBX_ACK(uint8_t *MSG) {
  uint8_t b;
  uint8_t ackByteID = 0;
  uint8_t ackPacket[10];
  unsigned long startTime = millis();
  Serial.print(" * Reading ACK response: ");

  // Construct the expected ACK packet
  ackPacket[0] = 0xB5;  // header
  ackPacket[1] = 0x62;  // header
  ackPacket[2] = 0x05;  // class
  ackPacket[3] = 0x01;  // id
  ackPacket[4] = 0x02;  // length
  ackPacket[5] = 0x00;
  ackPacket[6] = MSG[2];    // ACK class
  ackPacket[7] = MSG[3];    // ACK id
  ackPacket[8] = 0;     // CK_A
  ackPacket[9] = 0;     // CK_B

  // Calculate the checksums
  for (uint8_t i=2; i<8; i++) {
    ackPacket[8] = ackPacket[8] + ackPacket[i];
    ackPacket[9] = ackPacket[9] + ackPacket[8];
  }

  while (1) {

    // Test for success
    if (ackByteID > 9) {
      // All packets in order!
      Serial.println(" (SUCCESS!)");
      return true;
    }

    // Timeout if no valid response in 3 seconds
    if (millis() - startTime > 3000) {
      Serial.println(" (FAILED!)");
      return false;
    }

    // Make sure data is available to read
    if (Serial3.available()) {
      b = Serial3.read();

      // Check that bytes arrive in sequence as per expected ACK packet
      if (b == ackPacket[ackByteID]) {
        ackByteID++;
        Serial.print(b, HEX);
      }
      else {
        ackByteID = 0;  // Reset and look again, invalid order
      }

    }
  }
}

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

referring to the graphs ... what are the sample index numbers, sample values and milli() values on either side of the anomalies

@jsotola the data is extracted from the logs, which doesn't save the millis() value. What do you mean by "either side of the anomalies"? The anomalies are the long stretches of data close to ground level (<500m), so I'm not sure what to say for values "either side" of them.

i am thinking that the long vertical lines are the transitions between valid data and invalid data (anomalies is not the correct term) ... i was trying to ask for infornation about the one or two data points before the vertical lines, and one or two points after the vertical lines

You're correct, the vertical lines are where it switches between realistic and nonsense data (and vice-versa). The smaller vertical lines (such as on the descent in the 2019 graph at around 39,000s) look like the altitude value is just "sticking" for a while (for example it stays at 29,732m for about 90s, before updating the value to 25,653m). Data packets are generated approximately every 11-12s. I will update the question describing what we're seeing in the packets, as there is something odd happening during these "stuck" values.

Is this a real U-blox GPS module? There are a lot of fake ones around.. Altitude measured by GPS is generally not very accurate. Have you thought about measuring altitude with an altimeter (air pressure sensor)?

@StarCat hmm, you may be right, it does look like the module we are using is counterfeit (based on the label anyway, I will check the GPTXT data when I get a chance). We bought 2 modules at the same time, and the other one appears to be genuine (I'm just checking where we bought them from). I guess it's hard say whether this is the cause, but with the added observation it still looks like there is a coding issue perhaps? The lack of accuracy is fine, even it it's out by 100s of m. However there is a pressure sensor on the tracker, so I will add a "backup" altitude estimation from that.

I've tried the module that appears to be genuine, but still get the same behaviour. Also, even if the modules are counterfeit (and some were purchased several years apart, and from different companies), it seems relatively unlikely that they would fail in exactly the same way, so it still seems like it is a coding problem of some kind to me.