text:
Read binary file on SD card
Why I can't read the last byte in the file when I use the Arduino ide code?
The code in cpp is work without any mistakes.
This is my code on Arduino ide:
  vector<unsigned char> text;
  unsigned char textseg;
  in_file.read(&textseg,1);
  while (in_file.available()){
      text.push_back(textseg);
      in_file.read(&textseg,1);
  }

And this is cpp code:
vector<unsigned char> text;
unsigned char textseg;
in_file.read(reinterpret_cast<char*>(&textseg), 1);
while (!in_file.eof())
{   text.push_back(textseg);
    in_file.read(reinterpret_cast<char*>(&textseg), 1);
}

I would guess, the difference is caused by a differrent declaration of in_file. But, as you do not show us the declaration, it is just a guess. It is also caused by the fact, that you read the last line but do not write it the the text vector because the wihle loop ist not enter, when the last character is read. I have no explanation, why this does not happen in the second case. Perhaps because the eof is only triggered when the read method reads from an empty stream and available knows that the stream is empty without reading from it again.

because you read it but you don't write it. you have a read before the while loop but no write after the while loop. available() returns the count of bytes available to read  eof() is true when you try to read more than the length of the file

Are you aware that feof() returns true only after you tried to read past the end of the file?

Your loop seems to be out-by-one. I would prefer:
  vector<unsigned char> text;
  unsigned char textseg;
  while (in_file.available()){
      in_file.read(&textseg,1);
      text.push_back(textseg);
  }

Why read a byte, as you did, before you know if it is available?
In the Standard C++ library, eof() is true if a read fails, however in the Arduino available() means a byte is available to be read. They are not directly swappable.


text:
Send Email through Cayenne serial connection
I have an Arduino Uno connected to Cayenne through the serial connection, currently i am reading the data from a sensor of temperature and humidity DHT12 and showing it in the Dashboard of Cayenne correctly.
I need to know if i can send emails from the Arduino using the connection that cayenne let me use, because i can't stay with the pre-defined alerts that the platform have.

I suspect you would be better off seeing if you can configure Cayenne to send the emails for you.  Imagine what a pain it would be getting the Arduino to generate the string that contains the email and the headers.

Yes, I can send emails with Cayenne, but I want to personalize the emails.

No, the Arduino cannot send emails directly through serial. The communication channel you have set up is a direct connection between the Arduino and Cayenne. It cannot be used for anything else other than communicating with Cayenne.
However that doesn't mean you can't try and see if there is some way of making Cayenne send emails for you. Having never used Cayenne I cannot comment on this aspect. You would be better off consulting directly with Cayenne and their users through their forums.

source: Stack Exchange

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

sort: votes


text:
SD card fails to write when used with another SPI device
I have an ADXL355 accelerometer attached to an Adafruit Feather Adalogger.  I can configure and read the sensor.  I can also write binary values to the SD card.  The problem occurs when I try to read from the sensor and then write that data to the SD card.  The only thing I can think of is I'm somehow messing up the SPI communication but I can't see where.  I looked through pins_arduino.h for my board and the SD Card (pin 4) is on a different register than pin 10 so I don't see how I'm breaking things.
My operations proceed like this.  Global sensor creation, Serial.begin, SD.begin, SPI.begin, Test sensor connection, Create file for output on SD card, Initialize sensor, Read sensor FIFO, Write to file, repeat last 2 forever.
The file is created but remains at 0 file size, ie nothing is actually written to the card.
The sensor can operate at 4 kHz which was hard to achieve using the digitalWrite functions so I switched to using the port registers on the Feather.  I do it like this:
#include <SM_ADXL355_SPI_fast.h>
#include <SPI.h>
#include <SD.h>

#define cardSelect 4

ADXL355_SPIF adxl355(&DDRB, &PORTB, _BV(6)); // values taken from pins_arduino.h, tested and working on pin 10
void setup() {
  Serial.begin(57600);
  while(!Serial){
    // wait for Serial
  }
  SD.begin(cardSelect);
  SPI.begin();
  while(!adxl355.TestConnection()){
    delay(1000);
  }
  adxl355.OpenFile("TestSPI.bin");
  adxl355.Initialize(1, 10, 0); // set range to 2g's, frequency to 4 Hz and filter to off
}

void loop() {
  while(true){ // avoid Arduino overhead of their loop function
    adxl355.ReadFIFO();
    adxl355.WriteFIFOToFile();
  }
}

Here is the ADXL constructor
ADXL355_SPIF::ADXL355_SPIF(volatile uint8_t * outReg, volatile uint8_t * outPort, uint8_t bitValue) : sensorOutReg(outReg), sensorPort(outPort), sensorBitValue(bitValue){
    *sensorOutReg |= sensorBitValue;
    *sensorPort |= sensorBitValue;
    sensorWriteCount = 0;
}

TestConnection tests that the DeviceID reads 0xAD.  Initialize sets the G range, sample rate in Hz and filter.  I have tested these with serial output and they work properly.
OpenFile looks like this:
bool ADXL355_SPIF::OpenFile(const String& fileName){
    sensorFile = SD.open(fileName, FILE_WRITE);
    if (!sensorFile){
        Serial.print("Could not create file: ");
        Serial.println(fileName);
        return false;
    }
    return true;
}

After running this a file does get created on the SD card called "TESTSPI.BIN" with 0 file size.
ReadFIFO reads the numbers of entries in FIFO, stored as fifoCount and then populates a buffer (sensorFIFO[32][3]) with the values from the FIFO.  I've printed this buffer to Serial to show that it's working.  Here is that function
void ADXL355_SPIF::ReadFIFO(){
    ReadRegister(ADXL355_RA_FIFO_ENTRIES, 1);
    fifoCount = buffer[0];
    ReadFIFOInternal();
    return;
}

void ADXL355_SPIF::ReadFIFOInternal(){
    SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
    *sensorPort &= ~sensorBitValue;
    uint8_t spiCommand = ADXL355_RA_FIFO_DATA << 1 | ADXL355_READ;
    SPI.transfer(spiCommand);
    int i = 0;
    unsigned long tempV;
    unsigned long value;
    while(i < fifoCount){
        for (int ptr = 0; ptr < 3; ++ptr){
            buffer[0] = SPI.transfer(0x0);
            value = buffer[0];
            value <<= 12;
            tempV = SPI.transfer(0x0);
            tempV <<= 4;
            value |= tempV;
            tempV = SPI.transfer(0x0);
            tempV >>=4;
            value |= tempV;
            if (buffer[0] & 0x80) {
                value |= 0xFFF00000;
            }
            long lValue = static_cast<long>(value);
            sensorFIFO[i][ptr] = scaleFactor * lValue;
        }
        i += 3;
    }
    SPI.endTransaction();
    *sensorPort |= sensorBitValue;
    return;
}

Here is WriteFIFOToFile:
void ADXL355_SPIF::WriteFIFOToFile(){
    if (fifoCount > 0){
        sensorFile.write(reinterpret_cast<const char *>(&sensorFIFO), 4 * fifoCount);
    }
    sensorWriteCount += fifoCount;
    if (sensorWriteCount >= 100){
        sensorFile.flush();
        sensorWriteCount = 0;
    }
}

After allowing this to run for a while the file size is always 0.  I tried a simple binary write function just to test the card.  It looks like this and it worked.
#include <SD.h>

#define cardSelectPin 4

const float pi=3.14159;

File oFile;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while(!Serial){
    // wait for serial
  }
  SD.begin(cardSelectPin);
  oFile = SD.open("Test.bin", FILE_WRITE);
  Serial.println(sizeof(int));
  Serial.println(sizeof(float));
  float testFloat[32][3];
  for (int i = 0; i < 32; ++i){
    for (int j = 0; j < 3; ++j){
      testFloat[i][j] = pi * (i + 1) + j;
    }
  }
  oFile.write(reinterpret_cast<const char *>(&testFloat), sizeof(float) * 96);
  oFile.close();
  Serial.println("Finished writing file.");
}

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

}

SD cards are reportedly not fully compatible with shared SPI busses - though I'd been under the impression that it was usually the other devices impacted, since well-behaved SPI peripherals shouldn't be getting in the way of access to the card.

This is a Feather board?  Make sure your supporting software is up to date.  I had plenty of problems with a Feather board as they were new at the time.

@st2000 I use the Arduino IDE and I update everything it says it out of date when it opens.  Are you referencing another "supporting software"?  Yes it's the Feather 32u4 Adalogger.

Go to the Adafruit web site for information as to what is necessary to add to your Arduino IDE in order to program Adafruit Feather boards.  Remember, different Arduinos do not necessarily use the same processors.  The ARM core processors used on a Feather are likely orders of magnitudes more complex than that of the lowly Arduino Uno.

The problem here was caused by flush never being called within WriteFIFOToFile.  The variable sensorWriteCount was defined incorrectly.  Changing to call flush directly after each write statement fixed the problem.  This lead to the debugging of the if statement and variable.

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


text:
When is SPI.beginTransaction required?
I have been gradually converting many devices from i2c to spi for various reasons.  I noticed in tutorials like this from arduino.cc that SPI.beginTransaction is explicitly called out.  Then they link to examples such as this and this where they don't use SPI.beginTransaction.  In working through my own devices I found that I could often (almost always) forgo the use of SPI.beginTransaction.  The only case where I found problems was when I had 2 devices that used different SPI settings.
I went to Google and other searches for a simple reason for SPI.beginTransactions and found discussions of interrupts and locks and settings.  There was much discussions about users applications wrapping all calls with SPI.beginTransaction and SPI.endTransaction.  There were bugs when libraries didn't wrap everywhere.
This leads me to the conclusion that making calls to SPI.beginTransaction are only needed when the SPI settings need to change, but in practice you should always do it.  Is there documentation or examples that definitely state the purpose and proper (best practice) usage of it?

Although this question has an accepted answer, I'd like to provide some background and historical reasons to OP's question.
Transactional SPI using SPI.beginTransaction() was introduced in 2014, it was not available in the early version of the Arduinos or example codes published before that. As the results, there are still many codes out there on the Internet show the old way of setting up the SPI configuration, and this include the exampes provided by Arduino.cc on its library reference page even up to today, the authors of the library did not make any changes in those examples to show the usage of new API.
What the SPI.beginTransaction() does is to allow you to set unique SPI settings(through SPISettings object) for your application, even if other devices use different settings. SPI.beginTransaction() behave like a locking mechanism to gain the exclusive use of the SPI bus, and therefore requires SPI.endTransaction() to release the bus for others to access it. SPI.beginTransaction() provides better cross-device compatibility and solve software conflicts and allowing multiple SPI devices to properly share the SPI bus. You should therefore use the SPI.beginTransaction() in your SPI sketch. You should also using SPISettings object to configure your SPI communication interface, and not use the deprecated methods such as SPI.setBitOrder(), SPI.setClockDivider() and SPI.setDataMode() for setting up the SPI configuration.
Although rarely need today, there is a pre-defined macro SPI_HAS_TRANSACTION in SPI library for checking whether the firmware of the Arduino board supports SPI.beginTransaction(). It is useful for providing backward compatibility if you are writing an Arduino library.
#ifdef SPI_HAS_TRANSACTION
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
#elseif
  // use old Arduino SPI library syntax
