text:
Compensate weight due to acceleration (load cells)
I'm trying to make a weighing scale that works in a lift. I'm using load cells to measure the weight, let's say it's F. Then I use that weight F and g which I know is 9,81 m/s2 to calculate the mass of the object like this:
F = m·g <=> m = F/g
This works when the lift is in rest (or when moving at a constant speed), but when it accelerates the weight F increases and because of that the mass also increases. Is there a way to compensate this weight(/extra force) due to acceleration?

Maybe measure the effective g with an accelerometer?

Of cause it's possible. g is an acceleration. If the lift accelerates, you have to measure the acceleration, with an accelerometer. Then use the found acceleration instead of g in the formula. The resulting acceleration, you measure, is g plus(up)/minus(down) the lifts accelleration.

only weight when the lift isn't moving. 2. Have a separate load cell with a known weight on top, so you can calculate the acceleration. 3. Average the values over time, to average out the error due to the short moment of acceleration (most lifts only accelerate/decelerate for a few seconds).  4. Ignore it all together as lift only accelerate at 1m/s², giving you, at most, a 10% error is weight, which might be acceptable depending on the application.

You could measure the total acceleration (g + lift acceleration) with an accelerometer, and use that value in your calculation instead of 9.81m/s2. If the measured value is 0, sound an alarm.
Or, assuming the elevator only accelerates/decelerates for short periodes only (say, less than 2s) during a "trip", you could make a series of measurements in a loop at, say, every 0.5s.
When you get, say, 5 measurements that are the same, or very close to each other, you know acceleration = 0 and you can average those 5 measurements to get the desired result.
Values may vary depending on the lift, and the measurements will be slow in coming.

The force due to acceleration is: F = m*a
So to calculate the weight while accelerating the formula is:
F = mg + ma or F = m(g + a)
Note, of course, that a can be positive or negative depending on whether the elevator is accelerating or decelerating.
The trick here is to know what "a" is.  The best approach is probably to get an accelerometer and use its reading in your calculations.
By the way, the mass is always a constant here.  It does not change, in Newtonian Physics at least, due to acceleration.

Note that an accelerometer actually measures a+g.


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

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

Here is my code:
////// WAVE SHIELD HEADERS //////
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
/////////////////////////////////

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

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

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

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

Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

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

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

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

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

#define DEBOUNCE 100  // button debouncer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  char charUID[7];

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

  Serial.println();

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

  uint8_t amiiboNo = 0;

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

  Serial.println(amiiboNo);

  uint8_t clipNo = random(3);

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

    }
}

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

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

    uint8_t * ID{};

    waitForRFID();

    playSoundClip();

}

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

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

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

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

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

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

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

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

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

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

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

}

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

My first guess for what may be taking up the most memory is the switch statement. When I uncomment that, the memory usage jumps from 90% to over 130%. I've tried other ways to get this code to work, like concatenating text, but this is the only way that seemed to work reliably, until I ran out of memory.
I'm also using a lot of libraries to help use the shields and LCD I have attached to the Uno. I couldn't get rid of those libraries without compromising the project.
Other than that, I don't know what to do. If anyone has any suggestions for condensing the code down, I'd really appreciate any advice you have to offer.
Thanks.

Honestly I don't see much potential for optimziation without touching the libraries. Commenting the switch case gives you that much memory, because the compiler then optimizes out all the wav playing stuff, that is only used in the switch statement. Maybe you should switch to a board with more RAM

I think you can put all the string literals in program space with the string helper, but I don't think, that this will be enough, since you want to get to maybe 75% (the compiler doesn't count all local variables I believe)

The memory usage here clearly comes from the libraries you use. The combination of SD card reader library + LCD + NFC reader seems just too big for an Arduino Uno. I'm unable to build your code, as I can't find the libraries you're using. Are these standard libraries installed trough the library manager?

nitpick: Arduino Uno has an ATmega328, which has SRAM, not DRAM. The phrase "dynamic memory" seems to mean just dynamic in a more generic sense, i.e. volatile memory used at run-time, as opposed to the non-volatile program memory that's mostly static wrt. run-time use. On the other hand, DRAM is a particular way of implementing (volatile) RAM.

You have a huge switch...case here to decide the name of the file that
should be played. This costs a lot of code space, but also data space,
because every single literal string in this portion of code gets copied
to RAM during initialization.
There is no need to spend all this cost, as the file names have been
assigned in a very regular fashion, so you can build the file name
algorithmically. As a general rule, whenever you find yourself
programming by copying, pasting, then applying some predictable
modifications to the copies, you are almost certainly doing something
wrong. Making repeated copies of the same thing, with predictable
changes is what computers are best for. So you have to ask yourself how
you can instruct the computer (in this case, the Arduino) to do that for
you. Do not do the computer's job yourself!
In this case, the file name is built by gluing three pieces together:

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

The prefix cannot be computed algorithmically, so you still have to
write down all the possible prefixes. You could use a big
switch...case for this, but it is way more convenient to pick the
right prefix from an array indexed by amiiboNo:
const char *file_prefixes[] = {
    "MARIO", "MK",    "INK",    "DK",    "LUCAS", "DUCKH",  "OOT",
    "BOTWL", "8BITL", "TOONL",  "GANDW", "FALCO", "DEDEDE", "MEWTWO",
    "CAPF",  "ROB",   "PACMAN", "CLOUD", "NESS",  "RYU"
};

Then, you declare an array of char for holding the file name, and you
build that file name by putting together the three pieces listed above.
Your whole switch...case can then be replaced by this:
char filename[13];           // longest file name: 12 characters + NUL
char file_number[3] = "01";  // 2 digits + NUL
file_number[1] += clipNo;    // file_number: "01", "02" or "O3"
strcpy(filename, file_prefixes[amiiboNo]);
strcat(filename, file_number);
strcat(filename, ".WAV");
playComplete(filename);

This will already save you a lot of RAM, but probably not enough. I did
not see any obvious inefficient use of variables in your program (but I
did not look in too much detail), so we will continue to aim at literal
strings.
The problem with literal strings is the fact that they get copied from
flash to RAM during initialization, and whereas you probably have enough
flash, the RAM is in short supply. This is a problem specific to Harvard
architectures, as they have separate address spaces for code and data.
We can use some AVR-specific tricks to instruct the compiler not to
perform this copying. This makes it harder to access the data because
C++ does not natively know about address spaces. Fortunately, there are
some macros and helper functions that can make it easy in specific
cases.
The best know such helper in Arduino world is the F() macro. Use it
every time you print() or println() a literal string, as in:
Serial.println(F("Waiting for an amiibo ..."));

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

by something like
if (strcmp_P(charUID, PSTR("479119425560128")) == 0)

Note that the value returned by strcmp_P() has to be compared to 0, as
this is what that function, just like strcmp(), returns in case of
equality. Thanks to timemage for noticing this issue.
Last, we could also keep all the file prefixes in flash, but this would
be trickier. For now, I suggest you apply the tricks described here and
see whether they are enough to make your program fit.
Edit: more on the somewhat obscure statement:
file_number[1] += clipNo;
In C++, a char is an 8-bit number. Depending on the platform, it can
be either signed (range: −128…+127) or unsigned (0…255). The name comes
from the fact that it is most often used to store the numeric value of an
ASCII character. For example, the numeric value 33 means '!', 48 means
'0', and 65 means 'A'.
The definition
char file_number[3] = "01";

creates a 3-cell array initialized with the following content:
             ┌─────┬─────┬─────┐
file_number: │  48 │  49 │   0 │
             └─────┴─────┴─────┘

Using the language notation for characters, the contents could also be
written as follows:
             ┌─────┬─────┬─────┐
file_number: │ '0' │ '1' │ '\0'│
             └─────┴─────┴─────┘

The last cell with the ASCII NUL is there to inform library functions
such as strcat() that this is where the string of characters ends.
The statement
file_number[1] += clipNo;

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

I know this originated in the O.P.'s code, and you I know that you know this, but strcmp(_P) returns 0 for "equal".

@timemage: Oops! You are right. I know but I didn't pay attention. I added that to the answer, just to make it more prominent.

As soon as I get the opportunity, I’ll implement these fixes and get back with you on the progress. Thank you for the help!

As a minor addendum to Edgar Bonet's excellent answer, you could simplify your code further and save even more memory by renaming your files.
In particular, instead of storing a list of character names indexed by Amiibo number and using those as the filename prefix, why not use the Amiibo numbers directly?  That is, instead of your files being named

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

you could just name them e.g.

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

and construct the name in your code e.g. like this:
char filename[13];
int len = snprintf(filename, sizeof(filename), "AMI%02d_%02d.WAV", amiiboNo + 1, clipNo + 1);
if (len < 0 || len >= sizeof(filename)) {
  // TODO: handle error or insufficient buffer size here
}

The main advantage here is that you'll save memory by not having to store the list of character names.  The tradeoff, of course, is that your filenames will now be a lot less descriptive.
You could probably optimize this a bit more by manipulating the bytes of the filename directly like Edgar does.  But personally I'd suggest starting with the generic snprintf based solution and only switching to direct byte manipulation if it's still too much. At least I'd assume that the snprintf implementation in the standard library is probably going to be fairly well optimized for a low footprint.  Of course I could be wrong.