#endif

It appears calling the method beginTransaction() prevents additional SPI transactions from interrupting the current transaction.  Calling endTransaction() allows access to the SPI hardware again. This added complexity may sound odd.  Especially in the simple Arduino sketch-writing paradigm.  But as programs grow in complexity, more SPI devices are added and interrupts are used to quickly access SPI devices - the likely hood of SPI contention increases.
In the SPIClass source code, there is this comment immediately before the beginTransaction() method:
  // Before using SPI.transfer() or asserting chip select pins,
  // this function is used to gain exclusive access to the SPI bus
  // and configure the correct settings.

So, it may be, that if the sketch-code is particularly well behaved and does not need protection from accidentally using the SPI hardware from multiple concurrent transactions, that these two methods need not be used.  But why take the chance.

Every modern Arduino library for a SPI device should use SPI library with beginTransaction to be able to coexists with libraries for SPI devices using different modes and speed.
Recently we had here a question about two libraries for SPI not working together. The devices required different modes. The libraries didn't use beginTransaction, they only used SPI.begin() in initialization. It is not possible to use these libraries together.
The STM32 core supports switching CS pin with enhanced beginTransaction and endTransaction but this is not so useful as it looks. Many devices use CS as 'commit' and the CS must be switched several times inside one 'transaction'.
If you write a library you don't know with what other SPI devices on bus it will be used so call beginTransaction as the library gets control and endTransaction as the public library function returns control out of the library.

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


text:
How to determine which pins_arduino.h file is used?
For some applications I need access to the registers that control the output/input and high/low state of pins.  For example pin 10 on a adalogger is PORTB with a mask of _BV(6).  This information can be found in pins_arduino.h.  For some boards many variants get installed.  I turned on verbose compiling and looked through the output there as well as looking through boards.txt and platform.txt.  In that output I see an include to a directory with a pins_arduino.h file but there is nothing in that file but a definition for BUILTIN_LED.
When I run a function like digitalWrite(13,HIGH); how does it know which registers to use for pin 13?  Since my board has this pin, and digitalWrite(13, HIGH); makes an LED light up ... it's working.

In the boards.txt file for the core in question you have a line for each board:
xxxx.build.variant=yyyy

where yyyy is the name of the folder in variants for the board.
For instance, the Uno, has:
uno.build.variant=standard

which relates to:
variants/standard

with the pins_arduino.h file in it for that board.

Thanks, I found that line and it agrees with the output from the compiler.  The problem is that particular file is basically empty.  Does that mean there is a default somewhere that it's using as well?

It's far from empty on my installation. What version are you running? And what board / core is it?

I have hundreds of pins_arduino.h files throughout the system.  My problem is with the adafruit huzzah ESP8266.  The pins_arduino.h file is basically empty.

Well, that is down to the core. The core most likely has defaults that don't need overriding. Most ESP8266 boards just map the GPIOs 1:1 and don't need anything else. Remember: an ESP8266 is not an AVR Arduino and does not follow the same rules.


text:
Storing random and different values of millis() while inside a loop?
Is it possible to store a value of time while you're inside a loop? Entertain the condition:
if (condition && value > 0)
{
timeTrans = millis() + 2000;
timeTrans - millis() = value;
}

basically i want it to begin counting down from 2 to 0 no matter what time it is at, but the problem is if it's inside the loop tineTrans will update as millis counts up, and value will always be 2000 and will never count down to 0. And the condition stated in the if function cannot be called in void setup(), so there's no hope in that direction. I'd post my code but it's a little long, if it will help find a solution i will post it and point around to what i'm working on.
Also, the condition is met randomly. I do not know when, or at what time/millis() it will be met at.
I also tried using for loops as well but it counts wayyyy too fast for it to be viable, and obviously i cant delay it while its inside a void loop(). Is there any other way i can go about with this?
I've been looking at the beginners guides and here's where i'm at right now, this is about as clear and concise as this question is going to get
is there any way to make "time-2000" a constant variable in this example?
unsigned long time, timeNow, timePast, timeStart, value;
unsigned long period;

void setup() {
  Serial.begin(9600);
  timeStart = 0;

}

void loop() {
  time = millis();
  if (time > 3000) //Using time bigger than 3 sec as a condition substitute to trigger my event
  period = time-2000; //Since in my example, we'll know at what time the condition was triggered (once it's triggered), I set the "period" to that.
    if ((time - timeStart) > period) //aaaaannndd the attempt
      timePast = period;

  Serial.print("Time: "); //debugging
  Serial.print(time);
  Serial.print(" please work ");
  Serial.println(timePast);

that "time-2000" just needs to be turned into a constant somehow. After that, i'll be golden. Anybody know a way around this?

“this is about as clear and concise as this question is going to get” Then it's hopeless. You must make the question clearer if you want to have any chance of getting a good answer. Start by telling us what you are trying to accomplish.


text:
Rectangular Input signal on digital pins
I have a silly question.
Today I saw a function for arduino, that is pulseIn(). So to test what it does I applied a rectangular wave at a pin same as the arduino reference page did and it worked fine. There was a line in the reference page which stated :-
Works on pulses from 10 microseconds to 3 minutes in length.
So as it seems it will work upto 100KHz signal. Is there any way to read signals of much higher frequency than this? like in the range of MHz or so?

It depends how you define "read"...  Google "Arduino Frequency Counting".

Reading high frequency signals can be done. It's possible to read signals up to about 6MHz or maybe even higher (depending on the system clock frequency).
That is, as long as all you want to know is the fundamental frequency of the signal.
Pin 5 of the Arduino Uno (PD5) is connected to Timer 1 and can be set to be the clock source for that timer.  By connecting that to your signal and allowing the timer to count up from zero using that signal as the clock source, and then waiting for a pre-defined time period, you can easily find how many clock pulses have arrived from your signal in that time. From that, you can calculate the frequency of the signal.

The Timer/Counter can be clocked by an internal or an external clock source. The clock source is
  selected by the Clock Select logic which is controlled by the Clock Select bits in the Timer/Counter control
  Register B (TCCR1B.CS[2:0]).

Since all you are working with us the number of pulses over a given period you lose any information such as the duty cycle of the signal.
You should read the datasheet section 20: "TC1 - 16-bit Timer/Counter1 with PWM" for more detail about how you can use the timer to count the frequency of a signal.

TC1 is a synchronous timer. Its T1 input is synchronized to the system clock before going to the edge detector. This means that each signal level must last more than one clock cycle in order to be reliably sampled, which puts an upper bound on the input frequency at F_CPU/2, assuming a 50% duty cycle.

@EdgarBonet indeed. Recommended is system clock / 2.5, so 6.4MHz on a 16MHz board.

It depends on the processor. Lets assume Uno/Atmega328p at 16MHz. You might get an order of magnitude faster by writing a pulsein() function in assembler. Finding out sounds like a fun project!
To go much beyond that, you'll probably need hardware support.

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


text:
Digital selection for gain control not working instead showing 0
I am making a device which will have a button to measure the input and another button to reset and the inputs are variable analog values(0 to 5v) and output is a ratio of two analog input voltages. It also has a selection keys(two buttons) for four selections(like gain eg. if key1 == LOW key 2 == LOW then J = 1 and likewise)
but the problem is when i am multiplying j with it the output shows zero if I multiply numbers like 1,2,3etc without using j then the ratio value gets multiplied.
here is the code
    void setup() // put your setup code here, to run once:
    {
      Serial.begin(9600);
      pinMode( K1, INPUT );
      pinMode( K2, INPUT );
      pinMode( MeasureButton, INPUT );
      pinMode( ResetButton, INPUT );
      dsp.begin(20, 4);
      current = millis();
    }

    void loop()
    {

      while(current < wait)
      {
      Serial.println("INITIALIZING");
      delay(1000);
      current = millis();
      }
      Serial.println("                   ");
      delay(1000);
      Serial.println(" READY TO MEASURE ");
      delay(2000);
      while (digitalRead(MeasureButton) == LOW)
      {
        if(K1 == LOW && K2 == LOW)
        {J = 1; // SOMETHING VALUE
        showMessage1();
        i = 0;
        delay(1000);
        }if(K1 == LOW && K2 == HIGH)
        J= 2; // SOMETHING VALUE
        showMessage1();
        i = 0;
        delay(1000);
        if(K1 == HIGH && K2 == LOW )
        J= 3; // SOMETHING VALUE
        showMessage1();
        i = 0;
        delay(1000);
        if(K1 == HIGH && K2 == HIGH )
        J= 4; // SOMETHING VALUE
        showMessage1();
        i = 0;
        delay(1000);

      }
      while (digitalRead(ResetButton) == HIGH)
      {
      dsp.setCursor(1,0);
      dsp.print("                   ");
      Serial.println("                   ");
      delay(1000);
      dsp.setCursor(1,0);
      dsp.print("RESETED");
      Serial.println("RESETED");
      delay(1000);
      }
while (digitalRead(ResetButton) == LOW)
      {
      dsp.setCursor(1,0);
      dsp.print("                   ");
      Serial.println("                   ");
      delay(1000);
      dsp.setCursor(1,0);
      dsp.print("PRESS MEASURE");
      Serial.println("PRESS MEASURE");
      delay(1000);
      }
    }

    void showMessage1()
    {
       while(i<5)
        {
        A = analogRead(A0);
        B = analogRead(A1);
        C = analogRead(A2);
        D = analogRead(A3);
        N = analogRead(A4);
        W1 = (A/N)*J;        // J is another variable whose value is dependent on K selection values
        W2 = (B/N)*J;        // J is another variable whose value is dependent on K selection values
        W3 = (C/N)*J;        // J is another variable whose value is dependent on K selection values
        W4 = (D/A)*J;        // J is another variable whose value is dependent on K selection values

        sumW1 = sumW1 + W1;
        sumW2 = sumW2 + W2;
        sumW3 = sumW3 + W3;
        sumW4 = sumW4 + W4;
        i++;
      }
        Serial.print("W1-");
        Serial.print(sumW1);
        Serial.print("W2-");
        Serial.println(sumW2);
        Serial.print("W3-");
        Serial.print(sumW2);
        Serial.print("W4-");
        Serial.println(sumW4);
        sumW1 = 0;
        sumW2 = 0;
        sumW3 = 0;
        sumW4 = 0;
    }

  pinMode( K1, INPUT );

with
    if(K1 == LOW && K2 == LOW)

makes no sense. K1 is a pin number. LOW is a macro for 0 (HIGH for 1). You are comparing a static pin number against a static number.
If K1 is not equal to 0, the inner part of that if statement can never be reached.
What you meant to do was "if the voltage at the pin K1 is low". For that you need to read out the current value of the pin and check it.
For that you must replace your if(K1 == LOW) type statements to if( digitalRead(K1) == LOW).
I'd also like to mention that you must have a pull-up on your buttons for this "LOW"/"HIGH" logic to work. Either externally, or use INPUT_PULLUP instead of INPUT in pinMode.

you just saved me. :) I will correct that


text:
External ADC reference when using MATLAB support package for Arduino
I am using the MATLAB support package for Arduino.
However, I need to configure the ADC reference to external. MATLAB documentation doesn't really explain how to do this?
Is there any way I can use the MATLAB support package and configure the Analog pins to use external ADC reference?

MATLAB documentation doesn't really explain how to do this?

it makes sense. read your arduino documentation instead.

Is there any way I can use the MATLAB support package and configure the Analog pins to use external ADC reference?

absolutely.

Any more details on how to do this will be much appreciated. I am programming using only MATLAB and not writing a single line of C code using Arduino IDE. There is no mention of any wrapper function in the MATLAB documentation of its Arduino support package that lets the user configure the ADC reference to external.


text:
Lowest voltage applicable on AREF pin on Uno and Mega
I need to measure an Analog signal in the range of 5-30 mV.
Naturally, using the internal default 5V reference leads to very poor measurement resolution. I would like to use the capability to use an external reference voltage of 50mV on the AREF pin (using an Agilent precision power supply)
However, when I tried this in the lab, I noticed something strange. The ADC readout on the channel remained stuck at 1023. If I used anything above 0.5V on the AREF pin, the readout on the ADC is correct, and the counts reliably go up and down when I ramp up and down the Analog input accordingly.
Any idea how to resolve my issue?

Please tell us what your project is and where that signal comes from. Perhaps you need an opamp or external adc. The ads1115 has a gain (only x16), that might be enough.

According to the datasheet (page 375) the minimum voltage you are allowed to have as a reference voltage for the ADC is 1V.

In the Arduino Mega it's possible to use differential mode between two analog pins with 10x gain (or 200x). But, the resolution is halved (-512 ... 511) as it's possible to measure negative difference. But with some precision voltage reference switching and 200x gain you might be able to archieve some precision.
The downside is those ADC channels are not supported by analogRead, you have to do it directly by setting ADMUX register (or ADMUX and ADCSRB) to desired differential channel with gain.
byte backup = ADMUX; // store the arduino settings
ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX0); // internal 1.1V reference, differential: ADC1+ ADC0-, gain: 10x

// there should be some delay to stabilize the voltage reference (if another one was selected)
// but it's possible to preset it by  analogReference(INTERNAL1V1); in the setup() so no delay will be needed

ADCSRA |= _BV(ADSC);  // start conversion

while ((ADCSRA & _BV(ADSC)) != 0);  // wait for conversion end (ADSC is cleared after the end by hardware)

int val = ADC; // read the result
ADMUX = backup; // restore original settings (from arduino)

In the Arduino everything else in ADC is configured and ADC is started, so just necessary changes are here. It should be working but I didn't tested it (I don't have the Arduino Mega here)

I am interested in differential measurements. Can you provide an example code?


text:
Secure HTTPS request fails 90% of the time
I'm using a NodeMCU, which is connected to an enterprise network at a school. The information given in the GET requests that the ESP8266 sends is sensitive, so naturally we want to make it secure and encrypted - enter SSL. We do the request like so;
HTTPClient http.begin(url, thumbprint)
However, on the network at the school, doing this request fails 90% of the time, so I did a few tests - 100 requests to the exact same IP and certificate, noting how many went through;

School network

HTTPS requests: 10/100 successful [10%]
HTTP requests: 100/100 successful [100%]

Private home network

HTTPS requests: 100/100 successful [100%]
HTTP requests: 100/100 successful [100%]

We have also tried using the WiFiClient class, and while 100% of the requests went through, each one took 15 seconds which is too long.
My question is; what would the problem be, and what can we do to fix it? Can I do something in the code, or on the network?

Do you get any error messages?

@Gerben No stack errors, the response contains nothing and the HTTP code is -11

Your school probably uses a proxy which tries to filter out phishing sites or something. It's possible that it only works fast for white-listed domains.

I asked about this, and they told me there was nothing blocking my site. Again, it works 10% of the time. They said there was no firewall...

Have you tried increasing the timeout (HTTPClient.setTimeout) until you get 100% success?

@Craig didn't think of this! The requests actually go through 100% of the time now (at a 100000 timeout, just for now), so that's great! Although each request takes about 4.5 seconds compared to the 300ms that the unsecure requests take. But I'll take it! Post it as an answer, and I'll accept it.

As to why there is a difference between the 2 networks I'm not sure. I would turn up the log level on your server and see if that points you toward the problem.

you should consider an ESP32 if you need to make fast HTTPS requests from an MCU

Increase the timeout for your request with HTTPClient.setTimeout(). Note the timeout is in milliseconds.
HTTPClient http;
http.setTimeout(15000); // 15 Seconds
http.begin(url, thumbprint);


text:
What can be the reason for a Stack canary watchpoint triggered (loopTask) on a https get() command?
I have a program that only do get and post to a controller via an ethernet port. My problem is that after a certain amount of loop in the program, i got this error:
Guru Meditation Error: Core  1 panic'ed (Unhandled debug exception).
Debug exception reason: Stack canary watchpoint triggered (loopTask)
Core  1 register dump:
PC      : 0x4012d2c8  PS      : 0x00060b36  A0      : 0x8012e241  A1      : 0x3ffc9cb0
A2      : 0x3ffca070  A3      : 0x3ffca1ec  A4      : 0x3ffc9d70  A5      : 0x3ffca4bc
A6      : 0x00000000  A7      : 0x00000018  A8      : 0x80130298  A9      : 0x3ffc9fd0
A10     : 0x00000000  A11     : 0x00000000  A12     : 0x00000030  A13     : 0x3ffba06c
A14     : 0x3ffc49ac  A15     : 0x00000008  SAR     : 0x0000001c  EXCCAUSE: 0x00000001
EXCVADDR: 0x00000000  LBEG    : 0x40089a78  LEND    : 0x40089a83  LCOUNT  : 0x00000000

Backtrace: 0x4012d2c5:0x3ffc9cb0 0x4012e23e:0x3ffca010 0x4012e2b3:0x3ffca030 0x4012e2ed:0x3ffca050 0x4012a3d4:0x3ffca070 0x40124912:0x3ffca170 0x40124a0a:0x3ffca1e0 0x40124a56:0x3ffca290 0x40124bd9:0x3ffca310 0x401208d5:0x3ffca330 0x401209b6:0x3ffca4e0 0x40120a95:0x3ffca500 0x40120b69:0x3ffca570 0x4011e28e:0x3ffca590 0x4011f22b:0x3ffca5c0 0x40121c38:0x3ffca610 0x40122911:0x3ffca650 0x401230c7:0x3ffca840 0x401210ef:0x3ffca9a0 0x40121336:0x3ffcaa00 0x4011be1d:0x3ffcaa20 0x40119881:0x3ffcaac0 0x401198bb:0x3ffcaae0 0x400d9af1:0x3ffcab00 0x400d93c9:0x3ffcad80 0x400d943f:0x3ffcadc0 0x400d94ce:0x3ffcae00 0x4016e30d:0x3ffcae20 0x400dab06:0x3ffcae40 0x400dbddb:0x3ffcae70 0x400dbffb:0x3ffcaee0 0x400d5949:0x3ffcaf00 0x400d63e0:0x3ffcb3b0 0x400ddd91:0x3ffcbc10

And here is the Decoded stack:
0x4012d2c5: mbedtls_sha512_software_process at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/port/sha/parallel_engine/esp_sha512.c line 292
0x4012e23e: mbedtls_internal_sha512_process at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/port/sha/parallel_engine/esp_sha512.c line 252
0x4012e2b3: mbedtls_sha512_update_ret at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/port/sha/parallel_engine/esp_sha512.c line 367
0x4012e2ed: mbedtls_sha512_update_ret at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/port/sha/parallel_engine/esp_sha512.c line 342
0x4012a3d4: mbedtls_sha512_ret at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/sha512.c line 461
0x40124912: entropy_update at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/entropy.c line 184
0x40124a0a: entropy_gather_internal at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/entropy.c line 289
0x40124a56: mbedtls_entropy_func at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/entropy.c line 369
0x40124bd9: mbedtls_entropy_func at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/entropy.c line 338
0x401208d5: mbedtls_ctr_drbg_reseed_internal at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ctr_drbg.c line 380
0x401209b6: mbedtls_ctr_drbg_reseed at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ctr_drbg.c line 418
0x40120a95: mbedtls_ctr_drbg_random_with_add at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ctr_drbg.c line 536
0x40120b69: mbedtls_ctr_drbg_random at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ctr_drbg.c line 603
0x4011e28e: mpi_fill_random_internal at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/bignum.c line 2501
0x4011f22b: mbedtls_mpi_random at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/bignum.c line 2594
0x40121c38: ecp_randomize_jac at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ecp.c line 1719
0x40122911: ecp_mul_comb at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ecp.c line 2084
0x401230c7: mbedtls_ecp_mul_restartable at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ecp.c line 2761
0x401210ef: mbedtls_ecdh_compute_shared at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ecdh.c line 127
0x40121336: mbedtls_ecdh_calc_secret at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ecdh.c line 685
0x4011be1d: mbedtls_ssl_handshake_client_step at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ssl_cli.c line 3753
0x40119881: mbedtls_ssl_handshake_step at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ssl_tls.c line 5770
0x401198bb: mbedtls_ssl_handshake at /Users/ficeto/Desktop/ESP32/ESP32S2/esp-idf-public/components/mbedtls/mbedtls/library/ssl_tls.c line 5808
0x400d9af1: start_ssl_client(sslclient_context*, IPAddress const&, unsigned int, char const*, int, char const*, bool, char const*, char const*, char const*, char const*, bool, char const**) at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/WiFiClientSecure/src/ssl_client.cpp line 271
0x400d93c9: WiFiClientSecure::connect(IPAddress, unsigned short, char const*, char const*, char const*, char const*) at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp line 140
0x400d943f: WiFiClientSecure::connect(char const*, unsigned short, char const*, char const*, char const*) at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/cores/esp32/Printable.h line 33
0x400d94ce: WiFiClientSecure::connect(char const*, unsigned short) at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp line 117
0x4016e30d: WiFiClientSecure::connect(char const*, unsigned short, int) at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/WiFiClientSecure/src/WiFiClientSecure.cpp line 122
0x400dab06: HTTPClient::connect() at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/cores/esp32/WString.h line 339
0x400dbddb: HTTPClient::sendRequest(char const*, unsigned char*, unsigned int) at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/HTTPClient/src/HTTPClient.cpp line 601
0x400dbffb: HTTPClient::GET() at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/HTTPClient/src/HTTPClient.cpp line 518
0x400d5949: getPumpInfo() at /Users/martin/Library/CloudStorage/Dropbox/ErabliTEK/Martin/Arduino/LILYGO_POE_TEST/LILYGO_POE_TEST.ino line 204
0x400d63e0: loop() at /Users/martin/Library/CloudStorage/Dropbox/ErabliTEK/Martin/Arduino/LILYGO_POE_TEST/LILYGO_POE_TEST.ino line 307
0x400ddd91: loopTask(void*) at /Users/martin/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/cores/esp32/main.cpp line 50