snprintf() is a good suggestion. It will likely cost more flash than strcpy() and strcat() combined because, even if you only use %02d, the function carries support for a wide range of conversion specifiers. I do think it is a good choice, if you have enough flash (likely the case here), because it makes the code simpler. It's interface, however, may not be very novice-friendly. OTOH, my file_number[1] += clipNo; statement is probably not novice-friendly either. :-/

@EdgarBonet, as a novice, I can attest, I was a bit thrown off by the file_number[1] += clipNo; statement, haha. If you have the time, would you mind explaining what you did there?

Update: It works! After changing the string literals and file names via yours' and @EdgarBonet 's suggestions, my program sits at 84% memory. I'll probably tamper around with it a bit more to eek out some extra features. Thank you both!

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

I’ve considered getting a Mega; it seems worthwhile. Unfortunately this is a project that’s due in a few days. I may grab it just to satiate my own curiosity though. Thanks for the suggestion.

I generally start with a larger processor such as a Mega and when finished I can put it in a smaller unit. This gives me room for the debugging print statements etc.

So, I borrowed a Mega from my professor and tried it out yesterday. As it turns out, the wave shield I'm using to read audio files and play to a speaker explicitly lists the Mega as a version of Arduino that is NOT supported, for some reason. It really sucks; I wanted to expand the scope of this project significantly, but what can you do?

source: Stack Exchange

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

sort: votes


text:
Message is sent multiple times from one arduino to another, using nRF24L01
I am trying to build a bidirectional communication channel, using nRF24L01 and two arduinos. The message is introduced using a button (but) in Morse code, decoded and then sent when another button (but_send) is pressed.
Although everything seems to work fine, the message is sent multiple times even though I added delays. I am a beginner in Arduino and I have no idea what else i could do. I even tried deleting the string right after radio.write, but it doesn't seem to work either. If anyone has an idea, please help!

These are the two codes. They are quite similar, but i added them both just in case:
#include <LiquidCrystal.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
struct record
{
  char mesaj[10];
  boolean state = 1;
};

typedef struct record Record;
Record  button_state, button_state1 ;
RF24 radio(9, 10); // CE, CSN(pini nrf01)
const byte addresses [][6] = {"00001", "00002"};  //Setting the two addresses. One for transmitting and one for receiving
String code = "";
int len = 0;
char ch;
int ok;
char new_char;
int i1 = 0;
int i2 = 1;
const int but_send = 8;
const int but = 5;
const int led = 4;
const int del = 3;
String a = "";
unsigned long pres_len = 0, rel_time, pres_time = 0, old_time_len = 0, old_pres = 0, space = 0;
int state = 0;
int unit_delay = 250;
int min_delay = 10;
int buttonState = 0;

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

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

  code = "";
}
void sendText()
{
  // Aici trebuie sa fe codul pentru trimiterea efectiva a msj
  if (ok == 1) {
    Serial.println("Lavinia:" + a);
  }
  ok = 0;

  delay(100);
}
void setup() {
  Serial.begin(9600);
  pinMode(but, INPUT_PULLUP);
  pinMode(but_send, INPUT_PULLUP);
  pinMode(del, INPUT_PULLUP);

  pinMode(led, OUTPUT);
  radio.begin();                           //Starting the radio communication
  radio.openWritingPipe(addresses[0]);     //Setting the address at which we will send the data
  radio.openReadingPipe(1, addresses[1]);  //Setting the address at which we will receive the data
  radio.setPALevel(RF24_PA_MIN); //You can set it as minimum or maximum depending on the distance between the transmitter and receiver.

}
void loop() {

label:
  while (digitalRead(but) == HIGH) {
    delay(5);
    radio.startListening();

    if (radio.available())                     //Looking for incoming data
    {
      radio.read(&button_state, sizeof(button_state));
      if (button_state.state == 0)
      {

        ok = 1;
        sendText();
        String final = "";

        for (int i = 0; i < strlen(button_state.mesaj); i++)
        {
          final += String(button_state.mesaj[i]);
        }
        ok = 1;
        Serial.println("Iulia: " + final);
        button_state.state = 1;
        radio.stopListening();
      }
      else
      {
        //nu se intampla nimic daca eu nu am trimis mesaj

      }
      delay(5);

      radio.stopListening();                           //This sets the module as transmitter
      button_state1.state = digitalRead(but_send);
      int n = a.length();
      char char_array[n + 1];
      strcpy(char_array, a.c_str());
      strcpy(button_state1.mesaj, char_array);
      radio.write(&button_state1, sizeof(button_state1));   //Sending the data
    }

    if (digitalRead(del) == LOW && a[0] != '\0' ) {
      Serial.println("Deleted string");
      a = "\0";
      Serial.println(a);
    }

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

  }

  Morse_decod();
  delay(1000);

}

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN(pini nrf01)
#include <LiquidCrystal.h>
struct record
{
  char mesaj[10];
  boolean state = 1;
};

typedef struct record Record;
const byte addresses [][6] = {"00001", "00002"};  //Setting the two addresses. One for transmitting and one for receiving
String code = "";
int len = 0;
char ch;
int ok;
int ok2;
char new_char;
int i1 = 0;
int i2 = 1;
const int but_send = 8;
const int but = 5;
const int led = 4;
const int del = 3;
String a = "";
unsigned long pres_len = 0, rel_time, pres_time = 0, old_time_len = 0, old_pres = 0, space = 0;
int state = 0;
int unit_delay = 250;
int min_delay = 10;
Record  button_state, button_state1 ;

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

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

  code = "";
}
void sendText()
{
  // Aici trebuie sa fe codul pentru trimiterea efectiva a msj
  if (ok == 1) {
    Serial.println("Iulia:" + a);
  }
  ok = 0;

  delay(100);
}
void setup() {
  Serial.begin(9600);
  pinMode(but, INPUT_PULLUP);
  pinMode(but_send, INPUT_PULLUP);
  pinMode(del, INPUT_PULLUP);

  pinMode(led, OUTPUT);
  radio.begin();                           //Starting the radio communication
  radio.openWritingPipe(addresses[1]);     //Setting the address at which we will send the data
  radio.openReadingPipe(1, addresses[0]);  //Setting the address at which we will receive the data
  radio.setPALevel(RF24_PA_MIN); //You can set it as minimum or maximum depending on the distance between the transmitter and receiver.

}
void loop() {
label:
  while (digitalRead(but) == HIGH) {

    delay(5);
    radio.stopListening();                             //This sets the module as transmitter
    button_state.state = digitalRead(but_send);

    int n = a.length();
    char char_array[n + 1];
    strcpy(char_array, a.c_str());
    strcpy(button_state.mesaj, char_array);
    radio.write(&button_state, sizeof(button_state));  //Sending the data
    delay(5);

    radio.startListening();                            //This sets the module as receiver
    if (radio.available())
    {
      radio.read(&button_state1, sizeof(button_state1)); //Reading the data
      String final = "";
      if (button_state1.state == 0)      {
        ok = 1;

        sendText();
        for (int i = 0; i < strlen(button_state1.mesaj); i++)
        {
          final += String(button_state1.mesaj[i]);
        }
        Serial.println("Lavinia: " + final);
        button_state1.state = 1;
      }

    }

    if (digitalRead(del) == LOW && a[0] != '\0' ) {
      Serial.println("Deleted string");
      a = "\0";
      Serial.println(a);
    }

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

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

    }

  }

  Morse_decod();
  delay(1000);

}

I believe the relevant part would be:
    int n = a.length();
    char char_array[n + 1];
    strcpy(char_array, a.c_str());
    strcpy(button_state.mesaj, char_array);
    radio.write(&button_state, sizeof(button_state));  //Sending the data
    delay(5);

where a is the message to be sent.

Try creating a new, simple project that sends a number from 1 arduino to the other. If you send it from the setup() function, it should only be sent once. If you get that working, try creating a simple program that sends a "1" when a button is pressed and a "0" if the button is released. When that works, build your morse project from that. It's easier to debug short, simple programs and make one bit work at a time.

@jkp Hi there. Thanks for answering this! I have tried doing this, as i started from a simple project which worked. But since i added more functionalities, it seems like something goes wrong somewhere. Do you have any general idea what could be wrong in the code, perhaps the delays?