And here is the code:
#include <Arduino.h>
// #include <ETH.h>
#include <ETHClass.h>       //Is to use the modified ETHClass
#include <SPI.h>
#include <SD.h>
#include "utilities.h"          //Board PinMap

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

WiFiClientSecure client;
HTTPClient https;

String AIOHTTP_SESSION = "";
bool loggedIn = false;
unsigned long lastFetch;

//Change to IP and DNS corresponding to your network, gateway
IPAddress staticIP(192, 168, 202, 8);
IPAddress gateway(192, 168, 202, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns(192, 168, 202, 1);

static bool eth_connected = false;

#define TXD1 02
#define RXD1 14

float atmos = 28.0;
char pumpInfo[1024];
char sentPumpInfo[1024];
char trends[1024];

void WiFiEvent(WiFiEvent_t event)
{
    switch (event) {
    case ARDUINO_EVENT_ETH_START:
        Serial.println("ETH Started");
        //set eth hostname here
        ETH.setHostname("esp32-ethernet");
        break;
    case ARDUINO_EVENT_ETH_CONNECTED:
        Serial.println("ETH Connected");
        break;
    case ARDUINO_EVENT_ETH_GOT_IP:
        Serial.print("ETH MAC: ");
        Serial.print(ETH.macAddress());
        Serial.print(", IPv4: ");
        Serial.print(ETH.localIP());
        if (ETH.fullDuplex()) {
            Serial.print(", FULL_DUPLEX");
        }
        Serial.print(", ");
        Serial.print(ETH.linkSpeed());
        Serial.println("Mbps");
        eth_connected = true;
        loggedIn = false;
        break;
    case ARDUINO_EVENT_ETH_DISCONNECTED:
        Serial.println("ETH Disconnected");
        eth_connected = false;
        break;
    case ARDUINO_EVENT_ETH_STOP:
        Serial.println("ETH Stopped");
        eth_connected = false;
        break;
    default:
        break;
    }
}

void startPump(){
  https.begin(client, "https://192.168.202.10/api/pump/start");
  https.addHeader("Content-Type", "application/json");
  https.addHeader("Cookie", AIOHTTP_SESSION);
  int httpsResponseCode = https.POST("{}");
  if(httpsResponseCode == 200){
    Serial.println("Succefully started the pump!");
  }else{
    Serial.print("HTTPS Response code: ");
    Serial.println(httpsResponseCode);
    String response = https.getString();
    Serial.print(response);
    Serial.println();
  }
  https.end();
}

void stopPump(){
  https.begin(client, "https://192.168.202.10/api/pump/stop");
  https.addHeader("Content-Type", "application/json");
  https.addHeader("Cookie", AIOHTTP_SESSION);
  int httpsResponseCode = https.POST("{}");
  if(httpsResponseCode == 200){
    Serial.println("Succefully stopped the pump!");
  }else{
    Serial.print("HTTPS Response code: ");
    Serial.println(httpsResponseCode);
    String response = https.getString();
    Serial.print(response);
    Serial.println();
  }
  https.end();
}

void getPressureSetPoint(){
  https.begin(client, "https://192.168.202.10/api/pressure-setpoint");
  https.addHeader("Cookie", AIOHTTP_SESSION);
  unsigned long _start = millis();
  int httpsResponseCode = https.GET();
  if(httpsResponseCode == 200){
    Serial.print("Succefully fetched Pressure Setpoint in: ");
    Serial.print(millis() - _start);
    Serial.println(" ms");
    String response = https.getString();
    DynamicJsonDocument _doc(2048);
    DeserializationError err = deserializeJson(_doc, response);
    if(err == DeserializationError::Ok){
      DynamicJsonDocument _tmp(sizeof(pumpInfo));
      err = deserializeJson(_tmp, pumpInfo);
      _tmp["pressureSetpoint"] = serialized(String(atmos - (_doc["value"].as<float>() / 33.8639), 1));
      char buf[sizeof(pumpInfo)];
      serializeJson(_tmp, buf);
      strcpy(pumpInfo, buf);
    }
  }else{
    Serial.print("Error fetching Pressure Setpoint: ");
    Serial.print("HTTPS Response code: ");
    Serial.println(httpsResponseCode);
    String response = https.getString();
    Serial.print(response);
    Serial.println();
  }
  https.end();
}

void getPumpInfo(){
  https.begin(client, "https://192.168.202.10/api/pump-info");
  https.addHeader("Cookie", AIOHTTP_SESSION);
  unsigned long _start = millis();
  int httpsResponseCode = https.GET();
  if(httpsResponseCode == 200){
    Serial.print("Succefully fetched Pump Info in: ");
    Serial.print(millis() - _start);
    Serial.println(" ms");
    String response = https.getString();
    DynamicJsonDocument _doc(3072);
    DeserializationError err = deserializeJson(_doc, response);
    if(err == DeserializationError::Ok){
      DynamicJsonDocument _tmp(sizeof(pumpInfo));
      err = deserializeJson(_tmp, pumpInfo);
      _tmp["name"] = _doc["name"];
      _tmp["model"] = _doc["model"];
      _tmp["serial"] = _doc["serialNumber"];
      _tmp["status"] = _doc["status"];
      _tmp["runningHours"] = _doc["runningHours"];
      char buf[sizeof(pumpInfo)];
      serializeJson(_tmp, buf);
      strcpy(pumpInfo, buf);
    }else{
      Serial.print("deserializeJson() returned ");
      Serial.println(err.c_str());
    }
  }else if(httpsResponseCode == -11){
    lastFetch = lastFetch - 5000;
  }else{
    Serial.print("Error fetching Pump Info: ");
    Serial.print("HTTPS Response code: ");
    Serial.println(httpsResponseCode);
    String response = https.getString();
    Serial.print(response);
    Serial.println();
  }
  https.end();
}

void setAtmos(float value){
  atmos = value;
  https.begin(client, "https://192.168.202.10/api/atmospheric-pressure");
  https.addHeader("Content-Type", "application/json");
  https.addHeader("Cookie", AIOHTTP_SESSION);
  DynamicJsonDocument doc(200);
  doc["unitId"] = 23;
  doc["value"] = atmos;
  char payload[200];
  serializeJson(doc, payload, sizeof(payload));
  int httpsResponseCode = https.POST(payload);
  if(httpsResponseCode == 200){
    Serial.print("setAtmos setted to: ");
    Serial.print(atmos);
    Serial.println(" InHg!");
    //Setting gauge pressure!!
    doc.clear();
    doc["active"] = true;
    serializeJson(doc, payload, sizeof(payload));
    https.setURL("https://192.168.202.10/api/gauge-pressure");
    httpsResponseCode = https.POST(payload);
    if(httpsResponseCode == 200){
      Serial.println("Gauge pressure set succesfully!");
    }else{
      Serial.print("Error setting gauge pressure: ");
      Serial.print(httpsResponseCode);
      Serial.print(" with value: ");
      Serial.println(payload);
    }
  }
  https.end();
}

void setup(){
    Serial.begin(115200);
    Serial1.begin(115200, SERIAL_8N1, RXD1, TXD1);
    client.setInsecure();
    WiFi.onEvent(WiFiEvent);

#ifdef ETH_POWER_PIN
    pinMode(ETH_POWER_PIN, OUTPUT);
    digitalWrite(ETH_POWER_PIN, HIGH);
#endif

#if CONFIG_IDF_TARGET_ESP32
    if (!ETH.begin(ETH_ADDR, ETH_RESET_PIN, ETH_MDC_PIN,
                   ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE)) {
        Serial.println("ETH start Failed!");
    }
#else
    if (!ETH.beginSPI(ETH_MISO_PIN, ETH_MOSI_PIN, ETH_SCLK_PIN, ETH_CS_PIN, ETH_RST_PIN, ETH_INT_PIN)) {
        Serial.println("ETH start Failed!");
    }
#endif

    if (ETH.config(staticIP, gateway, subnet, dns, dns) == false) {
        Serial.println("Configuration failed.");
    }

}
unsigned int functionID = 0;
void loop(){
  if (eth_connected) {
    if((millis() - lastFetch) >= 500){
      switch(functionID){
        case 0:
          getPumpInfo();
          break;
        case 1:
          getPressureSetPoint();
          break;
      }
      functionID++;
      if(functionID > 1){
        functionID = 0;
      }
      lastFetch = millis();
    }
  }
  if(strcmp(pumpInfo, sentPumpInfo) != 0){
    Serial.println(pumpInfo);
    Serial1.print(pumpInfo);
    strcpy(sentPumpInfo, pumpInfo);
  }
  if(Serial1.available()){
    StaticJsonDocument<2048> doc;
    DeserializationError err = deserializeJson(doc, Serial1);
    if(err == DeserializationError::Ok){
      if(doc.containsKey("command")){
        if(doc["command"] == "startPump"){
          startPump();
        }else if(doc["command"] == "stopPump"){
          stopPump();
        }else if(doc["command"] == "setAtmos"){
          setAtmos(doc["value"]);
        }
      }
      serializeJson(doc, Serial);
      Serial.println();
    }else{
      Serial.print("deserializeJson() returned ");
      Serial.println(err.c_str());
    }
  }
}

And here is the data i try to retrieve in json:
{"name": "Shop", "location": null, "notes": null, "serialNumber": "API854338", "controllerSerial": "S5204001517", "model": "GHS350VSD+", "brand": "AtlasCopco", "productName": "HEX@", "status": "Off", "runningHours": 4, "commissioningDate": "2023-01-20T11:35:20.0Z", "datetime": "2023-08-21T15:02:18.860279+00:00", "hlpFeatures": [], "llpFeatures": [], "contactPhone": null, "contactEmail": null, "contactEntity": null, "loadCounters": {"load": 0.0, "time1to20": 6956.10009765625, "time20to40": 6353.2998046875, "time40to60": 703.5999755859375, "time60to80": 330.79998779296875, "time80to100": 2112.60009765625, "ratio1to20": 42.26987838745117, "ratio20to40": 38.60668182373047, "ratio40to60": 4.276423931121826, "ratio60to80": 2.010370969772339, "ratio80to100": 12.842491149902344}, "modelVersion": "v111", "containerVersions": [{"name": "netx90", "version": "0.1.0"}, {"name": "yocto", "version": "0.7.0"}, {"name": "llp", "version": "60793910172e1a27f5a9eb9c-710-001-5fee0bb632c7e68bda513826b3144484bffac665"}, {"name": "v111", "version": "0.12.15"}, {"name": "opcua", "version": "0.3.1"}, {"name": "centralcontroller", "version": "0.3.7"}, {"name": "value-wheel", "version": "0.3.9"}, {"name": "webui-cms-import-v111", "version": "0.2.39-15"}, {"name": "teamviewer", "version": "0.2.1"}, {"name": "iot-client", "version": "0.5.15"}, {"name": "composer", "version": "0.4.3"}, {"name": "webui-scheduler", "version": "0.2.39-15"}, {"name": "webui-front", "version": "0.2.39-15"}, {"name": "webui-api", "version": "0.2.39-15"}, {"name": "llp-interface", "version": "2579fd3d"}, {"name": "proxy-intern", "version": "0.3.2"}, {"name": "proxy", "version": "0.3.4"}, {"name": "database-postgres", "version": "0.2.0"}, {"name": "broker-extern", "version": "0.2.0"}, {"name": "updater", "version": "0.3.24-5"}, {"name": "system-manager", "version": "0.5.8-3"}, {"name": "broker", "version": "0.2.0"}, {"name": "docker-ui", "version": "0.4.0"}], "pressureSetpointPresent": true}

The GET call for this data is very long! It take about 4000ms in average!
Does anyone know what i am doing wrong ??
Thanx a lot!

Don't you have to explicitly free the storage assigned to a DynamicJsonDocument as used say in getPumpInfo(). See  https://arduinojson.org/v6/how-to/reuse-a-json-document/

I don't reuse the json document i recreate it each time! And the error happend before i create the json document!! The error happen on a GET call!

Ok, so, this is likely due to your stack not being big enough. Every time a function call is made, information needs to be pushed onto the stack. It'll be popped off when that function call returns. When you call into a library - you're calling a function. When that library function calls a function, it uses the same exact stack. Most likely, your stack is not big enough. Increase your stack size.

Also, make sure you're not making a recursive call ;)

This could also happen if you have a stray pointer and happen to modify the canary value stored in the stack. This value is periodically checked to see if it changes - IT SHOULD NEVER CHANGE - but it did. You could have your own bug that's causing this to happen, even though the stack may be the proper size. What I described above is what happens when you push something onto a full stack - it must overwrite that value, which will trigger what you're seeing.

Could this be done directly without using buf and save 1k stack space char buf[sizeof(pumpInfo)]; serializeJson(_tmp, buf); strcpy(pumpInfo, buf); ?
This also has what appears to be an unnecessary intermediate variable String response = https.getString(); Serial.print(response); possibly fragmenting heap storage. Maybe also look here because the data sizes in your program are huge: https://arduinojson.org/v6/how-to/reduce-memory-usage/. Some systems also impose a limit on the maximum URL size for HTTP GET. The stack size of the ESP32 is also limited and further reduced by heap growth.

The json object you shown has nothing related to the data you are trying to desrialize in the getPumpInfo(), so what exactly is the json object (before you are trying to deserialize it) that you received? how long is it? Also if you want others to help, trim down your code to the minimum reproducible code, and only show that code...


text:
Minimizing Digital input code
I am making a device which can multiply the analog input signal with respect to the selected gain from the digital inputs. Here I have used two digital inputs(from which I can have four selections) but I am planing to add two inputs more(then I can have 16 selections). I made the code with if else statements is there any shorter way to do that? or else the code is getting huge.
here is the code:
#define sensor A0
#define resetPin 3
#define measurePin 2
#define k1 3
#define k2 4

float A = 0;
float J = 0;
int resetstatus = 0;
int measurestatus = 0;

void setup() {
  Serial.begin(9600);
  pinMode(sensor,INPUT);
  pinMode(resetPin,INPUT_PULLUP);
  pinMode(measurePin,INPUT_PULLUP);
  pinMode(k1,INPUT_PULLUP);
  pinMode(k2,INPUT_PULLUP);
  Serial.println("INITIALAIZING");
  delay(3000);
  Serial.println("Ready to begin");
  delay(200);
  }

void loop()
{
  resetstatus = digitalRead(resetPin);
  measurestatus = digitalRead(measurePin);
  if(resetstatus == LOW)
  {
    reset();
    delay(200);
  }
  if(measurestatus == LOW)
  {
    if(digitalRead(k1 == LOW) && digitalRead(k2 == LOW))
    {
    J = 1.0;
    measure();
    delay(50);
    }
    else if(digitalRead(k1 == LOW) && digitalRead(k2 == HIGH))
    {
    J = 2.0;
    measure();
    delay(50);
    }
    else if(digitalRead(k1 == HIGH) && digitalRead(k2 == LOW))
    {
    J = 3.0;
    measure();
    delay(50);
    }
    if(digitalRead(k1 == HIGH) && digitalRead(k2 == HIGH))
    {
    J = 4.0;
    measure();
    delay(50);
    }
  }
}
void measure()
{
  A = analogRead(sensor);
  float sumA = A * J;
  Serial.println(sumA);
}
void reset()
{
  Serial.println("reset");
}

I am having a problem with the output from this code
(I am using a potentiometer to feed the arduino an analog value)

I dont know why the output is showing 993 and 3972 at each cycle. can someone explain?

I made the code with if else statements is there any shorter way to do that?

j = 1 + (digitalRead(k1) | (digitalRead(k2) << 1) | (digitalRead(k3) << 2) | (digitalRead(k3) << 3));

or
j = 1 + digitalRead(k1) + 2*digitalRead(k2) + 4*digitalRead(k3) + 8*digitalRead(k4)

dont know why the output is showing 993 and 3972 at each cycle. can someone explain?

the printed values are off because of the error addressed in Nick's answer

If k1 = 0, k2 = 1 the original code selects 2.0, but your code computes 3.0. If k1 and k2 were switched it would be right. However, for more general values a lookup table or array for the J values should be used.

@MaximilianGerhardt, it is no importand which kx is which button. it would be strange if I switch k1 and k2 in the formula

This is wrong:
if(digitalRead(k1 == LOW)

You mean:
if(digitalRead(k1) == LOW

Ditto for a lot of other places in your code.

I made the code with if else statements is there any shorter way to do that?
  or else the code is getting huge.

Yes, there is a way of simplification. As @Juraj already noted, it can in this special case even be expressed as a binary representation:
if(digitalRead(k1) == LOW && digitalRead(k2) == LOW)
{
J = 1.0;
measure();
delay(50);
}
else if(digitalRead(k1) == LOW && digitalRead(k2) == HIGH)
{
J = 2.0;
measure();
delay(50);
}
else if(digitalRead(k1) == HIGH && digitalRead(k2) == LOW)
{
J = 3.0;
measure();
delay(50);
}
if(digitalRead(k1) == HIGH && digitalRead(k2) == HIGH)
{
J = 4.0;
measure();
delay(50);
}

What you are doing here is the following pattern:

read the state of the buttons
depending on which combinations of buttons is pressed, assign a different value to J

We can generalize this concept of "get the J value for a certain button combination" by doing the following:

aggregate the entire "button states" into a single, unique number
search for the associated J value

If we name the input button states "k1" and "k2", we see that you have the following logic:
| k1 | k2 | J   |
| 0  | 0  | 1.0 |
| 0  | 1  | 2.0 |
| 1  | 0  | 3.0 |
| 1  | 1  | 4.0 |

We simply concatenate the button inputs to a signle bitstring "k1|k2" and we see
| (k1,k2) | J   |
| 00      | 1.0 |
| 01      | 2.0 |
| 10      | 3.0 |
| 11      | 4.0 |

If we re-write the binary indices to decimal numbers:
| (k1,k2) | J   |
| 0       | 1.0 |
| 1       | 2.0 |
| 2       | 3.0 |
| 3       | 4.0 |

So we see that we can use this (k1,k2) number as an index from 0 to 3 to get us a J value as such:
//Aggregate all button inputs to single number
//using bitshifts
int index = (digitalRead(k2) << 1) | digitalRead(k1);

//All used J values in the right order
const float J_values[] = {
        1.0f, 2.0f, 3.0f, 4.0f
};

//get the right J value
J = J_values[index];

//measure and delay
measure();
delay(50);

This replaces all your 4 if-else statements and does exactly the same.
Now if you were to add more inputs, you can simply expand the way you construct the index number and your J_values array. Write down the "function table" for your wanted J values as above, construct the bit strings, order the indices in ascending order and write down the array values accordingly.
Referenecs:

https://www.cprogramming.com/tutorial/bitwise_operators.html
https://www.arduino.cc/reference/en/language/structure/bitwise-operators/bitshiftleft/

Put all 4 pins on one port then do a port read.
Say you used D2,3,4,5
Then
switches = (PIND && 0b00111100) >> 2;
then switches = 0 to 15 and you can do a branch on that.

yes +1, this low level solution should be mentioned here as answer too


text:
Serial.print query
is it even possible to print a variable output with 4 digits before and one digit after decimal in serial monitor?
my pot reading is shown in the above output
value   -   1.2
value   -   51.5
value   -   61.8
value   -   546.6
value   -   255.0
value   -   1235.9

to this
value   -   0001.2
value   -   0051.5
value   -   0061.8
value   -   0546.6
value   -   0255.0
value   -   1235.9

There are some implementations of printf() kicking around in some libraries.  If they are fully implemented you could use the command printf ("value   -  %04.1f\n", value); and that will give you 4 digits before the DP padded with zeros and one after the DP.

stdio sprintf and co. are build in, but without %f support. simplest is to code print of necessary count of zeros

%f specified does not work with Arduino provided functions like snprintf.

@MaximilianGerhardt, those are AVR libraries, not Arduino. http://nongnu.org/avr-libc/user-manual/modules.html

@Juraj Sorry I misread the comment. I somehow read that they are supported, not that they are not. my mistake.

While the libraries are not Arduino, the decision to link the full or miniature one not supporting floating point is an Arduino one.

You basiscally want a format string which includes %f. However on Arduino, that only returns a ? (not included to to space reasons). Refer to https://stackoverflow.com/q/27651012/5296568.
However the alternative is dtostrf (double-to-string-formatted). The function takes the double / float value, the total wanted width of the string and the decimal places you want to have.
However it fills the string with spaces to the left until the total width is met. You need an additional pass to replace it with 0.
#include <Arduino.h>

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

    const float vals[] = {
            1.2, 51.5, 61.8,
            546.6, 255.0,
            1235.9
    };

    //allocate 8 byte buffer
    //biggest string is "-9999.9\0" (with NUL)
    char buf[8];

    int numVals = (int) (sizeof(vals) / sizeof(*vals));

    for(int i=0; i < numVals; i++) {
        //format correctly
        dtostrf(vals[i], 4+1+1, 1, buf);

        //convert left-appended spaces to zeroes
        for(size_t j=0; j < sizeof(buf); j++){
            if(buf[j] == ' ')
                buf[j] = '0';
        }

        //print buffer
        Serial.println(buf);
    }
}

void loop() {
}

Prints
0001.2
0051.5
0061.8
0546.6
0255.0
1235.9

Edit: You can also offload it into a function and then feed it with the ADC values.
Example:
#include <Arduino.h>

void printValueFormatted(float value, int numDecimalPlaces, int totalWidth) {
    //format correctly
    char buf[16];
    //prevent buffer overflow
    if(totalWidth >= (int) sizeof(buf))
         return;
    dtostrf(value, totalWidth, numDecimalPlaces, buf);

    //convert left-appended spaces to zeroes
    for(size_t j=0; j < sizeof(buf); j++){
        if(buf[j] == ' ')
            buf[j] = '0';
    }

    //print buffer without newline
    Serial.print(buf);
}

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

void loop() {
    float val = analogRead(0);
    Serial.print("ADC Count: ");
    Serial.print(val);
    Serial.print("  -- Voltage: ");
    val = val * 5.0f / 1023.0f;
    printValueFormatted(val, 1, 4+1+1);
    //print newline
    Serial.println();
    delay(100);
}

Prints
ADC Count: 719.00  -- Voltage: 0003.5
ADC Count: 718.00  -- Voltage: 0003.5

What if i want to change the input analog value to this type of format! then what should I do?

@PeouseDutta I updated the code a bit, do you understand now?

Yes that was very helpful. :)

Why it is not working when I am printing it on a LCD?
it is showing 13.800 instead of 0013.8

@PeouseDutta Can you pastebin the code you're running?

i posted the entire code have a look

@PeouseDutta OK since this is quite lengthy I think it might be best if you asked this as an new question and delete your 'answer' here (because it is not an answer). Also include what it prints in the serial console there.

if(val < 1000){Serial.print('0');}
if(val < 100){Serial.print('0');}
if(val < 10){Serial.print('0');}
Serial.println(val, 1);

This is going to fail for values just under powers of 10.  Consider 999.99 - that is indeed less than 1000, so a leading zero gets printed, but the value itself rounds to 1000.0 when limited to one digit after the decimal point.  You end up with 01000.0, one character too many.  (The idea would work just fine with integer values.)

As is, this isn't going to work. However, it does suggest a strategy of pre-converting to an integer type and a fraction, being careful to get those correctly rounded, and then printing them in an individually formatted manner.


text:
Serial.print only showing "0"
This is my code for a timer. My goal is to increment the count at every 1 sec.
unsigned int count = 0;
int wait = 1000;

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  long current = millis();
  if((millis() - current) == wait)
  {
    count++;
  }
  Serial.println(count);
}

but the serial monitor is only showing zeroes. what to do?

millis() - current will always be 0 because current is always set to the value of millis() right before you compare it.  So it will never equal wait (0 is not 1000), so count never increments.

then what can i do to make it better?

Program it with the correct logic. Think about what you are trying to program logically.

There is one problem. the Serial.println(count); line only working fine inside the If statement but when the Serial.println(count); line is placed outside of the if statement it is only showing zeroes. why is that?

I told you why in my answer. You are subtracting "now" with "now" and expecting it to be something other than 0. "x - x = 0" and can never be anything else, otherwise maths is broken and the universe will end. You need to compare "now" with "then".


text:
Why the LED freezes? when I am adding a delay?
I am new into arduino and stuff. So i was playing around with the pull up resistor. It worked fine but the problem rised when I used a delay to turn the led on for few seconds before it gets back to low state it stopped working when I pressed the switch multiple times it may work sometimes but maximum time it is not working
here is the code
const int buttonPin = 4;
const int ledPin =  12;
int buttonState = 0;

void setup() {
      pinMode(ledPin, OUTPUT);
      pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {
        buttonState = digitalRead(buttonPin);
      if (buttonState == LOW)
  {
    digitalWrite(ledPin, HIGH);
    delay(5000);
  } else
  {
    digitalWrite(ledPin, LOW);
    delay(5000);
  }
}

What does happen, when it doesn't work? Please explain further

the state of the LED doesn't change.

you are not reading the switch during the delay(5000).... you have to hold the button down for up to 5 seconds

Change the second delay to lower value, say 100ms.

one of the things that you have to learn when programming is to identify the area of failure .... your program fails to respond to a pushbutton being pressed, it is not LED freezing

Your Arduino does nothing during the delay(5000). So pressing the button during the 5000 mSec that the led is off won't do anything. Or you must be very lucky to press the button in the very small time between one loop and the next.
I learned a lot about timing and delays with this tutorial: Blink Without Delay

Actually the Arduino is doing something, just not what the op thinks.

Yes, it's waiting till the delay is over...

it never waits. You should see what delay actually does.

in the case of this code it does wait... otherwise this is what it does: 'Certain things do go on while the delay() function is controlling the Atmega chip however, because the delay function does not disable interrupts. Serial communication that appears at the RX pin is recorded, PWM (analogWrite) values and pin states are maintained, and interrupts will work as they should.' (From the arduino reference)

You should actually see what it does. Then you will know what I’m talking about.


text:
NFC/RFID module multiple cards
I have this NFC module. When i read ONE card at a moment everything works fine, but i need to read more that one cart at a moment.
One card lays on a module - module reads it ok, when I move another card over modure, I get a mix of both card's numbers.
Is there any way to read both card at one moment correctry?
I read card like this. As a bord I use NodeMCU ESP8266 ESP-12E
SoftwareSerial rfid(RFID_RX, RFID_TX);
..
void loop()
{
    rfid.listen();
    delay(500);

    while (rfid.available() > 0) {
        Serial.println("Closest card number: " + rfid.readString());
    }

}

"at a moment"? Do you mean that you want to read two cards simultaneously at the same time?

@gre_gor, yes, at same time. in perspective I need to read about 4-5 cards at one moment


text:
Arduino IDE lost board connection
Board: Arduino Leonardo
IDE version: 1.6.5(also tried with 1.8.3)
Try Arduino Web Editor as well
The problem: after connecting Arduino to PC via USB in 5-7 seconds IDE says that connection is losted.
Everything was OK, but after one deploy happened thing, that I described.
If it help: I connect OLED display and use it with OLED_I2C library. Sketch contains one cpp and one h file.
I'm already fully reinstall USB drivers with Arduino USB as well

The problem: after connecting Arduino to PC via USB in 5-7 seconds IDE says that connection is losted.

Yes, that's normal. That's the bootloader running, and it's during that 5-7 second window that you can upload a new sketch.
Under normal circumstances the IDE will automatically reboot the board for you so the upload time window coincides with the IDE's attempt to upload a new sketch. However under some circumstances it can't, so you have to do it manually by pressing the reset button at the right time.
Also on Windows you may find that you have a different COM port for programming as you do when a sketch is running (Windows is retarded like that, you see). The IDE tries to do some magic to identify the correct COM port to use, but you have to first have the correct "sketch mode" COM port selected so it can first reboot the board into the bootloader, at which point it tries to do its magic to work out the correct COM port to use by looking to see which COM port (if any) has just appeared since rebooting.
So, in short: if the IDE can't reboot the board for you then do it manually, but note that timing is vital. Press the reset button a few moments before avrdude runs. It may take practice.

Well, it's seems a little bit strange, but it's work. Thanks :D


text:
Incomplete serial string input
I am using an Arduino M0 Pro and have a device connected via Pin 0 and 1 of it. So I am using the predefined Serial5 interface to receive data from it. I have the following code snippet/method that tries to read an answer from Serial5 if it is available. Otherwise it returns an empty string.
String read_answer() {
  String str = "";
  // Check if bytes are available
  if (Serial5.available()) {
    char c;
    // Read an character unless the read() method returns -1
    // The -1 is identical to 255
    while ((c = Serial5.read()) != 255) {
      // Append the read character to the string array
      str.concat(c);
    }

    // Output the string on the serial debug interface
    Serial.print("Read: \"");
    Serial.print(str);
    Serial.print("\"\n");
  }
  // Return the read string
  return str;
}

If I send an the following string "ABCDEF HIJKL MNOPQR" via an FTDI towards it the first times it correctly printed :
Read: "ABCDEF HIJKL MNOPQR"

But suddenly it just stops reading the complete string. The output is something like that:
Read: "ABCDEF HIJKL MN

It is just cut off and everything stops working, over and over again. It might be a very stupid mistake but I don't know where to check next. If I missed something to explain or more context is needed pls tell me.

Your code has no idea when the string is finished. At the moment it is just waiting until the receive buffer is empty (Serial.read() returns -1), but since serial is a slow protocol that could happen at any time, not just at the end of the string.
You need something to terminate your string so it knows when the end is. The most common way is to use a line feed character (\n, character 10) or a carriage return (\r, character 13) or a combination of the two.
char c;
while ((c = Serial5.read()) != '\n') {
    if (c != 255) {
        str.concat(c);
    }
}

// Output the string on the serial debug interface
Serial.print("Read: \"");
Serial.print(str);
Serial.print("\"\n");


text:
Arduino receives HIGH when the button is LOW
I just got a simple scheme where i have a button connected to the 5V connector and to the 4th digital PIN and then i got a led connected to the 2nd PIN and to the GND. When i press the button the LED should switch on and when i don't press it, it shouldn't bright. The problem here is that i got a True value when i'm not pressing the button. What could it be? Here goes the code:
int Button=0;

void setup() {
Serial.begin(9600);
pinMode(2, OUTPUT);
pinMode(4, INPUT);
}

void loop() {

Button = digitalRead(4);

Serial.println(Button);

if (Button == HIGH) {

  digitalWrite(2, HIGH);

} else {

  digitalWrite(2, LOW);

}

  delay(200);

}

Is there a resistor in series with the led ? You may not connect a led to a pin without resistor. When the button is not pressed, the input is not connected to something. It is floating, and when the pin is read, it can be anything. Have you seen the tutorial ? https://www.arduino.cc/en/Tutorial/Button

or this one arduino.cc/en/Tutorial/InputPullupSerial ?

You will need a pushbutton connected as follows:
The signal labeled Vout will connect to digital pin 4.

Explanation:
When the pushbutton is NOT pressed, no current flows through the resistor, and Vout = 0V. When the pushbutton IS pressed, current flows through the resistor, and Vout = 5V.
This resistor is called a pull-down resistor, because it pulls the signal down to ground. A pull-up resistor would reverse the operation of the pushbutton (i.e. Vout = 5V when not pressed, and 0V when pressed.)


text:
IR Remote control on UNO
I am working on IR remote code run on Arduino UNO
I can already get it work. but when I press the button and hold, the output is sent with the same value repeatly. So,the quesion is how can I do to make it send out only one output while I press and hold the button.
this is my code
#include <IRremote.h>
int RECV_PIN = 5;
#define PB  3392264773 // button code
#define VUP  3476004267 // button code
#define VDN  2998643817 // button code
#define SRC  387001607 // button code
#define MUTE  305976139 // button code

IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {

    if (results.value == PB) {
      Serial.println("Power");
    }
    if (results.value == VUP) {
      Serial.println("Vol UP");
    }
    if (results.value == VDN) {
      Serial.println("Vol Down");
    }
    if (results.value == SRC) {
      Serial.println("Select");
    }
    if (results.value == MUTE) {
      Serial.println("Mute");
    }

    irrecv.resume(); // Receive the next value

  }
}