(Too few characters in comments, so writing as answer instead)
It's a bit hard to figure out without having the setup here and I don't think I have any of the radio modules in my box.
What I think is happening is this.
It seems like the first code will not send anything unless it receives a message from the second code, because the radio.write is inside the radio.available if-block. But when it receives a message, the message to send back must be present, so you start by entering a message on Arduino1.
Then you enter a message on Arduino2. You press the button, it skips the while loop below the label. When you release the button, it will enter the while loop and send the message. For both versions, the message will be sent as soon as 'but' is released. but_send is copied to the record that is sent, but the sending does not depend on the state of this button. You need an if statement that checks but_send to do this. The effect is, that you can only send '.' or '-' because the message is sent right away, before you get to enter more dots or dashes.
Anyways, the message from Arduino2 is received by Arduino1. If the state field of the message is 1, the message is written to Serial. Then the message from Arduino1 is send to Arduino2. Since we are not pressing any buttons, the message from Arduino 2 is send again and again and again. The state field will be 0, because but_send is not pressed, but the message is sent anyway. This triggers a new send on Arduino 1, because it receives something from Arduino 2 and gets into the radio.available part.
It seems like the messages will bounce back and forth. The only reason you don't see your Serial console filled with letters is that state is 0 for most of the messages, because you release btn_send. But as long as you hold down btn_send, it will set state=1 and print the message at the receiving end.
To prevent this, you should not call radio.write unless btn_send is released. That is going from LOW to HIGH. To test this, have a variable called old_btn_send and do something like this:
Initialize old_btn_send to HIGH in setup()
if (old_btn_send == LOW && digitalRead(btn_send) == HIGH {
    [do the sending thing]
}
old_btn_send = digitalRead(btn_send);

That is, you press btn_send. We will not enter the if block, but old_btn_send will be LOW. When you release, the condition will be true, but only once, because old_btn_send will be HIGH after the if block.
Please note, that what I write is from reading the code and not doing any testing, so I might be completely wrong :)

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


text:
ESP32 can't enter interrupt anymore after interrupt appears during delayMicrosecond function
I have a strange problem with my ESP32 project. I use an ADPS-9960 for gesture control which triggers an external interrupt. In the interrupt handler itself I only set a variable that causes the execution of a function in the loop. When I trigger an interrupt during the delay function the interrupt stops working. This means the loop is still running, but the interrupt routine doesn't get executed anymore.
#include <Arduino.h>
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <ESP32Servo.h>
// Pins
#define APDS9960_INT    25 // Needs to be an interrupt pin

#define SERVO 4

// Constants
// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;
void IRAM_ATTR interruptRoutine();
int detectorPin = 19;

Servo myservo;

void setup()
{
  // Set interrupt pin as input
  pinMode(APDS9960_INT, INPUT_PULLUP);
  // Initialize Serial port
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("--------------------------------"));
  Serial.println(F("SparkFun APDS-9960 - GestureTest"));
  Serial.println(F("--------------------------------"));

  // Initialize interrupt service routine
  attachInterrupt(digitalPinToInterrupt(APDS9960_INT), interruptRoutine, FALLING);
  // Initialize APDS-9960 (configure I2C and initial values)
  if ( apds.init() )
  {
    Serial.println(F("APDS-9960 initialization complete"));
  }
  else
  {
    Serial.println(F("Something went wrong during APDS-9960 init!"));
  }
  apds.setGestureGain(GGAIN_1X); // ohne diese Zeile geht es nicht zuverlässig

  // Start running the APDS-9960 gesture sensor engine
  if ( apds.enableGestureSensor(true) )
  {
    Serial.println(F("Gesture sensor is now running"));
  }
  else
  {
    Serial.println(F("Something went wrong during gesture sensor init!"));
  }

  myservo.attach(SERVO);
  myservo.write(20);

  pinMode(detectorPin, INPUT);
}

void loop()
{
  if( isr_flag == 1 )
  {
    detachInterrupt(digitalPinToInterrupt(APDS9960_INT));
    handleGesture();
    isr_flag = 0;
    attachInterrupt(digitalPinToInterrupt(APDS9960_INT), interruptRoutine, FALLING);
  }

  if(digitalRead(detectorPin))
    Serial.println("ON");

  else
    Serial.println("OFF");
}

void IRAM_ATTR interruptRoutine()
{
  if(isr_flag == 0)
    isr_flag = 1;
}

void  handleGesture()
{
    if ( apds.isGestureAvailable() )
    {
      if( apds.readGesture() == DIR_FAR )
      {
        Serial.println("FAR");
        myservo.write(165);
        delayMicroseconds (5000000);
        myservo.write(20);
      }
      else
        Serial.println("FALSE");
  }
}

isr_flag needs to be declared as volatile. Please do this and try again

Hey @chrisl thanks for your reply. I changed it to volatile int isr_flag = 0;  but unfortunaltely the problem is still present.

Why are you using delayMicroseconds() for delaying 5s. I think the parameter type is only unsinged int. According to the Arduino documentation the max is 16383us. Please use delay() for such long delays. In older versions delayMicroseconds() also disabled interrupts. So that might be your problem