and this is output when I press and hold the button
Power
Power
Power
Power
Power
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP
Vol UP

Thank you for all answers.
Tanwa

you cannot do anything to make it send only one output ... you cannot modify the remote control

one thing has crossed my mind ... the remote control may be using a repeat code instead of key code when a button is held down ... if that is the case, then the IR library could be modified to generate repeated code that is distinct from the keypress code

by adapting chrisl's idea, I got it done. the code is here.
#include <IRremote.h>
int RECV_PIN = 5;
#define PB  3392264773 // button code
#define VUP  3476004267 // button code
#define VDN  2998643817 // button code
#define SRC  387001607 // button code
#define MUTE  305976139 // button code

int pre_p  = 0;
int pre_src  = 0;
int pre_mu  = 0;

//trigger
int p = 0;
int src = 0;
int mu = 0;

int pw = 0;
int s = 0;
int m = 0;

IRrecv irrecv(RECV_PIN);
decode_results results;

unsigned long previous_timestamp;
unsigned long check_timestamp;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {

        if (results.value == PB){
           p = 1;
          if(p != pre_p){
           pw = !pw;
            //Serial.println(pw);
              Serial.println("pw");
              Serial.println(pw);
          }
        }
      if (results.value == VUP) {
        Serial.println("Vol UP");
      }
      if (results.value == VDN) {
        Serial.println("Vol Down");
      }
      if (results.value == SRC) {
        src = 1;
          if(src != pre_src){
           s = !s;
          Serial.println("s");
          Serial.println(s);
          //Serial.println("Select");
          }
      }
      if (results.value == MUTE) {
        mu = 1;
          if(mu != pre_mu){
           m = !m;
          //Serial.println("Mute");
          Serial.println("mu");
          Serial.println(m);
          }
      }

    irrecv.resume(); // Receive the next value
    pre_p = p;
    pre_src  = src;
    pre_mu  = mu;

    p=0;
    src = 0;
    mu = 0;

    previous_timestamp = millis();

  }
    if(millis() - previous_timestamp > 200){
    pre_p = 0;
    pre_src  = 0;
    pre_mu  = 0;
  }
}

As noted in the comments, you cannot change what the remote is sending. Though I guess, that it would be OK for you to just react to the first occurence of a specific value send consecutively. For that you first need to check the time between these consecutive values send, when holding the button down. That (plus a small margin) will be the threshold to recognize multiple distinct button presses. Note: Depending on the rate, that the remote is sending when holding a button, this might mean, that you cannot distinguish between holding a button and pressing it multiple times in a fast pace.
First define a variable to hold the previous decode results and a timestamp for saving when it arrived:
decode_results previous_results;
unsigned long previous_timestamp;

On receiving a new value via IR, check if the new value is the same as in previous_results. If yes, don't execute the code checking for the actual value. If no, then update previous_results with the new value and act upon the actual received value. Then set the timestamp to the current millis() value and resume receiving.
if (irrecv.decode(&results)) {
  if(results != previous_results){
    previous_results = results;
    if (results.value == PB) {
      Serial.println("Power");
    }
    ....
  }
  previous_timestamp = millis();
  irrecv.resume(); // Receive the next value
}

Now you need to reset the previous_results variable after a specific time threshold, so that consecutive presses on the same button can be registered. Add a corresponding millis() statement to your loop() function:
if(millis() - previous_timestamp > 500){
  previous_results = 0;
}

Note: The value of 500ms is just a wild guess. As described at the start, you need to find that value yourself, fitting to your remote. Play a bit with this value until you are satisfied.
All in all something like this:
#include <IRremote.h>
int RECV_PIN = 5;
#define PB  3392264773 // button code
#define VUP  3476004267 // button code
#define VDN  2998643817 // button code
#define SRC  387001607 // button code
#define MUTE  305976139 // button code

IRrecv irrecv(RECV_PIN);
decode_results results;
decode_results previous_results;
unsigned long previous_timestamp;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
void loop() {
  if (irrecv.decode(&results)) {
    if(results != previous_results){
      previous_results = results;
      if (results.value == PB) {
        Serial.println("Power");
      }
      if (results.value == VUP) {
        Serial.println("Vol UP");
      }
      if (results.value == VDN) {
        Serial.println("Vol Down");
      }
      if (results.value == SRC) {
        Serial.println("Select");
      }
      if (results.value == MUTE) {
        Serial.println("Mute");
      }
    }
    previous_timestamp = millis();
    irrecv.resume(); // Receive the next value
  }

  if(millis() - previous_timestamp > 500){
    previous_results = 0;
  }
}

Note: I have not tested this code in any way.

I got it done by adapting your comment. Thank you very much


text:
Arduino Nano timer, please advice
I'm new here and in the Arduino world. I try to put together a system to cut the power of a LED night light after a preset time. The light is powered by a 5V accu and I would like to avoid to re-charge the accu each morning if the light stays on all night...
I purchased an Arduino Nano, a RTC module and a mini OLED display. I would like to kindly ask you for help in putting the system together: programming the Arduino and connecting the module together. The RTC module should open the possibility to completely automate the system (turn power on and off between precise times) and the OLED Display should give the feedback of the current settings.
The RTC and OLED modules are just "nice to have", my main goal would be to have an automatic cutting of of the power after a certain time (i.E. 60 min.) after initialization of the system (through a push button, for example).
Thank you in advance for your advices!

it is much simpler to do a countdown timer then a scheduler with RTC.

As Juraj said, you don't need an RTC for this. You just have to:

turn the LED on
wait for 60 minutes
turn it off

And do this every time the user presses a push-button.
The code that does this is pretty trivial:
const uint8_t BUTTON_PIN = 2;
const uint8_t LED_PIN = 3;
const uint32_t MINUTE = 60000;
const uint32_t ON_TIME = 60 * MINUTE;

void setup() {
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    pinMode(LED_PIN, OUTPUT);
}

void loop() {
    if (digitalRead(BUTTON_PIN) == LOW) {  // button pressed
        digitalWrite(LED_PIN, HIGH);       // LED on
        delay(ON_TIME);                    // wait
        digitalWrite(LED_PIN, LOW);        // LED off
    }
}

Now, you can build on top of that whatever “nice to have” functionality
you want.


text:
Need to "Extend" a Arduino Digital Signal
Here's the scenario:
We have 1 arduino uno accepting DMX and converting that to a signal that is being sent out digitally (PIN 3). The digital signal then goes to several IR LED senders that control 3,200 IR, color-changing candles. I've recently added some more senders, and now some of the senders are not working (even some that were working before). I assume this is because the digital signal has been weakened due to me splitting it so many times.
I'd like to add another arduino to control half of the IR senders. I obviously already have a cable running to every device, but I know of a perfect place to "interject" the new arduino. Is this possible? Can the second arduino essentially "repeat" or decode and re-encode the digital signal? If so, what pins am I looking at and will I need any special code?
Thanks for the help!

Or - can I use a different PIN on the current Arduino to power the other half of the senders? It needs to be PWM capable.

@AltAir - We use a custom built IR sender using LED Bucks from Sparkfun. We used these last year without a problem. The problem is now happening after adding 6 additional bucks this year.

Can you provide a link to the devices you use in your senders?

@Majenko - https://www.sparkfun.com/products/13716

The scenario you are referring to - connecting one output to many devices - is called the fan-out. Yes, a GPIO pin has a limited amount of drive which limits the number of devices in the fan-out.
There are two problems that are caused by excess fan-out:

Excess current draw from resistive loads
Excess capacitance from logic loads

The former is evident when you have too many LEDs connected directly to an output (with resistors, of course). The combined current draw of the LEDs exceeds the current the IO pin can provide and either damage the pin or the LEDs go dimmer than would be desired.
The latter is more evident when working with communication signals. The excess capacitance imposed by each gate attached to the output causes a low-pass filter effect which can filter out high-frequency signals or corrupt the waveforms by removing higher frequency components and "curving off" the nice clean square waves.
In normal logic systems it's common to use line drivers or buffers to allow the connection of more devices to a single signal. Devices such as the 74HC244, which is 8 buffers in one chip, are commonly employed. You can connect the inputs of all 8 buffers to one Arduino output, and each output from the buffer mirrors the input exactly and can connect to more devices than an Arduino can (each output has an extra 10mA steady-state drive capacity than the Arduino).
And yes, you can even connect the output of one buffer to the inputs of other buffers to give even more capacity.

simulate this circuit – Schematic created using CircuitLab

So it sounds like I could use some of these buffers. Is this something I buy or build?

It's a chip you buy and build into your design.

ok. So basically I would buy one of those devices and then put that between the Arduino and the led bucks?

Yep. That's right.

I have 28 bucks powering 4 IR LEDs each.

where’s the best place to buy the device you’re talking about?

Sounds like too much capacitance corrupting the waveform.

For just one or two then eBay is probably best.