I used dealyMicroseconds() because I missunderstood the documentation of àttachInterrupt(). Unfortunately usingdelay()` didn't solve the problem, if an interrupt appears during the delay function I am still not able to enter the interrupt after this. The problem is very hard to localize as there seems no good way to debug in the Arduino IDE.

Can you please check, when exactly the ISR is executed (especially after the first delay() call), by connecting a LED and toggling it in the ISR (but not in the if statement, just in the ISR)?

@chris Thanks again for the reply. When i make the gesture during the delay the ISR doesn't seem to be executed as the LED doesn't get toggled.
I have looked in the reference example and I have noticed  something strange. They declare 2 as interrupt pin, but then use 0 in the attachInterrrupt/detachInterrupt, this have to be a mistake right?
link

Mhh, now I don't see any more reasons, why the ISR shouldn't trigger again after the 5s and the servo movement. Are you sure, that the delay is the problem? Maybe remove it and try again. I'm currently poking in the dark a bit

Yes I'm pretty sure this has to do something with the delay, because when I use a gesture which causes a execution of the else block in handleGesture() there seems to be no problem. The thing I will try next is using a simple button for the external interrupt and look if anything changes. Thanks for your support so far!


text:
How can I make this program take up less memory?
I'm measuring how long it takes to drain a battery. An Arduino Nano controls an SSD1036 OLED display, a board with two relays, and an INA3221 voltage/current measurement board.
The battery is connected to the INA3221, then to a resistor. A relay in this circuit allows me to disconnect the battery.
I've tested each part of the setup separately, and it all works. When I combine the code into a single program, the getTime() function stops working. It is supposed to return the time as a formatted string (12:34:56), but it returns an empty string instead.
I've rewritten that function to use less memory, but that was insufficient: when I run the full program, with the time function modified as indicated in the linked question, the getTime() call still returns an empty string.
When I compile, I get this report:

Sketch uses 23088 bytes (75%) of program storage space. Maximum is 30720 bytes.
Global variables use 806 bytes (39%) of dynamic memory, leaving 1242 bytes for local variables. Maximum is 2048 bytes.

Because smaller parts of this program do work, I suspect I'm running out of memory. How can I fit this program into the memory of the Nano?
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <TimeLib.h>
#include <INA3221.h>
#include <Bounce2.h>

//D4 is relay 1, D5 is relay 2
#define Rel1 4
#define Rel2 5

//buttons
const int inputPin1 = 2;//D2 -stop measurement
const int inputPin2 = 6;//D6 - start measurement
Bounce bouncer1 = Bounce();
Bounce bouncer2 = Bounce();
int buttonState = LOW;
int stopMeting = 0;
int stopMeting1 = 0;
int stopMeting2 = 0;
float stopVoltage = 1.30;
String stopTijd1;
String stopTijd2;

//SSD1036 OLED
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

//timer
unsigned long previousMillis = 0;
const long interval = 1000; //in ms
char buffer[20] = {0};

//INA3221
#define SERIAL_SPEED 115200
#define PRINT_DEC_POINTS 3

INA3221 ina_0(INA3221_ADDR42_SDA);

float voltage1 = 0.0;
float current1 = 0.0;
float voltage2 = 0.0;
float current2 = 0.0;
float power1 = 0.0;
float power2 = 0.0;
float energy1 = 0.0;
float energy2 = 0.0;
float dEnergy1 = 0.0;
float dEnergy2 = 0.0;

void setup() {
  Serial.begin(115200);
  Serial.println("Start program");
  //buttons
  pinMode(inputPin1,INPUT_PULLUP);
  bouncer1.attach(inputPin1);
  pinMode(inputPin2,INPUT_PULLUP);
  bouncer2.attach(inputPin2);
  //relay
  pinMode(Rel1,OUTPUT);
  digitalWrite(Rel1,LOW);
  pinMode(Rel2,OUTPUT);
  digitalWrite(Rel2,LOW);

  //oled
  if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;); // Don't proceed, loop forever
  }
  display.clearDisplay();
  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);
  display.display();
  delay(2000);

  //time
  setTime(00,00,00,01,01,2024);

  //INA
  current_measure_init();
  delay(2000);

}

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

  bouncer1.update();
  int debouncedInput1 = bouncer1.read();
  bouncer2.update();
  int debouncedInput2 = bouncer2.read();

  if ( bouncer2.changed() ) {
    int debouncedInput2 = bouncer2.read();
    if ( debouncedInput2 == LOW ) {
      startMeting();
    }
  }

  if ( bouncer1.changed() and stopMeting == 0) {
    int debouncedInput1 = bouncer1.read();
    if ( debouncedInput1 == LOW ) {
      eindMeting();
      stopMeting = 1;
    }
  }

  String Tm = getTime();
  voltage1 = ina_0.getVoltage(INA3221_CH1);
  voltage2 = ina_0.getVoltage(INA3221_CH2);

  if (voltage1 < stopVoltage and stopMeting1 == 0) {
    stopMeting1 = 1;
    digitalWrite(Rel1,LOW);
    stopTijd1 = Tm;
  }
    if (voltage2 < stopVoltage and stopMeting2 == 0) {
    stopMeting2 = 1;
    digitalWrite(Rel1,LOW);
    stopTijd2 = Tm;
  }

  if (stopMeting1 == 1 and stopMeting2 == 1) {
    stopMeting = 1;
    eindMeting();
  }

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (stopMeting == 0) {
      updatedisplay(currentMillis);
      }
    }

}
void startMeting(void) {
  digitalWrite(Rel1,HIGH);
  digitalWrite(Rel2,HIGH);
}

void eindMeting(void) {
  digitalWrite(Rel1,LOW);
  digitalWrite(Rel2,LOW);
  setupdisplay();
  display.println("Eind meting");
  String Tm = getTime();
  Serial.println("Eind meting ");
  Serial.print(Tm);Serial.print(";");
  Serial.print(current1);Serial.print(";");
  Serial.print(voltage1);Serial.print(";");
  Serial.print(current2);Serial.print(";");
  Serial.print(voltage2);Serial.print(";");
  Serial.print(dEnergy1);Serial.print(";");
  Serial.print(dEnergy2);Serial.println(";");
  display.print("time "); display.println(Tm);
  display.print("E1 ");display.println(dEnergy1);
  display.print("E2 ");display.println(dEnergy2);
  //display.println(stopTijd1);display.println(stopTijd2);
  display.display();
}

void setupdisplay(void) {
  display.clearDisplay();
  display.setTextSize(1);      // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE); // Draw white text
  display.setCursor(0, 0);     // Start at top-left corner
  display.cp437(true);         // Use full 256 char 'Code Page 437' font
}

void updatedisplay(unsigned long currentMillis) {
  //INA
  current1 = ina_0.getCurrent(INA3221_CH1) * 1000;
  voltage1 = ina_0.getVoltage(INA3221_CH1);
  current2 = ina_0.getCurrent(INA3221_CH2) * 1000;
  voltage2 = ina_0.getVoltage(INA3221_CH2);
  power1= current1 * voltage1;
  power2= current2 * voltage2;
  if (stopMeting1 == 0) {
    energy1= energy1 + power1; //in mWs
  }
    if (stopMeting2 == 0) {
    energy2= energy2 + power2; //in mWs
  }
  dEnergy1 = (energy1/3600); //in mWh
  dEnergy2 = (energy2/3600); //in mWh
  String Tm = getTime();
  Serial.print(Tm);Serial.print(";");
  Serial.print(current1);Serial.print(";");
  Serial.print(voltage1);Serial.print(";");
  Serial.print(current2);Serial.print(";");
  Serial.print(voltage2);Serial.print(";");
  Serial.print(dEnergy1);Serial.print(";");
  Serial.print(dEnergy2);Serial.println(";");
  setupdisplay();
  display.print("time ");display.println(Tm);
  display.print(hour());display.print(minute());display.println(second());
  display.print("I1 ");display.println(current1);
  display.print("V1 ");display.println(voltage1);
  display.print("I2 ");display.println(current2);
  display.print("V2 ");display.println(voltage2);
  display.print("E1 ");display.println(dEnergy1);
  display.print("E2 ");display.println(dEnergy2);
  display.display();
}

String getTime(void) {
  snprintf(buffer, sizeof(buffer)-1,"%02d:%02d:%02d", hour(), minute(), second());
  return buffer;
}

void current_measure_init() {
    ina_0.begin(&Wire);
    ina_0.reset();
    ina_0.setShuntRes(100, 100, 100);
}

This question is similar to: How can I make this function take up less memory?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem.

As indicated in the other question, modifying the getTIme call as the answer suggested did not make the program small enough to fit yet.

don't repeat code

If you suspect a memory problem, remove all instances of the String class from your program. Use char buffers and the corresponding C functions instead. If it then still doesn't work your problem is somewhere else

This doesn't look like a memory problem. There's plenty of dynamic memory left.  I'm suspect of the function that tries to return a char array as a String but I'm not sure if that's actually a problem or not.

Further to @Delta_G's comment, the buffer is already a global char array that can be accessed by all the functions, there is no need to return it as a String.

Your initial memory allocations are pretty light. Program memory use isn't going to increase during the run, and I don't see any dynamic allocations from RAM, besides the call-stack, of course, which is well-behaved -- until/unless there are enough nested function-calls to over-write some static allocations (globals, typically). Without that, you aren't likely running out of memory.
Places to start looking are: 1) In the standard Arduino library, printf() and friends don't implement printing of floats. I don't know well behaved they are if you try. 2) Perhaps you're over-writing a some variable - an address or pointer, especially?
You say you've tested the pieces but the full program fails. I'd try adding in one piece at a time and test that much, until something fails. Then do it again but adding pieces in a different order. Does it fail on the same added piece or a different one?
Another approach is to replace each function, one at a time - with a stub - a function that has the same name and parameters but which does nothing except to return a valid value (if any return value is required). Or returns 'false' or an invalid value, if you suspect that to be what triggers the failure. Replace one function at a time by a stub until the program "works" (minus what that function was supposed to do, obviously) with the stub but fails with the function's full code. Now you can start stubbing major sections of that function's code, until again, the program starts working. Narrow the stubbed out section again, etc, ..., until you find the offending statement(s).

String getTime(void) {
  snprintf(buffer, sizeof(buffer)-1,"%02d:%02d:%02d", hour(), minute(), second());
  return buffer;
}

Since the result is already in buffer, why return it as a String? This could well cause heap fragmentation.
I strongly suggest you rewrite the entire code without using the String type.


text:
How to get air speed, which sensor to use?
I want to measure the airspeed on a flying vehicle and get the data with arduino. Note that, there will not be any control mechanism on the flying object, it will be flying mechanicaly/passively, I mean no flight controller or something like that will be present.
However, I could not understand whether there is a sensor to measure the airspeed directly or is airspeed something you analyze by using other datas(temperature, pressure etc.)
I saw there are sensors which are sold as "airspeed sensor" however it is not so common that I cannot find examples in which the incoming data is shown.
Anybody ever experienced with this issue may lighten me.
Thanks in advance.

please do not post at multiple sites ... https://robotics.stackexchange.com/questions/19830/how-to-obtain-airspeed-data

@jsotola why? I am not sure which community fits the best

Typically you want to use Pitot tube sensor


text:
Arduino IDE: sketch window has become unresponsive
I am very new to all this, but have programmed in other languages using several IDEs. Last night when returning to a coding session, I noticed that the background of the sketch window had gone from white to gray. Then when I tried to continue editing the sketch, I found that I could not make any changes. At all. Clicking anywhere on the screen is futile; the cursor never appears. Text can be highlighted but not copied or pasted. In short, I can’t go on from here at all.
What have I done?

You haven't done anything. It's Java. Notoriously bad at staying alive overnight. Kill it.

As one well-known IT guy would say, "Have you tried turning it on and off again"? :)

@duck dodgers: yes I have—multiple times. I’ve also tried using a bigger hammer and waving a dead chicken at it. I’ve not yet gotten to the point that I would kill a goat and examine its entrails, but I am getting close.

Interesting :). Then could you please possibly post a screenshot of the Arduino IDE here. I have never experienced something like this myself (barring minor glitches which one can get fixed by updating to a newer version).  Could you please state then the version number of your IDE, what operating system you are using, etc. It would be helpful.

(see my penultimate comment first please) p.s. you can also try something other than the Arduino IDE, just for the time, that you try to debug the problem with the "Arduino IDE".


text:
Send ECG data using buffer in real time to the server without using delay
I am trying to make a ECG monitoring system using Arduino, GSM and ECG sensor which data should be sent to the private server in real time. Those data are then collected via Matlab on the remote computer and analysis should be executed in real time. When using delays in Arduino sketch GSM successfully sends data to the server but those data are sent in big delays (around 30 seconds) and the sketch doesn't send the data of the whole buffer for some reason (it should be 300 samples, but I had to try to lower that number in order to see any results). After removing delays in the loop where data should be continuously sent, GSM is not executing send data command - AT+CIPSEND. Can anybody help me fix the timer issue and explain why is not the whole buffer sent? Thanks in advance.

#include <SoftwareSerial.h>
#include <String.h>
#include "DHT.h"
int sensorPin = 0;    // set the input pin for the potentiometer
int sensorValue = 0;
#define DHTPIN A0
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

#define DHT11_PIN A0

SoftwareSerial gprsSerial(7,8);

float t; // temperature in celcius
float f; // temperature in fahrenheit
float h; // humidity

  int samplesPerBuffer = 60;
  char separator = ',';
  String buffer = "";
  int currentBufferPosition = 0;
  unsigned long startSamplingTime = 0;
  const long sampleInterval = 50;

  // gsm modem config
  String gsmBuffer = "";
  int gsmSendingState = 0; // 0 not sending, 1 preparing sending, 2 sending, 3 finishing sending
//  int gsmSendInterval = 1000;

  int gsmPreparingDelay = 200;
  int gsmSendingDelay = 1500;
  int gsmFinishingDelay = 100;
  unsigned long startRequestTime = 0;

void setup() {
  // put your setup code here, to run once:
  gprsSerial.begin(9600);               // the GPRS baud rate
  Serial.begin(9600);    // the GPRS baud rate
  dht.begin();
  delay(1000);
  initModem();
}

float getSensorData() {
   t = dht.readTemperature();
  //Read humidity
  h = dht.readHumidity();

  // Compute temperature values in Celcius
  t = dht.computeHeatIndex(t,h,false);

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println("Failed to read temp from DHT sensor!");
    return 1;
  }

  return t;
}

void initModem() {
  // model init
  if (gprsSerial.available())
    Serial.write(gprsSerial.read());

  gprsSerial.println("AT");
  delay(1000);

  gprsSerial.println("AT+CPIN?");
  delay(1000);

  gprsSerial.println("AT+CREG?");
  delay(1000);

  gprsSerial.println("AT+CGATT?");
  delay(1000);

  gprsSerial.println("AT+CIPSHUT");
  delay(1000);

  gprsSerial.println("AT+CIPSTATUS");
  delay(2000);

  gprsSerial.println("AT+CIPMUX=0");
  delay(2000);

  ShowSerialData();

  gprsSerial.println("AT+CSTT=\"prepaidnet\"");//start task and setting the APN,
  delay(1000);

  ShowSerialData();

  gprsSerial.println("AT+CIICR");//bring up wireless connection
  delay(3000);

  ShowSerialData();

  gprsSerial.println("AT+CIFSR");//get local IP adress
  delay(2000);

  ShowSerialData();

  gprsSerial.println("AT+CIPSPRT=0");
  delay(3000);

  ShowSerialData();
}

void prepareSending() {
  gprsSerial.println("AT+CIPSTART=\"TCP\",\"website.com\",\"80\"");//start up the connection
  ShowSerialData();
}

void sendData() {
  int time = millis();
  gprsSerial.println("AT+CIPSEND");//begin send data to remote server
  String str="GET http://website.com/channel/" + gsmBuffer;
  Serial.println(str);
  gprsSerial.println(str);//begin send data to remote server
  gprsSerial.println((char)26);//sending
}

void finishSending() {
  gprsSerial.println("AT+CIPSHUT");//close the connection
}

void loop() {
 int time = millis();
 if (time - startSamplingTime >= sampleInterval) {
    if (buffer.length() == 0) {
      buffer = buffer + (String)getSensorData();
    }
    else {
      buffer = buffer + separator + (String)getSensorData();
    }
    currentBufferPosition++;
    startSamplingTime = time;
 }
 if (gsmSendingState == 0) {
   // copy buffer to gsmBuffer and triger preparing of the request
   if (currentBufferPosition == samplesPerBuffer) {
    Serial.println("GSM - Preparing sending");
    gsmBuffer = buffer;
    Serial.print("Buffer length: ");
    Serial.println(gsmBuffer.length());
    Serial.println(gsmBuffer);
    buffer = "";
    currentBufferPosition = 0;
    prepareSending();
   }

   // send data if we have something in gsmBuffer
   if (time - startRequestTime >= gsmPreparingDelay) {
    if (gsmBuffer.length() > 0) {
      Serial.println("GSM - Sending data");
      sendData();
      gsmBuffer = "";
      gsmSendingState = 1;
      startRequestTime= time;
    }
   }
 } else {
  if (gsmSendingState == 1) {
    if (time - startRequestTime >= gsmSendingDelay) {
      Serial.println("GSM - Finishing request");
      finishSending();
      gsmSendingState = 2;
      startRequestTime = time;
    }
  }
   else {
      if (gsmSendingState == 2) {
        if (time - startRequestTime >= gsmFinishingDelay) {
          Serial.println("GSM - Request finished");
          gsmSendingState = 0;
          startRequestTime = time;
        }
      }
   }
 }
}

void ShowSerialData()
{
  while(gprsSerial.available()!=0)
    Serial.write(gprsSerial.read());
    Serial.print("Temperature = ");
    Serial.println(t);
    Serial.print("Humidity = ");
    Serial.println(h);
    //delay(5000);
}

float readTemp() {
  // Read temperature as Celsius
  t = dht.readTemperature();
  //Read humidity
  h = dht.readHumidity();

  // Compute temperature values in Celcius
  t = dht.computeHeatIndex(t,h,false);

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println("Failed to read temp from DHT sensor!");
    return 1;
  }

  return t;
}

I tried with flush but it didn't resolve the problem. What I read yesterday after so much research is that the GSM module (I am using SIM900) cannot transmit more than 64 bytes with GET method, so I decided to try with the POST method, but no luck - code is returning HTTP 411 error - The request has an invalid header name. I tried some variants of resolving that problem but it didn't work. Does anyone have an ide how to resolve this? I haven't found some working example on the Internet, just some explanations which were unclear to me. The new code is below, along with the output.
/**************************************************************
 *
 * This sketch connects to a website and downloads a page.
 * It can be used to perform HTTP/RESTful API calls.
 *
 * TinyGSM Getting Started guide:
 *   https://tiny.cc/tinygsm-readme
 *
 **************************************************************/

// Select your modem:
//#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM808
 #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_UBLOX
// #define TINY_GSM_MODEM_BG96
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266

// Increase RX buffer if needed
//#define TINY_GSM_RX_BUFFER 512

#include <TinyGsmClient.h>
#include <ArduinoHttpClient.h>
#include <SoftwareSerial.h>
#include <String.h>
#include "DHT.h"
int sensorPin = 0;    // set the input pin for the potentiometer
int sensorValue = 0;
#define DHTPIN A0
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

//SoftwareSerial gprsSerial(7,8);

float t; // temperature in celcius
float h; // humidity
String headerValue = "";

int samplesPerBuffer = 60;
char separator = ',';
String buffer = "";
int currentBufferPosition = 0;
unsigned long startSamplingTime = 0;
const long sampleInterval = 50;
String gsmBuffer = "";
  int gsmSendingState = 0; // 0 not sending, 1 preparing sending, 2 sending, 3 finishing sending
//  int gsmSendInterval = 1000;

  int gsmPreparingDelay = 200;
  int gsmSendingDelay = 1500;
  int gsmFinishingDelay = 100;
  unsigned long startRequestTime = 0;

// Uncomment this if you want to see all AT commands
//#define DUMP_AT_COMMANDS

// Uncomment this if you want to use SSL
//#define USE_SSL

// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial

// Use Hardware Serial on Mega, Leonardo, Micro
#define SerialAT Serial1

// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
SoftwareSerial SerialAT(7, 8); // RX, TX

// Your GPRS credentials
// Leave empty, if missing user or pass
const char apn[]  = "prepaidnet";
const char user[] = "mts";
const char pass[] = "064";

// Server details
const char server[] = "ekg.velizarius.com";
const char resource[] = "/71F977B8DE73/";

#ifdef DUMP_AT_COMMANDS
  #include <StreamDebugger.h>
  StreamDebugger debugger(SerialAT, SerialMon);
  TinyGsm modem(debugger);
#else
  TinyGsm modem(SerialAT);
#endif

#ifdef USE_SSL
  TinyGsmClientSecure client(modem);
  const int  port = 443;
#else
  TinyGsmClient client(modem);
  const int  port = 80;
#endif

HttpClient http(client, server, port);

void setup() {
  // Set console baud rate
  SerialMon.begin(9600);
  delay(10);

  // Set GSM module baud rate
  SerialAT.begin(9600);
  delay(3000);

  // Restart takes quite some time
  // To skip it, call init() instead of restart()
  SerialMon.println(F("Initializing modem..."));
  modem.restart();

  String modemInfo = modem.getModemInfo();
  SerialMon.print(F("Modem: "));
  SerialMon.println(modemInfo);

  // Unlock your SIM card with a PIN
  //modem.simUnlock("1234");
}

void loop() {
  SerialMon.print(F("Waiting for network..."));
  if (!modem.waitForNetwork()) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

  SerialMon.print(F("Connecting to "));
  SerialMon.print(apn);
  if (!modem.gprsConnect(apn, user, pass)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

  SerialMon.print(F("Connecting to "));
  SerialMon.print(server);
  if (!client.connect(server, port)) {
    SerialMon.println(" fail");
    delay(10000);
    return;
  }
  SerialMon.println(" OK");

/*==================================================================================*/
  http.connectionKeepAlive();
  http.beginRequest();
  int codePost = http.post("/71F977B8DE73/");
//
//  DEBUG_MSG_LINE(F("Returned status after post = "));
//  DEBUG_MSG(codePost);
  http.post("url");
  http.sendHeader(F("Content-Type"), F("text/html"));
  http.sendHeader(F("Content-Length"), String(t).length());
  client.println();
  http.beginBody();
  http.println(String(t));
  http.endRequest();
/*===============================================================================*/

  // Make a HTTP POST request:
  client.print(String("POST ") + resource + " HTTP/1.0\r\n");
  client.print(String("Host: ") + server + "\r\n");
  client.print(String(F("\r\nHeader: ")) + headerValue);
  client.print(String(F("\r\n\r\n")));
  client.print(String(t));
  client.print("Connection: close\r\n\r\n");

  unsigned long timeout = millis();
  while (client.connected() && millis() - timeout < 10000L) {
    // Print available data
    while (client.available()) {
      char c = client.read();
      SerialMon.print(c);
      timeout = millis();
    }
  }
  SerialMon.println();

  // Shutdown

  client.stop();
  SerialMon.println(F("Server disconnected"));

  modem.gprsDisconnect();
  SerialMon.println(F("GPRS disconnected"));

  // Do nothing forevermore
//  while (true) {
//    delay(1000);
//  }
}

float getSensorData() {
   t = dht.readTemperature();
  //Read humidity
  h = dht.readHumidity();

  // Compute temperature values in Celcius
  t = dht.computeHeatIndex(t,h,false);

  // Check if any reads failed and exit early (to try again).
  if (isnan(t)) {
    Serial.println("Failed to read temp from DHT sensor!");
    return 1;
  }
  return t;
}

Can it be, that the GSM module has a limitation on how long the URL can be? Big data chunk are normally send via the body of a POST request, not via the URL of a GET request.

Yeah, putting data in the URL of a GET request is a bad idea. You should refactor your server API to use RESTFul conventions (send a POST with the data in the body in JSON)

Thanks for the answers. The URL of a  GET request can contain up to 2400 characters, something like that, so I think that shouldn't be a problem. My code with the POST didn't work, GSM commands couldn't have been executed for some reason.

Hook up the gsm serial port to your computer to see what the SoftSerial library is really sending to the GSM module. See if adding gprsSerial.flush() at end of sendData helps. See if switching to a different softwareserial library helps (for example AltSoftSerial). See if switching the hardware and software serial helps (use hardware serial, which is generally more reliable, for the GSM module).


text:
Arduino Serial Monitor Input 3DES Encryption
I am trying to 3DES encryption using Serial Read, Found this 3DES Sample code in Github,
#include <DES.h>
DES des;
void setup() {
  Serial.begin(9600);
  Serial.println("Hello!");
}
void loop() {
  desTest();
  tdesTest();
  delay(2000);
}
void desTest()
{
  byte out[8];
  byte in[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  byte key[] = { 0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e };

  Serial.println();
  Serial.println("========= DES test ==========");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.encrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.decrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
}
void tdesTest()
{
  byte out[8];
  byte in[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
  byte key[] = {
                  0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
                  0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
                  0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
                };

  Serial.println();
  Serial.println("====== Triple-DES test ======");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
}
void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

I want to get user serial input from Serial Monitor to feed byte in[]. Which will encrypt user input, I will pad user input to 8 Bytes or restrict input to 8.
Library: https://github.com/Octoate/ArduinoDES
Could any one help me to get data from user input.
Edit 1: I was able to read the String to char and feed to byte in[] changed the code,
#include <DES.h>
DES des;

String  input;

char buf[30];
void setup() {
  Serial.begin(9600);
  Serial.println("Hello!");

}

void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}
void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    char buf[30];
/*
    input.toCharArray(buf, 9);
    Serial.println(buf);
*/
    input.toCharArray(buf, input.length() + 1);
    Serial.println(buf);

    byte out[8];
    byte in[] = {buf};
    Serial.println(buf);
    byte key[] = {
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
      0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
    };

    Serial.println();
    Serial.println("====== Triple-DES test ======");

    //encrypt
    Serial.print("Encrypt...");
    unsigned long time = micros();
    des.tripleEncrypt(out, in, key);
    time = micros() - time;
    Serial.print("done. (");
    Serial.print(time);
    Serial.println(" micros)");
    printArray(out);

    //decrypt
    for (int i = 0; i < 8; i++)
    {
      in[i] = out[i];
    }
    Serial.print("Decrypt...");
    time = micros();
    des.tripleDecrypt(out, in, key);
    time = micros() - time;
    Serial.print("done. (");
    Serial.print(time);
    Serial.println(" micros)");
    printArray(out);
    delay(2000);
  }

}

But I don't think getting the correct,
Please find the below,

But when I feed manually like below,
...
input.toCharArray(buf, input.length() + 1);
    Serial.println(buf);

    //tdesTest();
    byte out[8];
    byte in[] = {"12345678"}; //Manually feeding hardcoding the value need to get the value from serial read to here
    Serial.println(buf);
    byte key[] = {
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
      0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
      0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
    };

    Serial.println();
    Serial.println("====== Triple-DES test ======");
...

I get the expected output,

https://majenko.co.uk/blog/reading-serial-arduino

Hi @Majenko, Thanks for the reply,  I can read the serial string from while (Serial.available > 0) {
a = Serial.readString(); // read the incoming data as string

} But I could not find a way to feed it to the "byte in[ ]" in tdesTest Method due to unable to feed the string.

Well, that all depends on what format your input is in and what format you need to feed into the in array.

I want to input String from Serial and convert it to Char and feed to in[ ] @Majenko

Yes, I gathered that. But what is in the string, and how does that relate to what would be put into in[]?

String is the data needs to be encrypted which will be feeds to in [ ] for encryption using DES Library.

byte in[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; will be replaced by Char in [] = {Data_from_SerialRead}

a.c_str() gives you a char * array pointer to the internal data buffer of the string. Is that what you are after?

@Majenko Thanks, Could you give me an example found this on internet but I have no idea how to use it.

From your comments I think I understand what you are after.  So, assuming you have read some string into a String object called input and you have an array in[8] to populate you can:

Clear the in[] array to a preset state
Copy the string content into in[]

As code:
memset(in, 0, 8); // Erase the contents of in[]
input.toCharArray((char *)in, 8); // Copy up to 8 bytes from the string

Comments are not for extended discussion; this conversation has been moved to chat.

#include <DES.h>
DES des;
byte in[8];
String  input;

char buf[30];
void setup() {
  Serial.begin(9600);
  Serial.println("Hello!");

}

void tdesTest() {
  byte out[8];

  byte key[] = {
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key A
    0x92, 0x2f, 0xb5, 0x10, 0xc7, 0x1f, 0x43, 0x6e, // key B
    0x3b, 0x38, 0x98, 0x37, 0x15, 0x20, 0xf7, 0x5e, // key C (in this case A)
  };

  Serial.println();
  Serial.println("====== Triple-DES test ======");

  //encrypt
  Serial.print("Encrypt...");
  unsigned long time = micros();
  des.tripleEncrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);

  //decrypt
  for (int i = 0; i < 8; i++)
  {
    in[i] = out[i];
  }
  Serial.print("Decrypt...");
  time = micros();
  des.tripleDecrypt(out, in, key);
  time = micros() - time;
  Serial.print("done. (");
  Serial.print(time);
  Serial.println(" micros)");
  printArray(out);
  delay(2000);
}

void printArray(byte output[])
{
  for (int i = 0; i < 8; i++)
  {
    if (output[i] < 0x10)
    {
      Serial.print("0");
    }
    Serial.print(output[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

void loop() {

  while (Serial.available() > 0) {

    String  input = Serial.readString(); // read the incoming data as string
    memset(in, 0, 9); // Erase the contents of in[]
    input.toCharArray((char *)in, 9); // Copy up to 8 bytes from the string
    tdesTest();

  }
}


text:
speed motor test with IR sensor and PID algorithm
I'm trying to control motor speed (RPM) using an IR sensor , All I've done is to control it without PID algorithm . and it works . can someone help me with implantation with PID . I'm using Arduino Uno , L298n motor driver , IR sensor and LCD display .
here you can see the circuit :
Circuit
and also this is the code without PID algorithm :
#include<LiquidCrystal.h>
LiquidCrystal lcd(A5,A4,A3,A2,A1,A0);
#include <Stepper.h>
const int stepsPerRevolution = 200;
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
volatile byte REV;
unsigned long int rpm,RPM;
unsigned long st=0;
unsigned long time;
int ledPin = 13;
int led = 0,RPMlen , prevRPM;
int flag = 0;
int flag1=1;
#define bladesInFan 2
float radius=1.9685;   // inch
int preSteps=0;
float stepAngle= 360.0/(float)stepsPerRevolution;
float minSpeed=0;
float maxSpeed=280.0;
float minSteps=0;
float maxSteps=maxSpeed/stepAngle;

void setup()
{
  myStepper.setSpeed(60);
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  lcd.begin(16,2);
  lcd.print("Speedometer");
  delay(2000);
  attachInterrupt(0, RPMCount, RISING);
 }

  void loop()
  {
    readRPM();
    radius=((radius * 2.54)/100.0);  // convering in meter
    int Speed= ((float)RPM * 60.0 * (2.0 * 3.14 *
        radius)/1000.0);
    // RPM in 60 minute, diameter of tyre (2pi r) r is radius,
    1000 to convert in km
    int Steps=map(Speed, minSpeed,maxSpeed,minSteps,maxSteps);

    if(flag1)
    {
       Serial.print(Speed);
       Serial.println("Kmh");
       lcd.setCursor(0,0);
       lcd.print("RPM: ");
       lcd.print(RPM);
       lcd.print("           ");
       lcd.setCursor(0,1);
       lcd.print("Speed: ");
       lcd.print(Speed);
       lcd.print(" Km/h       ");
       flag1=0;
   }
   int currSteps=Steps;
   int steps= currSteps-preSteps;
   preSteps=currSteps;
   myStepper.step(steps);
}

 int readRPM()
 {
    if(REV >= 10 or millis()>=st+1000)                  //  IT
   WILL UPDATE AFETR EVERY 10 READINGS or 1 second in idle
    {
        if(flag==0)
           flag=1;
           rpm = (60/2)*(1000/(millis() - time))*REV/bladesInFan;
           time = millis();
           REV = 0;
           int x= rpm;
           while(x!=0)
           {
              x = x/10;
              RPMlen++;
            }
            Serial.println(rpm,DEC);
            RPM=rpm;
            delay(500);
            st=millis();
            flag1=1;
           }
        }

void RPMCount()
 {
   REV++;
   if (led == LOW)
 {
   led = HIGH;
 }
  else
 {
    led = LOW;
  }
 digitalWrite(ledPin, led);
}

here is the source
thanks

What exactly is your problem with incorporating a PID controller? There is even a PID library for Arduino, which does the main work for you

@chrisl im a newbie and i dont know how to combine the PID code with the code above

@masut do you know what a pid controller is?

@SimSon yes three parameters proportional–integral–derivative  a control loop machine


text:
Serial.readString() - how does it work exactly?
Someone posted a solution for a problem I had which used Serial.read() .Why doesn't readString() seem to work though? From the docs it seems it reads the data as a String object which would make things a bit cleaner.
But here's my Python code:
import serial

arduinoSerialData = serial.Serial('com7', 9600, timeout=0)

while True:
    arduinoSerialData.write('ALIVE\r\n')

And Arduino code:
void setup() {
  Serial.begin(9600);

  pinMode(13, OUTPUT);

}

void loop() {
    if (Serial.readString() == "ALIVE") {
        digitalWrite(13, HIGH);
    } else {
        digitalWrite(13, LOW);
    }
}

If this was right, the green LED on the Arduino would light up when the Python program would run, but it doesn't. What is Serial.readString() expecting that it doesn't get?
I even tried if (Serial.readString().startsWith("ALIVE")) instead, as well as arduinoSerialData.flush() before arduinoSerialData.write()

All of your five questions so far seem to be about your issue with Python, and detecting if your USB connection is alive. They are just variations on a theme. Does reading work? Does writing work? Are there separate transmit and receive buffers? How does readString work? For example: Pyserial serial.write() doesn't work. I suggest you stick to one thread and work through your issues with the help of people who are genuinely trying to help you.

Nick, I'll suggest you "unstick" from me and get over the fact that I cross-posted before. Here's what happened: I had an issue and didn't know what was causing it, by experimenting for hours I wrongly deduced that the issue was reading and writing not working together properly, while it turns out it was me not understanding how readString() works. I have an eureka moment that the problem could be how readString() worked instead, and by asking it turned out to be the case. Answer below genuinely helped me. Monitoring my activity and bugging me continuously didn't, nor it seems ethical. Thanks.

BTW, these are separate questions (this one and the previous one). This is a Q&A site, as far as I know it's suggested to stick to one question per topic. Sticking to one thread per issue might be a good idea for forums.

I am not monitoring your activity. New questions are automatically shown to me (as to every visitor to the site). However if you prefer I do not respond to any future questions of yours I can certainly do that. It is hardly unethical to respond to further questions, and indeed the site encourages moderation by its users. Moderation being detecting cross-posts, poor quality posts, that sort of thing. However I am sure that others can achieve that if I do not.

I thought you understood what I meant... I think you noticed that I accepted one of your answers to one of the questions. Answers are welcome, criticizing me for making similar posts over and over again isn't very nice. I cross posted one of the questions, and you haven't gotten over it. Someone else even pointed out that one of my latest questions was different to another one you claimed to be the same, again.  I personally have nothing against cross posting, some people only visit Stack, some only visit the forums, but if it's against the rules, okay, I won't do it. And I'm not, anymore...

readString() will read characters from the serial (or other Stream) device until a timeout occurs.  That timeout is, by default, 1 second.  It is only appropriate to use readString() if your data is arriving in chunks with a minimum time between each chunk.
It is more appropriate to use readStringUntil() which will read characters from the serial device until either it times out, or it receives a certain character.  It is most common to use either the line feed (\n) or carriage return (\r) characters as the end of string marker.  You must, of course, ensure that your sending program sends the string terminated in the right way.
However, that all said, you really should avoid using String objects when possible, since the constant creation and destruction of temporary objects all over the place can make a real mess of your heap.
It is far better to learn to use character arrays and fill them using Serial.read().  A tutorial I wrote for that is here:

http://hacking.majenko.co.uk/reading-serial-on-the-arduino

Thank you. It's about time I also learned what the timeout is. Is there some quetion/answer about that here already? The Pyserial docs don't seem to mention that. Don't know what "heap" is either.

The timeout is a function of the arduino's reading, not the PySerial's transmitting.  The heap is an area of memory in the Arduino that is used to dynamically allocate space for variables.

Thanks. So timeout is the delay between all the Serial.read() functions in the Arduino code? Sorry, just don't want to start a topic for something small like this.

@LeoErvin The timeout is how long readString waits to receive a character on the serial port before it decides that there are no more to receive. If more than 1 second passes without it having received a character then it finishes reading and returns whatever it has managed to get up until then.  It does mean that there will be at least a 1 second delay in your program while it waits for characters to arrive.

@LeoErvin If you send one character every 900ms then it will never finish, because it never reaches 1 second while waiting for the next character.  If you send 30 characters together, then don't send anything for more than one second, then readString() will wait for 1 second after the last character has been received and then return those 30 characters as a string.

Got it, thanks. It seems if I have a newline I also don't need to flush() from Python for some reason.

@LeoErvin It is called a blocking function, because it blocks the operation of the Arduino until it is finished. You can't do anything else for the entire time it's waiting for those characters to come in.  Far from desirable.

But it seems if I set timeout to 0 (which is probably pointless here), then do readStringUntil('\n'), it works fine. Then again I'm only sending few characters.

@LeoErvin Not perfect.  If there is a slight delay between characters in your string then it will chop the string off at that point and return the first half, since it timed out, and then it will return the second half as a new string when it gets the terminator.  Better to use a non-blocking stateful system like in the link in the answer that will signal when it has got a full line for you to process, and otherwise just return and allow you to continue.l

Hm, why will it chop if there is no timeout?

@LeoErvin There is a timeout - 0ms.  It runs the read portion while the elapsed time is less than the timeout, so the elapsed time will never be less than 0ms since time doesn't run backwards, so it's an instant timeout if there is no character in the receive buffer for it. You're confusing "0ms timeout" with "infinite timeout". The two are complete opposite ends of the spectrum.

Doesn't that mean readStringUntil() should never read anything if timeout is set to 0?

@LeoErvin No, because it first attempts a read, and only if that failed does it check the timout.  Take a look in the file Stream.cpp in the Arduino core for the int Stream::timedRead() function to see how it works.

Well, I don't know C++ (only basic stuff to be able to code Arduino), but thanks for explaining. By attempting a read I suppose you mean reading one character, right?

Yep, that's right.

Okay, thanks for the answer plus the explanations in the commments :)

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


text:
make Arduino tell when the Python program stops reading from the Serial (crash, etc)
Here's the Arduino code:
void setup() {
  Serial.begin(9600);

  pinMode(7, INPUT_PULLUP);
}

void loop() {
    int val = digitalRead(7);
    if (val == HIGH) {
        Serial.print("1");
    } else {
        Serial.print("0");
    }
    Serial.println("");  // new line

}

Python code:
import time
import serial

# setup Arduino USB communication
try:
    arduinoSerialData = serial.Serial('com3', 9600)

except: # not connected/damaged
    pass

while True:
    if arduinoSerialData.inWaiting() > 0:
        datastr = arduinoSerialData.readline()
        print datastr
        time.sleep(1)

WHat I want to add is, if Python program exits, or crashes, let the Arduino know somehow. More specifically turn on a LED in pin 8.

You didn't provide the information you were asked for. What does your existing serial protocol consist of? How does your "program" operate? We need DETAIL!

And anyway, you just asked the same question, not the question you were told to ask!

possible duplicate of know the state of USB (Serial) connection (coonected or not connected)

You were told the exact terms to ask about, and the exact information that was required, neither of which you have given.  The question should have been more along the lines of "I have written a program in Python that does XXX.  It communicates with the Arduino using a protocol that consists of YYY, ZZZ, etc.  How can I implement keepalive in this situation?"

Majenko, I asked you what I needed to ask. You said to ask something I didn't understand what even meant and refused to explain so I'd know it is what I indeed need to ask. Give me a break.

I have just told you the exact words to use.  Fill in the blanks.

I'm not going to ask something without understanding what is it I'm asking. That's retarded.

What part of that question formatting do you not understand?

It's not about formatting, it's about the terminology, I asked you this already and you refused to listen.

WHAT terminology do you not understand?!

I told you already in the other thread and you replied with "Go ask the question". Take a chill pill.

I told you in that question WHAT to ask, yet you seem to have refused point blank. You also refuse point blank to tell me what it is you don't understand.  Is it the "Keepalive" you don't understand? "Protocol"? "Serial"? What? YOU suggested a concept. I gave it a name. Now you are saying you don't understand?!

I already said why I refused to ask what you wrote down for me to ask, and very clearly gave the reason why, which was that I didn't understand if that was what I needed to know. And I'm not refusing to tell what I didn't understand "point blank" now, it's just that the comment is still there, but fine, I'll repost here:  What is the difference between "connected" and "alive and working"? And then, "What does your existing serial protocol consist of?" What does that mean? "How does your "program" operate?" - what does this mean? Youre asking to post all that. I'm asking what you need exactly.

They are far from vague.  "What does your existing serial protocol consist of?" You have a serial connection. You must be sending data down it in some form.  The Keepalive will also be serial data. We NEED to know what data YOU are sending so we can determine what the best way of augmenting that with Keepalive messages would be. "How does your program operate?" What data does it consume or produce? If we need to CHANGE your protocol we NEED to know what that protocol has to support.

Some reading matter.  https://en.wikipedia.org/wiki/Communications_protocol https://en.wikipedia.org/wiki/Keepalive

"The Keepalive will also be serial data", "What data does it consume or produce?" sorry but for me specifically this is pretty vague. At this point I can post my Arduino code and Python code. I'm not as experienced as you nor can I read your mind.

I'm sorry, but I cannot be more explicit than that. If you are unable to describe what your program does then how are we going to know what it does unless it is only a handful of lines?

You have two programs. Let's call them A (Arduino) and P (Python).  WHAT does A send to P? WHAT does P send to A? WHEN does A send things to P? WHEN does P send things to A?

Okay, code it is then. Give me a minute to simplify the codes and post what each does (you already know though). I think you have the privillege to edit the title, right?

Cross posted on Arduino Forum and a second time.

There is no way to know if the connection has closed or not, you can only know if the connection was working at some point in the past.
Your communication protocol as shown is only half duplex (i.e., it's only one way - the Arduino sends to Python but never the other way around) which simplifies things somewhat.
There are a number of strategies you can employ in your case, and any number of them can be combined to create a system as robust (and complex) as you like.
First you would need to make your protocol full duplex.  This is, you need your Python program to be able to send information to the Arduino.  Since you aren't doing that at the moment the implementation of it can be in any way you like.
One method you can use is called Keepalive.  In this system the Python program will periodically send an "I am here" message to the Arduino.  The Arduino receives these messages and remembers when the last one was (hint: use the millis() function).  If a message hasn't been received for more than a pre-defined timeout period the link is assumed to be dead.
Another method which is good if you are sending data very regularly from the Arduino to the Python program is to use a system of acknowledgements.  In this situation every bit of data sent to the Python program is followed by the Python replying with an "I got that" message.  If the Arduino doesn't get that response after sending its data within a certain timeout period (can be much shorter than for a keepalive timeout) then the link is assumed to be dead.
Wrapped around both these methods you can add an "I have arrived" and an "I am leaving" message.  These are sent by the Python program when it starts and just before it's about to exit so the Arduino knows when the link should be alive and when it shouldn't.  If it gets an "I am leaving" message then it knows that it shouldn't care whether it gets any acknowledgement or keepalive messages, so it doesn't need to think about timeouts. Only after it has received an "I have arrived" message should it start caring.
So for instance your protocol, with all these things implemented, might look like this (>> = message from Arduino to Python, << is message from Python to Arduino):
>> 1
>> 1
>> 1
>> 0
>> 0
>> 1
<< A    - I have arrived
>> 1
<< Y    - Yes, I got that
>> 1
<< Y    - Yes, I got that
>> 0
<< Y    - Yes, I got that
<< K    - keepalive - we know the link is alive and working.
>> 0
<< Y    - Yes, I got that
>> 1
<< Y    - Yes, I got that
(Program crashes now.)
>> 1
*no Y received - assume connection is closed*
>> 1
... etc ...

In this instance the 0 and 1 are what you are sending at the moment.  A is an "I have Arrived" message, Y is a "Yes I got that" message, K is a "Keepalive" message, and if the program had exited cleanly an L would have been an "I am Leaving" message.
Keeping the messages simple (single characters) means it's really easy for the Arduino to parse those messages and work out what is going on.
There is a certain amount of balancing act to be performed when implementing your system between how often you are sending data and how long you are willing to wait for a valid response or message to flag the connection closed.
Expanding your existing example program to incorporate these messages might look like:
unsigned long lastKA = 0;
unsigned long lastSent = 0;
boolean isConnected = false;

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

  pinMode(7, INPUT_PULLUP);
}

void loop() {

    // Check the timeouts if we are connected
    if (isConnected) {

        // First check to see if the Keepalive timeout has passed
        if (millis() - laskKA > 5000) { // 5 second keepalive timeout)
            isConnected = false;
        }

        // If we have sent data...
        if (lastSent > 0) {
            // ... check that we got a response in time
            if (millis() - lastSent > 100) { // 100ms Y timeout
                isConnected = false;
            }
        }

    }

    // If we are connected then send some data
    if (isConnected) {

        int val = digitalRead(7);
        if (val == HIGH) {
            Serial.print("1");
        } else {
            Serial.print("0");
        }
        Serial.println("");  // new line

        // and set the timer for the response
        lastSent = millis();
    }

    // Now process incoming messages.
    if (Serial.available()) {
        int c = Serial.read();

        // If the message is an A then turn on the connection and
        // treat it as a Keepalive as well.
        if (c == 'A') { // Arrived
            isConnected = true;
            lastKA = millis();

        // If it's a Leaving message then turn off the connection.
        } else if (c == 'L') { // Leaving
            isConnected = false;

        // If it's a Keepalive then reset the timer.
        } else if (c == 'K') { // Keepalive
            lastKA = millis();

        // A Y acknowledgement will disable the sent timer.
        } else if (c == 'Y') { // Yes
            lastSent = 0; // Cancel the sent timer
        }
    }
}

This is odd, serial.Serial.write('1') in Python doesn't seem to write anything to the buffer, print serial.Serial.readline() doesnt show what it wrote. Otherwise will work.

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


text:
Is the Serial buffer going from Arduino to PC and from PC to Arduino different?
I'm both sending and receiving strings to Arduino from my Python program on the PC and the opposite. I don't check by code if one is finished before doing the other. Are they seprate buffers, or is it just pure luck my program has been running fine until now and each program has been reading the right string ?

Yes there are separate buffers for Tx and Rx.

There shall be separate buffers for Tx and Rx (in Arduino Serial library). The actual buffer size may vary, but shall be around 8-16 bytes and there is also hardware buffer in MCU. Please try to increase serial baudrate, if possible.
UPD: In HardwareSerial.h:
#if (RAMEND < 1000)
#define SERIAL_TX_BUFFER_SIZE 16
#else
#define SERIAL_TX_BUFFER_SIZE 64
#endif

....

unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];

It seems for Atmega328 the buffers are 16 bytes each
UPD: As Nick pointed, for Atmega328:
#define RAMEND       0x8FF     /* Last On-Chip SRAM Location */

So the buffers are 64 byte each.

What is Tx and Rx mean?  Also, who downvoted the answer? If it is incorrect or unrelated, please comment what the issue is.

It was probably downvoted for factual inaccuracy. The Atmega328 has 2048 bytes of RAM and therefore the buffer will be 64 bytes, not 16. Tx is shorthand for Transmit and Rx is shorthand for Receive. Why? Historical reasons probably.

Well knowing they are separate is all I needed to know. I was worried that writing to Serial then reading could result in reading (a part of) what I had written to it. That would cause some issues. However, this might not only depend on the buffer...

BTW, you don't plainly downvote for inaccurate number, you point it out as comment and/or edit the post. That was just plain rude.


text:
Why does the PIN 13 LED of Uno R3 blink every time I upload some code?
I was driving a relay from Arduino Uno R3 Pin 13. I observed that every time I upload some code the led on the board designating pin 13 would blink. I'm curious why this is so. I understand that the serial LED blinks cause there's a serial transmission but why an IO pin?

See What happens when code is uploaded using the bootloader? - the flashing is by design.

Probably the reason is to confirm that the bootloader has started.

It's driven by the bootloader, which is performing the flashing (I suppose you are flashing through the USB port).

To show that the bootloader is functioning satisfactorily to the hobbyist. Boot loader helps to upload new sketch on the chip.