The buffer is a good idea, each pin on an arduino can deliver 20ma, but then the chip can over heat, and you can't drive every output to 20ma, so the buffer chip is the way to go. Just consider the speed of the buffer when you are sending data. There are many chips that can do it, and many that might not be able to do it. So look at the speed of the chip from input to output. Then again, the arduino may not be able to keep up. So consider a PIC, some PIC's are really fast compared to an arduino.


text:
Clion Arduino plugin: Error:Could not find Arduino SDK (set ARDUINO_SDK_PATH)
I am trying to setup CLion as my workspace for my arduino. I have installed the two Arduino plugins for CLion, generated a new sketch project, but I am getting cmake errors on opening the project.
CMake Error at /cygdrive/c/Users/user/project/cmake/ArduinoToolchain.cmake:86 (message):
  Could not find Arduino SDK (set ARDUINO_SDK_PATH)!
Call Stack (most recent call first):
  /cygdrive/c/Users/user/project/CMakeFiles/3.9.4/CMakeSystem.cmake:6 (include)
  /cygdrive/c/Users/user/project/CMakeFiles/CMakeTmp/CMakeLists.txt:3 (project)

The issue is similar to this logged issue here:
https://github.com/francoiscampbell/CLionArduinoPlugin/issues/11
As a Windows 10 user, I have the Arduino SDK installed here: C:\Program Files (x86)\Arduino
What's interesting is that the cmake file is calling the UNIX commands when it's running in this if statement:
    if(UNIX)
        file(GLOB SDK_PATH_HINTS /usr/share/arduino*
            /opt/local/arduino*
            /opt/arduino*
            /usr/local/share/arduino*

                )
    elseif(WIN32)
        set(SDK_PATH_HINTS "C:\\Program Files\\Arduino"
            "C:\\Program Files (x86)\\Arduino\\libraries"
            )
    endif()

I have the same error, even if I set it manually: set(ARDUINO_SDK_PATH C:\Program Files\Arduino) I checked my path, but nothing wrong in the arduino path, I'm using Cygwin if it can help...

Me too. Did you ever figure this out?

unfortunately no :(


text:
How much low analog voltage can Arduino uno read?
Today I was playing around with arduino analog voltage ranges, the error in output
 with respect to a digital multimeter started to happen when the reading was around 0.0014volts. How much low an arduino can read?

What reference voltage do you use?

you could use an opamp to scale (amplify) low voltages like (0-0.05) to a 0-5v range.

There are other possibilities to make more precise readings: one can use Arduino with an external ADC with better voltage resolution (e.g. 16 bit), or average several readings to reduce measurement noise.

If you are measuring lower voltages, you can use the internal 1.1 band gap voltage as a reference voltage.

The Arduino Uno uses a processor containing a 10 bit ADC.  This means the ADC can resolve (if we do not consider noise) 2 to the 10th or 1024 voltage levels between zero and the voltage supplied to the Arduino Uno at the AREF pin.  There is a good explanation of the AREF pin in this stackexchange.com question / answer.  It is common practice to supply the AREF with voltages lower than the positive rail the processor is operating at to improve resolution of expected lower voltages.  For example, if you do not expect to measure voltages higher than 3.3 volts on a 5 volt Arduino, use the 3.3 volt supply as a reference.  Relative to using a 5 volt reference, using a 3.3 volt reference decreases your granularity from 0.00489 to 0.00322 volts per step.
Of course there is a lot of noise in most ADC circuits.  Finding the average of many ADC readings helps mitigate this problem.  Consider using exponential averaging.

You divide your reference voltage by 1024.  That tells you what the step size is.  The smallest you can measure is an ADC reading of 1.  So for say a 5V reference that works out to 0.00488V


text:
How to connect SPI device on Etherntet shield on Arduino Uno
In my project I need to connect RFID reader (RC522) on top of the Ethernet shield because of it's capability of reading and editing SD card. When I connect only RFID sensor on Arduino, it works. Same goes to Ethernet shield. But when I use both together, It simply doesn't work. I can compile it and upload it, but I don't get anything in the serial monitor. I think it's because both Ethernet shield and RFID reader use the same pins for SPI like MOSI, MISO and SCK. My question is, if that is the problem, how to connect multiple SPI devices on Arduino, or at least on Ethernet shield.
Here is my code, although I think there's nothing wrong with it. I just merged code for RFID and Ethernet shield with copy-pasting. Sorry for bad formatting, I need it just for test, I'll later make the real code.
#include <SPI.h>
#include <MFRC522.h>
#include <SD.h>

#define RST_PIN         6          // Configurable, see typical pin layout above
#define SS_PIN          7

MFRC522 mfrc522(SS_PIN, RST_PIN);

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// MKRZero SD: SDCARD_SS_PIN
const int chipSelect = 4;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
  mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
  Serial.println(("Scan PICC to see UID, SAK, type, and data blocks..."));

  Serial.print("\nInitializing SD card...");

  // we'll use the initialization code from the utility libraries
  // since we're just testing if the card is working!
  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    while (1);
  }

  Serial.print("Clusters:          ");
  Serial.println(volume.clusterCount());
  Serial.print("Blocks x Cluster:  ");
  Serial.println(volume.blocksPerCluster());

  Serial.print("Total Blocks:      ");
  Serial.println(volume.blocksPerCluster() * volume.clusterCount());
  Serial.println();

  // print the type and size of the first FAT-type volume
  uint32_t volumesize;
  Serial.print("Volume type is:    FAT");
  Serial.println(volume.fatType(), DEC);

  volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
  volumesize *= volume.clusterCount();       // we'll have a lot of clusters
  volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
  Serial.print("Volume size (Kb):  ");
  Serial.println(volumesize);
  Serial.print("Volume size (Mb):  ");
  volumesize /= 1024;
  Serial.println(volumesize);
  Serial.print("Volume size (Gb):  ");
  Serial.println((float)volumesize / 1024.0);

  Serial.println("\nFiles found on the card (name, date and size in bytes): ");
  root.openRoot(volume);

  // list all files in the card with date and size
  root.ls(LS_R | LS_DATE | LS_SIZE);
  }
}

void loop() {
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  // Dump debug info about the card; PICC_HaltA() is automatically called
  mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

Sorry for being dumb, where is your Ethernet bit code? Also you know that SPI uses Chip select to select device it wants to talk to?

set pin 10 HIGH if you don't use the Ethernet chip

You mean because shields SS is 10? And do you mean that I do pinMode(10, HIGH); ?

yes, set 10 as OUTPUT and HIGH. while it is floating it randomly enables and disables the Wiznet chip on SPI bus

The two devices should share SCK, MISO, and MOSI, but SS (or CS as it's sometimes called) will have to be different and both shields are probably trying to use pin 10 for SS.  Let the ethernet shield have pin 10 for SS.  On the other shield, take that pin and bend it out so it doens't go down into the header when you stack them and then solder a wire to it and take it to another pin.  Go into the code and modify the code for that shield to use the new pin as SS instead of pin 10.

they have pin 7 as SS for RFID reader. and it is not a shield I think

Does CS mean chip select? By the way you are right juraj.

Yes CS is chip select.

OK if they already have the CS lines separated then the next thing to check is SPI modes.  Maybe the two devices use different SPI modes.


text:
Powering Atmega328p from 4.5V
I want to use Atmega328p controller to handle some very simple signals. I'm using the chip and not the whole arduino board because it is a lot cheaper. The problem is that chip itself doesn't have voltage regulator so I need to think of a rechargeable power source. My idea is to use 3 rechargeable AA batteries (~4.5V). I read that it can handle somewhere from 1.5V to 5.5V but I also read that clock speed is then reduced and a lot other complications. So, finally, the question, If I were to use described power source, what challenges should I be ready to face and how will it impact the performance and is it even possible to pull it off.

From the ATmega328P datasheet:

Within the range 2.7 V – 4.5 V, the maximum frequency is a
linear function of Vcc. From this graph, you can compute the minimum
value of Vcc required to run the microcontroller at 16 MHz: it's
3.78 V.
If you do want to run at 16 MHz, in order to emulate an Arduino
Uno, it may become unreliable once the supply voltage drops below
3.78 V, i.e. 1.26 V per cell. Whether this is a serious issue or
not depends on the cell chemistry. For reference, alkalines reach about
1 V at the end of their useful life, and NiCd has about 1.2 V
when fully charged. You will have to find the relevant voltage for the
chemistry you plan to use.
If you can afford running the microcontroller at 8 MHz, then you
will most certainly be safe.
Edit: If you want to run the microcontroller at 8 MHz, and you
are programming it with the Arduino IDE, you have to select a
board/processor combination that runs at 8 MHz. For example,
“Arduino Pro or Pro Mini” / “ATmega328P (3.3V 8MHz)”. This will ensure
that the time-related functions (millis(), delay(), etc.) and the
baudrates of Serial.begin() provide the correct timings. Other than
that, the drawback of running at a lower clock speed is that the
CPU-bound functions (computations) take twice as long.

+1, but I got 3.6 V.

@tim: The linear interpolation formula is Vcc = 2.7 + (f-10)/(20-10)*(4.5-2.7).

Ah, thanks, I see where I went wrong. There are two different gradients which I didn't initially spot and was using the gradient between 1.8 V to 2.7 V to calculate for 16 MHz which is on the second gradient between 2.7 V and 4.5 V.

What are side effects of running your board at lower clock speeds? I can see that it would be slower but is that really it?

@Mirakul It also affects your choice of PWM frequencies and UART speeds. But mostly just... everything takes twice as long :)

Personal anecdote: I've observed an ATmega644p running seemingly fine at 20 MHz on only 3.3 V.   You can operate outside the safe operating area, it's just not "safe" outside of it.

@Mirakul: See edited answer.

Thank you, that is what I needed.

They make SEPIC converters that will hold the voltage at 5V for you. The reason for the SEPIC is during charge what happens to the battery voltage and especially if the battery open circuits. If there is no chance for the battery voltage to go to high a boost converter will work just fine. This solution will allow it to run at full speed without degrading performance etc. The new converters are not very expensive and are generally greater than 95% efficient depending on the unit. If you can up the battery voltage things will get a lot more efficient but you would then need to change the boost to a buck, the SEPIC would be fine. I tend to use the China Nanos, they are inexpensive, probably less then your parts and readily available. I have not had problems with them. I like to supply them with about 8 volts via Vin, that gives me the additional filtering of the onboard power supply.

I am surprised that you claim an efficiency of 95%. The figures I have seen tend to be in the 70 to 90% range, and that is with currents of 500mA, An ATMEGA typically takes a few mA, and with consumption that low, the overheads of the switcher are likely to exceed the throughput (ie efficiency less than 50%).