text:
How can a function/method determine if a const array passed in is PROGMEM (flash) or not (RAM)?
Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?
If I have a method or function that receives a constant array that is in RAM, the array is declared like this:  const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };
gets passed into a method or function like this:  MyFunction(MY_ARRAY);
and the method or function can handle it like this:
void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM:   const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };
The pass looks the same:  MyFunction(MY_ARRAY);
And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:
void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not?  Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).
If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.
Some relevant questions:
How to pass a static const (progmem) array to a function
RAM usage question: PROGMEM vs const vs #define
Storing array in PROGMEM
PROGMEM: do I have to copy data from flash to RAM for reading?
UPDATE:
It looks like what I want to do is not possible.  The responses below are very interesting options though:  using __flash in plain C, using OOP to make PROGMEM and non-PROGMEM data holders or trying to (somehow?) use non-deprecated progmem specific data types from avr/gpmspace.h.
The best answer to my original question is that the method can not make this determination.  The best solution, from a comment by Delta_G, is to create regular (ram) and "_P" (flash/ progmem) versions of the functions and to be as obvious as possible in the naming of those functions.

You can use the same trick as the Arduino classes are using. class __FlashStringHelper; #define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal))) and function overloading

@KIIV That sounds very promising.  Can you show me what the function declaration would look like or give some references on how to do that?

Go look at the Print class in the Arduino core.

void someFunction(const __FlashStringHelper *str); and call it like   someFunction(F("soometning"));

But the input is an array of uint8_t not a string.  Does it still work?

Not exactly, but if you go look at the Arduino core at how that whole thing works it is possible to do something similar.  You can do that or you can have two different functions.  But you can't make it where the user doesn't have to know the difference.  They'll either have to declare their data with your specific data type that you create for your overload, or they'll have to cast to it, or they'll have to know to call a different function.  You can't take that decision off of them either way.

You would have to create your own dummy class, analogous to __FlashStringHelper, for each type that you want to store in flash. Not very convenient to say the least...

Or, you can use arduino based on Atmega4809 as there is flash address space mapped into memory address space with 0x4000 start offset (and compiler takes care about it if it's const variable)

After digging through WString.h and pgmspace.h, this looks beyond my c++ chops.  It also would seem to force the caller to use an F() type macro, which if I can be sure they will do that, then I can be sure it will use PROGMEM.  I guess I can add some notation, likely including the word "PROGMEM" in the function name as well as in the input name for the flash const array and just hope all callers remember the PROGMEM contract.

That's what you end up having to do.  You release with two versions of the code and a note that if the user wants to use PROGMEM they can but they have to call the _P version of the function or however you name it differently.  Often that's easier than trying to have it both ways because it reminds the user right in the name of the function and that sort of forces them back to the docs to see how it needs to be set up.

@Delta_G  Thanks.  I've messed up the using or not using the pgm thing enough times that I was hoping there was a way to solve it once and for all (anticipating that I'll do it again).  Oh well, more hardware testing.  If you write that up as a solution I can accept it.

everything in this question, comments and answers assumes classic AVR. it is different for esp8266 and the Arduino megaavr boards package

@KIIV Please do not answer questions in a comment. See How do comments work?. They are not for answering a question.

@Delta_G You too. This isn't a forum. The whole idea here is that you make an actual answer. Then people can vote on it and it can be accepted. Bonus feature - you get reputation from this. Not from answering in comments.

And you other guys.

I am afraid there is no good solution to this problem. One option I do
like is to use the __flash qualifier instead of PROGMEM:
const uint8_t ram_array[] = { 1, 2, 3, 4 };
__flash const uint8_t flash_array[] = { 5, 6, 7, 8 };

void function_reading_ram(const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

void function_reading_flash(__flash const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

int main(void)
{
    function_reading_ram(ram_array);      // OK
    function_reading_flash(flash_array);  // OK
    function_reading_ram(flash_array);    // Warning
    function_reading_flash(ram_array);    // Warning
}

Note that, with __flash, you don't need pgm_read_byte_near() or
anything similar. You just use the array like you would use any regular
array, and the compiler is smart enough to generate the code required to
access the Flash memory.
The warnings generated by gcc are:
warning: conversion from address space ‘__flash’ to address space ‘generic’ [-Waddr-space-convert]
     function_reading_ram(flash_array);
     ^
warning: conversion from address space ‘generic’ to address space ‘__flash’ [-Waddr-space-convert]
     function_reading_flash(ram_array);
     ^

Given how nice this solution is, you may wonder why I wrote “there is no
good solution”. Well, this comes with two caveats, one small and one
huge. The small caveat is that you need to explicitly pass the option
-Waddr-space-convert to the compiler if you want it to generate the warnings.
It is not implied even with
-Wall -Wextra. The huge caveat is that this only works in plain C.
If you try to use this trick in C++ you get:
error: ‘__flash’ does not name a type

This is an implementation of the “named address spaces” extension to the
standard C. Since nothing like this is standardized in C++, the authors
of gcc assumed it would not be useful to users of C++. :-( You can mix C
and C++ sources in Arduino, but you can't call class methods from C.

That's good to know.  I've not heard of _flash before.  However, I've got classes on my classes, so I'm stuck with C++ on this one.

I will expand on KIIV's comment here.
This is a known issue to the people who wrote the Arduino framework. Essentially, the pointers to PROGMEM and RAM are both data pointers (think of a pointer like an array index, but for the entire RAM/Flash itself rather than one chunk of it that you manage) of the same size and type. They cannot be told apart since pointer types are only determined by the size of the data, not where the data is.
So, they used a clever solution: Make the pointer into a different pointer that isn't compatible with the regular RAM pointer. This is done by casting to the __FlashStringHelper class (and then casting back when it must be read). The FSH class doesn't actually have any methods or do anything; it's simply used to define a custom pointer type that is different from the normal const *.
You can directly go read one of the better guides I've seen on it here (Note that it's for the ESP8266, but this part works the same), or I can try to explain it. I suggest reading it anyway, since it has a lot of other info that's useful but not relevant to this question. Do note that they have a few examples near the end which don't de-allocate memory when they are done using it, though, so copying them directly could cause a memory leak (see my string processing example to see the proper method).
First, you need to cast the array to the FSH class:
const byte MyProgmemArray[] PROGMEM = {4,4,4,4,4,4,4,4}; //Fixes issue #82 (add randomness); see https://xkcd.com/221/ for details :D
__FlashStringHelper * MyArray = (__FlashStringHelper *) MyProgmemArray;

I am unaware if there is any method (and I did look) to declare these in-place, i.e. to make the original array declaration into a __FlashStringHelper * directly. So you still need, as the programmer/user, to know which strings are in flash when you add them, and add the conversion line. This means that what you wanted (fully automatic RAM/Flash detection) isn't quite possible, but this is as close as I think it gets. A further warning is that the original array still exists, meaning that it could accidentally be used instead (will still cause the original mismatch issue) and the new definition takes up slightly more memory for the additional pointer (if the compiler does not optimize it out?).
Oddly, it works fine if your want to store a string:
__FlashStringHelper * MyString = PSTR("yaddayaddayadda...");

Strings can be inlined, but I think it's because of both the PSTR macro and because string definitions might be treated differently than an array of values (even though they are physically the same thing). Perhaps you could experiment with however PSTR works (it's actually a macro that does something, and isn't just a keyword) and see if you can implement this in your own code after all.

Now, you still need to get the data OUT of the array in that function you mentioned. To do that, we actually use two versions of that function. This is called overloading (and I think it's C++ only, but this is Arduino, which is by definition C++, so it's safe).
The RAM function you declare as normal:
void MyFunction(const uint8_t *MY_ARRAY){
  byte index_two = MY_ARRAY[1];
  ...
}

The PROGMEM function you declare as follows (assuming that pgm_read_byte_near IS the right function. Also note that it gets more complicated if you need multi-byte values, like int or something...):
void MyFunction(__FlashStringHelper *MY_PROGMEM_ARRAY){
  const byte *MY_ARRAY = (const byte *)MY_PROGMEM_ARRAY; //convert back to normal
  byte index_two = pgm_read_byte_near(MY_ARRAY+1); //still have to read it as flash, of course
  ...
}

As a bonus bit of info that is unrelated to the question as asked, but that may interest you/be relevant later:
There are a few more notes if you use this for string data (or pretend it's a string for this part, which works if your data contains no zeros and ends in one). By the latter, I refer to the fact that strings in C (NOT the C++ std::string or Arduino String, though, so keep this in mind) are basically char arrays with a 0 tacked on the end. All string-processing functions run an infinite loop until they read a 0 at their current index, which allows them to work with strings of any length but still know when they are done. As a result, when reading it, you can treat your data like a string, with three caveats:

It can never contain a 0, except for the very last item, which won't be read.
When defining it, you'd need to still use {} instead of "" since most values don't have printable ASCII characters. (And even so, you'd have to write " " for 32, for instance.)
You can't actually print the alleged string, since the data won't actually contain printable characters. You'll get any mix of numbers, letters, punctuation, and fun things like backspace and newline all jumbled together. You would need to read each character and convert it (via, say, String num = <your value here>; or itoa() etc).

If you want to print it using an existing Arduino function, like Serial.print, and it is actually a string (and not data pretending to be a string), it will natively support __FlashStringHelper *, so you don't need the conversion step (this lets you do Serial.print(F("No static RAM used here!")); and similar).
There are two ways to read the data if it is for your own string-processing function, however. The first, the simple one, is not memory efficient and creates a full copy of the data or string in RAM while it's being used. As a result, it is not capable of processing strings that are too large for RAM and may have issues if it's called while a lot of RAM is already in use or it is called deep down a set of nested functions. It is very convenient, however:
//convert from __FlashStringHelper * as above, but let's assume it's a char* here
int size = strlen_P(MY_ARRAY);
if (size!=0){
  char * data = new char[size];
  if (data!=NULL){
    strcpy_P(data,MY_ARRAY);
    //do stuff with the string
    delete data;
  }
}

The second method is more annoying to actually do, and requires more control over how the data is processed, but you can also read out the data byte-by-byte as shown in my first decoding example above using pgm_read_byte_near. This lets you work with data that is too large to fit in RAM and keeps a constant stack size too. The downside is that it requires that you are actually able to stream the data byte-by-byte in all places that it's then used (or that you re-read it when it needs to be accessed out-of-order).

There is also an OO solution possible, using the strategy design pattern, but this comes with some (slight) memory and performance penalties. You need to use C++ for this.

Put each array you want to differ between flash/SRAM in a separate class (one per type). You get data hiding and possible separation of concerns for free.
Instead of putting the array in each class, put a reference/pointer or use it directly.
You can use inheritance:

Create a Flash Array class with a SRAM array reader/writer
Create an SRAM Array class with a Flash array reader/writer
Inherit each of the array types you use from one of these classes where the base class takes care of reading/writing.

Alternative solution: use the strategy pattern; involves a bit more work, but you can prevent multiple inheritance (although since you use C now, you don't use inheritance (yet)). This would involve roughly:

Create a Flash and SRAM Array class reader as above.
Instead of inheritance, create a pointer to one of these classes which suits the type of the array.

Although I can imagine this will mean quite some changes in your sketch.
Explanation using Inheritance
(requested by comment)
@Casey I assume you mean the Inheritance way. Assume in a class you have x_array which is of type FlashArray. You just call x_array.Read(...). This method is implemented in FlashArray, but also with the same parameters in RamArray. You can enforce this by inheriting both FlashArray and RamArray by a base class (e.g. ArduinoArray and create a (pure) virtual function Read with the same arguments. Anyway, the implementation of Read method in FlashArray should read from Flash and the same method in RamArray should read from RAM.
When you change the type of x_array from FlashArray to RamArray or vice versa, you don't need to change anything (except the types). To make this easier consider defining a type for x_array, so when you later need to change it, you only need to do this in one location.

The advantage of two separate classes is that you can make a per-class policy on data accesses, e.g. "for this class, I would like to copy the data into the current stack frame before working with it". Given the typically small scope of Arduino programs, the code duplication is probably still more readable than a template monster that tries to avoid it. Typical data classes I work with have a "from-flash" constructor, where they copy all the members out of a struct with no methods, and the compiler optimizes out the copies for the members that go unused.

@SimonRichter Thanks for the additional comment. I almost never program beforehand on performance, unless I know it will be an issue. As you say, nowadays compilers optimizes a lot.

Yes, that's the beauty of it: I can change the performance characteristics later on by changing the communication between the "in-flash" and "in-ram" classes, without changing the users of these classes.

@SimonRichter you could even change it dynamically, during execution of the sketch).

I think I see how this would work, but one of my goals here is to make the handling method be able to deal with either without relying on the author of the caller to do anything special.  My fear is the wrong array type (flash or ram) gets send to a routine and the reader uses the wrong method and produces garbage as a result.  Your OO option seems to force a bunch more on the caller side.  Do I have this right?

@Casey I added an example in my answer.

Or you could have a single class and overload the read() method.

@EdgarBonet That's also possible, although I rather like a neater split as ArduinoArray is more suitable as an abstract base class. But indeed, both ways are possible.

The classic avr-gcc way is to have dedicated functions with different names
e.g. void* memcpy(void* dest, const void* src, size_t n);  // Only works if src is RAM
vs. void* memcpy_P(void *dest, PGM_VOID_P src, size_t n); // Only works if src is PROGMEM
BTW: That's mentioned in a comment to the question already by @Delta_G. More about the example memcpy_P here

PGM_VOID_P looks very similar to what I'm after.  Can I just use that to enforce that the pointer (well, array really) is in PROGMEM?  Or, do I need a different version of it that is for uint8_t arrays?

I tried replacing my "const uint8_t *" declaration with "PGM_VOID_P" but that doesn't work because they are different types.  avr/pgmspace.h has a bunch of PROGMEM data types, such as prog_uint8_t, but they have all been deprecated.  pgmspace.h recommends using the attribute during declaration.  So, it looks like what I want to do use to be possible, but isn't any longer.


text:
Setting up 433 MHz Transmitter and Receiver in the same Arduino sketch using Radiohead
I have set up a 433 MHz transmitter and receiver pair on one Arduino Uno board. Using the RCSwitch library, I could successfully send and receive signals. Using the Radiohead library however, I could only send and got no reception. I am curious why and grateful for any help.
Here is the sketch. Both receiver and transmitter draw power from Arduino 5V and GND. The DATA pin of transmitter is attached to pin 12 of Arduino. The DATA pin of receiver is attached to pin 11. These appear to be "hard-coded" in the Radiohead library. My reciever has an additional chip select (CS) pin which I have wired to pin 10.
Using the serial monitor, it looks like transmitter and receiver are initialized without problem and message is sent. I have used the RCSwitch library with transmitter and receiver on the same board and that worked, (i.e. messages sent were received correctly) so I am curious why the issue with Radiohead.
// Include RadioHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// Include dependent SPI Library
#include <SPI.h>

// Create Amplitude Shift Keying Object
RH_ASK rf_receiver;
RH_ASK rf_transmitter;

void setup()
{
    // Initialize ASK Object
    if (!rf_receiver.init())
        Serial.println("Failed to initialize receiver.");
    if (!rf_transmitter.init())
        Serial.println("Failed to initialize transmitter.");

    Serial.begin(9600);

    digitalWrite(10, HIGH);   // enable CS on some receiver devices
}

void loop()
{
    const char *msg = "Hello world!";
    rf_transmitter.send((uint8_t *)msg, strlen(msg));
    rf_transmitter.waitPacketSent();
    Serial.print("Message sent: ");
    Serial.println((char*)msg);

    uint8_t buf[12];
    uint8_t buflen = sizeof(buf);

    if (rf_receiver.recv(buf, &buflen))
    {
      Serial.print("Message received: ");
      Serial.println((char*)buf);
    }
    else
    {
      Serial.print("No message rec'd: ");
      Serial.println(*&buflen);
      Serial.println((char*)buf);
    }

    delay(1000);
}

The answer can be found in the source code 0f RH_ASK.h (you should read the well made documentation before using this library):

At present only one instance of RH_ASK per sketch is supported.

So you will have to write such an extension yourself, use two Arduinos or use another lib for testing.

source: Stack Exchange

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

sort: votes


text:
HTU21 on GY-21 breakout board I2C problem
I am interfacing the HTU21D sensor with my nodeMCU v3. All good! I managed to get some readings etc. But when I re-upload my code the device does not respond. If I remove the power supply from the pin and hard reset it, it works again. I have exactly the same problem using the Sparkfun library, so it seems more of a hardware problem. Anyone else had the same problem?
link to the sparkfun library
https://github.com/sparkfun/SparkFun_HTU21D_Breakout_Arduino_Library
for reference, here is my code
   This program interfaces the HTU21 temp/humidity sensor via I2C
*/

#include <Wire.h>
#include <Math.h>

const int HTU21_ADDR = 0x40;
const int Trigger_Temp_Measurement = 0xE3;// hold master
const int Trigger_Hum_Measurement = 0xE5; // hold master
const int Trigger_Temp = 0xF3; //No Hold Master
const int Trigger_Hum = 0xF5; //No Hold Master

int16_t Temp, Hum;//variables to store temp and humidity
int8_t TmpCrc, HumCrC;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(HTU21_ADDR);
  Wire.write(0xFE);
  Wire.endTransmission(true);

}

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

}

void TempReading() {

  Wire.beginTransmission(HTU21_ADDR);
  Wire.write(Trigger_Temp_Measurement);
  Wire.endTransmission();

  Wire.requestFrom(HTU21_ADDR, 3, true);
  if (Wire.available() <= 3) {
    Temp = (Wire.read() << 8) | (Wire.read() );
    TmpCrc = Wire.read();
  }
  float TempCalc = -46.85 + (175.72 * ((float)Temp / (pow(2, 16))));
  Serial.print("Temperature \t");
  Serial.print(TempCalc);
  //Serial.println(TmpCrc, HEX);

}

void HumReading() {
  Wire.beginTransmission(HTU21_ADDR);
  Wire.write(Trigger_Hum_Measurement);
  Wire.endTransmission();

  Wire.requestFrom(HTU21_ADDR, 3, true);
  if (Wire.available() <= 3) {
    Hum = (Wire.read() << 8) | (Wire.read());
    HumCrC = Wire.read();
  }

  float HumCalc = -6 + 125 * (Hum / (pow(2, 16)));
  Serial.print("\t Humidity \t");
  Serial.println(HumCalc);
  //Serial.println(HumCrC, HEX);

}```

Are you also resetting the slave device together with the nodeMCU? When you disrupt the I2C communication at the wrong time, the slave might be in a bad state, blocking the bus. Also you might not want to spam the I2C and Serial bus (because you don't have any delay or such in your loop())

Well If I press reset it would run through the setup loop which would reset the device. This would indeed NOT work if the I2C bus is in a bad state. What could be a solution to reset the bus?

Does the setup really run completely? How do you know that? With reset I mean a real hard reset, not a command reset. Only a hard reset would reset the I2C bus

Yes the setup runs completely. I found out that the bus hangs if I terminate communication by uploading new code to the board. I found a piece of code that releases the bus which works.

Yes the setup runs completely. I found out that the bus hangs if I terminate communication by uploading new code to the board. I found a piece of code that releases the bus which works. See below:
#if defined(TWCR) && defined(TWEN)
  TWCR &= ~(_BV(TWEN)); //Disable the Atmel 2-Wire interface so we can control the SDA and SCL pins directly
#endif

  pinMode(SDA, INPUT_PULLUP); // Make SDA (data) and SCL (clock) pins Inputs with pullup.
  pinMode(SCL, INPUT_PULLUP);

  boolean SCL_LOW = (digitalRead(SCL) == LOW); // Check is SCL is Low.
  if (SCL_LOW) { //If it is held low Arduno cannot become the I2C master.
    return 1; //I2C bus error. Could not clear SCL clock line held low
  }

  boolean SDA_LOW = (digitalRead(SDA) == LOW);  // vi. Check SDA input.
  int clockCount = 20; // > 2x9 clock

  while (SDA_LOW && (clockCount > 0)) { //  vii. If SDA is Low,
    clockCount--;
    // Note: I2C bus is open collector so do NOT drive SCL or SDA high.
    pinMode(SCL, INPUT); // release SCL pullup so that when made output it will be LOW
    pinMode(SCL, OUTPUT); // then clock SCL Low
    delayMicroseconds(10); //  for >5uS
    pinMode(SCL, INPUT); // release SCL LOW
    pinMode(SCL, INPUT_PULLUP); // turn on pullup resistors again
    // do not force high as slave may be holding it low for clock stretching.
    delayMicroseconds(10); //  for >5uS
    // The >5uS is so that even the slowest I2C devices are handled.
    SCL_LOW = (digitalRead(SCL) == LOW); // Check if SCL is Low.
    int counter = 20;
    while (SCL_LOW && (counter > 0)) {  //  loop waiting for SCL to become High only wait 2sec.
      counter--;
      delay(100);
      SCL_LOW = (digitalRead(SCL) == LOW);
    }
    if (SCL_LOW) { // still low after 2 sec error
      return 2; // I2C bus error. Could not clear. SCL clock line held low by slave clock stretch for >2sec
    }
    SDA_LOW = (digitalRead(SDA) == LOW); //   and check SDA input again and loop
  }
  if (SDA_LOW) { // still low
    return 3; // I2C bus error. Could not clear. SDA data line held low
  }

  // else pull SDA line low for Start or Repeated Start
  pinMode(SDA, INPUT); // remove pullup.
  pinMode(SDA, OUTPUT);  // and then make it LOW i.e. send an I2C Start or Repeated start control.
  // When there is only one I2C master a Start or Repeat Start has the same function as a Stop and clears the bus.
  /// A Repeat Start is a Start occurring after a Start with no intervening Stop.
  delayMicroseconds(10); // wait >5uS
  pinMode(SDA, INPUT); // remove output low
  pinMode(SDA, INPUT_PULLUP); // and make SDA high i.e. send I2C STOP control.
  delayMicroseconds(10); // x. wait >5uS
  pinMode(SDA, INPUT); // and reset pins as tri-state inputs which is the default state on reset
  pinMode(SCL, INPUT);
  return 0; // all ok
}

Thanks for pointing me in the right direction!

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


text:
How do I configure WEMOS D1 R2 Vin pin to output max voltage?
I am in need of 12VDC from my Wemos D1 R2. How do I configure the Vin pin to output the max (I think its 12VDC)?
board: Wemos D1 R2 V2.1.0 - ESP8266 (LOLIN D1 R2)
Pinout here in pictures below

Your Wemos D1 cannot generate a higher voltage than what is provided as input (via the barrel connector). It will only output 12V if you connect your own 12V power supply to the barrel connector.

you should learn how to use a mosfet as a switch in these types of situations.

After looking into it and seeing all the previous answers, I noticed the Vin pin can be used as an output but only up to the input from the barrel connector.
When using a 9V input to the barrel jack, the voltage difference between the ground pin and Vin pin was just under 9V. Similarly, when measuring the voltage difference when using a 12V supply, the multimeter reported just under 12V.
This is in line with @StarCat comment.

You cannot. You are misunderstanding, what that pin is. Vin means Voltage In. It's a voltage input, connected to a voltage regulator, which will regulate the provided voltage at that pin down to 3.3V for the Wemos to work with. It is not an output. The regulator cannot convert the 3.3V from the Wemos to 12V. That is not, what it is build for.
To get 12V you either need a separate 12V power source, or you need to buy a stepup/boost converter, which brings the 3.3V (or 5V, if you are powering from USB) up to 12V. For the latter, be sure, that the converter and the source, where you get the input voltage of the converter, can provide enough current for your use case.


text:
Uno Wifi rev2 - after long time it disconnects
Given an Arduino Uno Wifi Rev2 with this small U-blox NINA wifi module.
All work great however after a long time (I can't be more exact but we talk here about weeks if not months), it suddenly disconnects.
This board is unattended, and the only way to recover is to reset the Arduino.
Here is my code:
WiFiServer server(PORT);

void setup() {
  connectToWifi();
  server.begin();
}

void connectToWifi() {
  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    if (status == WL_CONNECTED) break;

    // wait 10 seconds for connection:
    delay(10000);
  }
}

void loop() {
  // check WiFi status
  if (WL_CONNECTED != WiFi.status()) connectToWifi();

  WiFiClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        ... (other wifi-unrelated code)

        // close the connection:
        client.stop();
      }
    }
  }
}

When it disconnects from wifi, the router's dhcp manager console shows it with "waiting" status.
Note: I'm the only client, and only one character is sent to the Arduino at once, then the socket is closed. It is very unlikely, that a client hangs, and the board is stuck in the while loop.
Is this a known problem, or I have to dig myself more into this?
Thank you!

do you use the newest versions of firmware and library?

I've updated that at the end of last year. Until then it is unattended, and this is the second time this situation happened. (after the first time we had to apply a power recycle to the board). So I'm not sure that's the latest, and I can not query it, as it is far away and lost the connection

As you have not given the details there are some things to check

is your Nina-Firmware > 1.2.4
If not update to the latest 1.3.0 via the WiFi101-FirmwareUpdater-Plugin 0.10.10 is included in the ArduinoIDE 1.8.12 or greater
Disconnect before you reconnect (in case of router drop-outs) and
Close any connection before sending/receiving. This will free the socket on the Nina module. Stop the client after doing the stuff needed with   client.stop();
If there is any server connection code in setup this should be run in a reconnect routine (as you did not include setup) just as a hint
Make sure that after a certain period the while (status != WL_CONNECTED) and while (client.connected()) are broken and error testing takes place e.g. if (status==WL_DISCONNECTED || status==WL_CONNECTION_LOST){.. do something to change that ..}
If all fails implement a routine that checks the signal and restarts the sketch if the router has dropped out (for whatever reason).

Disconnect code:
void connectToWifi() {
    // This new line is required to disconnect the previous connection otherwise
    // it will try to use the old connection and never reconnect if the connection fails
    status = WiFi.disconnect();

    // attempt to connect to Wifi network:
    while (status != WL_CONNECTED) {
    .... REST of your code ...
    }
}

Hint (as you did not show setup) if you have something like
client.connect(server, 80);

move it to the reconnection routine in the form of
if (client.connect(server, 80)) {
    Serial.println("connecting...");
.... REST of reconnect ...
}

Restart code if wifi signal is lost
void(* resetFunc) (void) = 0; // Declare reset function at address 0

void loop() {
  if (WiFi.RSSI() == 0) // Checks if Wifi signal lost.
  { resetFunc(); // Calls Reset
  }
// Rest of code goes here.
}

This should altogether ensure a long and stable running client

Thank you, points 1-2-3 I can check once I return to the board. client.stop(); is actually called, I've updated the Q. server.begin is called only once in setup - Q is updated. I need to call server.begin after every connectToWifi call?

No not server.begin()  thats ok as it is - please give infos to your schematic of the network. Are there clients connected to the UNO (server.begin indicates that) and the UNO acts himself as client to anothrer server. Or is the UNO the only server ? . Its hard to work with bread crumbs (what libs are you using, is String clas called, what is attached to the UNO, ... The more info the more precise the answers you get

UNO functions as a server. One client very rarely (once/week) connects to it, sends 1 character as a command, then UNO responds with client.print("response"); (always 1 line only). Very simple logic: UNO reads some GPIO and put it into response.

I had 1.2.4 version on the NINA, now upgraded to 1.3.0. Also added the status = WiFi.disconnect(); line to the connectToWifi routine. Keeping my fingers crossed.


text:
Vin pin vs USB vs Barrel connector: Wemos D1 R2
@Majenko says in the leading (19 Upvote) answer here not to use VIN and USB socket at the same time.

You must never ever connect VIN to a power source and connect the USB socket. That can destroy the USB port in your computer. There is zero back-powering protection on [LoLin v3 board] board.

I need to do diagnostics on my Wemos (LOLIN) D1 R2 V2.1.0 while it's connected via 9-12V barrel jack and the Vin pin connected to an L9110H H-bridge as an output (bridge input).
Does the Wemos (LOLIN) D1 R2 V2.1.0 (ESP8266) work like this as well? Would I be able to run diagnosics with Serial through my USB socket while running this setup?

So that means, that you only have one power source: the USB port, right?

Power source is from the barrel jack (9-12V) @chrisl

The D1 R2 uses the same power supply arrangement as the Arduino Uno (albeit with a better switching regulator for the 5V instead of the Arduino's basic linear regulator).
So it should be safe to use both the USB and the barrel jack at the same time.
The NodeMCU doesn't include a 5V regulator and doesn't have the power switching circuitry of the Uno / D1 R2, and thus is a completely different arrangement.

I have a "Uno-like" Wemos D1 R2 (almost said R2 D2 then! :) ) which also powers a NRF24 board connected to it. When I power it from the barrel connector the Wemos Wifi works but the NRF24 board won't communicate. When I power via USB everything works fine. Perhaps the onboard switching regulator you speak of does not have enough grunt to power both but a USB source does?


text:
Arduino Nano 33 BLE work with its Bluetooth and GPS synchronously?
I am using Arduino nano 33 Sense BLE in which I want GPS to run and display its location . The GPS module which I am using is Adafruit GPS. I want both Bluetooth and GPS to run synchronously. But only one of them shows output. I have tried Adafruit-GPS library with the Hardware Serial but it shows the GPS location not the Bluetooth working.
I also checked the code individually both are working well.I have used the example of Adafruit-GPS library->GPS_HardwareSerial_Parsing and ArduinoBLE library->LED , these codes both work individually well but when I have combined them and tried to make it run only the GPS shows its location the bluetooth seems to be not working.Below is the combined code:
#include <Adafruit_GPS.h>
#include <ArduinoBLE.h>

// what's the name of the hardware serial port?
#define GPSSerial Serial1
// Connect to the GPS on the hardware port
Adafruit_GPS GPS(&GPSSerial);
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO false
uint32_t timer = millis();

BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
const int ledPin = LED_BUILTIN; // pin to use for the LED

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

 // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate

  pinMode(ledPin, OUTPUT);
  BLE.setLocalName("LED");
  BLE.setAdvertisedService(ledService);
  // add the characteristic to the service
  ledService.addCharacteristic(switchCharacteristic);
  // add service
  BLE.addService(ledService);
  // set the initial value for the characeristic:
  switchCharacteristic.writeValue(0);
  // start advertising
  BLE.advertise();

  delay(1000);
}

void loop()
{
  char c = GPS.read();

  BLEDevice central = BLE.central();

  if (GPS.newNMEAreceived()) {
   // Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
    if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
      return; // we can fail to parse a sentence in which case we should just wait for another
  }

 if (timer > millis()) timer = millis();

//BLE code to connect to bluetooth

  // if a central is connected to peripheral:
  if (central) {
    Serial.print("Connected to central: ");
    // print the central's MAC address:
    Serial.println(central.address());
    // while the central is still connected to peripheral:
    while (central.connected()) {
      // if the remote device wrote to the characteristic,
      // use the value to control the LED:
      if (switchCharacteristic.written()) {
        if (switchCharacteristic.value()) {   // any value other than 0
          Serial.println("LED on");
          digitalWrite(ledPin, HIGH);         // will turn the LED on
        } else {                              // a 0 value
          Serial.println(F("LED off"));
          digitalWrite(ledPin, LOW);          // will turn the LED off
        }
      }
    }
    // when the central disconnects, print it out:
    Serial.print(F("Disconnected from central: "));
    Serial.println(central.address());
  }

//GPS to print latitude and longitude
  // approximately every 5 seconds or so, print out the current stats
  if (millis() - timer > 5000) {
    timer = millis(); // reset the timer
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", ");
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
    }
  }

}

return; // we can fail to parse skips the rest of the loop()


text:
Trying to move servo motor via 3 buttons

I am having some difficulties in trying to make my servo motor move to a specific angle based on the button pressed.
For example, having the motor start at 0 degrees and then having it move to 180 when the 3rd button is pressed, have it return to 0 degrees when the first button is pressed, and have it go to 90 degrees when the second button is pressed, etc, etc.
I can't tell if I am going about this all wrong or not with my code, so if anyone could provide some assistance with this it would be a great help
EDIT: Added the wiring as a just in case
#include <Servo.h>

Servo myservo;
int angle = 0;
int anglestep = 10;

#define FIRST 2 // pin 2 is connected to 1st floor button
#define SECOND 3 // pin 3 is connected to 2nd floor button
#define THIRD 4 // pin 4 is connected to 3rd floor button
#define SIGNAL 10

void setup()
{
Serial.begin(9600);
myservo.attach(10);
myservo.write(angle);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(4,INPUT_PULLUP);
Serial.println("Lift/Descend");
}

void loop()
{
while (digitalRead(FIRST) == LOW)
    {
    if (angle > 0 && angle <= 90) //2to1
        {
        angle = angle - anglestep;
            if (angle < 0)
            {
            angle = 0;
            }
            else
            {
            myservo.write(angle);
            Serial.print("Moved to: ");
            Serial.print(angle);
            Serial.println(" degree");
            }
        }
    else if (angle > 90 && angle <= 180) //3to1
    {
        angle = angle - anglestep;
            if (angle < 0)
            {
            angle = 0;
            }
            else
            {
            myservo.write(angle);
            Serial.print("Moved to: ");
            Serial.print(angle);
            Serial.println(" degree");
            }
    }
    else //1on1
    {
        angle = 0;
    }

}
while (digitalRead(SECOND) == LOW)
    {
    if (angle > 90 && angle <= 180) //3to2
        {
        angle = angle - anglestep;
        if (angle > 90)
            {
            angle = 90;
            }
        else
        {
        myservo.write(angle);
        Serial.print("Moved to: ");
        Serial.print(angle);
        Serial.println(" degree");
        }
    }
    else if (angle > 0 && angle < 90) //1to2
        {
        angle = angle + anglestep;
        if (angle < 90)
            {
            angle = 90;
            }
        else
        {
        myservo.write(angle);
        Serial.print("Moved to: ");
        Serial.print(angle);
        Serial.println(" degree");
        }
    }
    else
    {//2on2//
    angle = 90;
    }
}

while (digitalRead(THIRD) == LOW)
{
    if (angle > 0 && angle <= 90) //1to3
    {
        angle = angle + anglestep;
        if (angle > 180)
            {
            angle = 180;
            }
        else
        {
        myservo.write(angle);
        Serial.print("Moved to: ");
        Serial.print(angle);
        Serial.println(" degree");
        }
    }
    else if (angle > 90 && angle < 180)
    {//2to3
        angle = angle + anglestep;
        if (angle > 180)
            {
            angle = 180;
            }
        else
        {
        myservo.write(angle);
        Serial.print("Moved to: ");
        Serial.print(angle);
        Serial.println(" degree");
        }
    }
    else
        {
        angle = 180;
        }
    }
}

And what is the problem? You forgot to describe, what  does not work as expected and how.

You are really overthinking things there. A servo will move to an angle if you just give it the final angle to move to. You don't need to nudge it to the final angle by visiting every angle in between, and you don't need to know what angle it's at currently.
You can simply do:
if (digitalRead(FIRST) == LOW) {
    myservo.write(0);
}

if (digitalRead(SECOND) == LOW) {
    myservo.write(90);
}

if (digitalRead(THIRD) == LOW) {
    myservo.write(180);
}

However if you wanted to slow the movement down, which would entail moving the servo in smaller steps, I would separate out the current angle and positioning from the buttons, which would set a desired angle.  Something more like:
static uint8_t desiredAngle = 0;
static uint8_t currentAngle = 0;
static uint32_t timestamp = millis();

// Choose a new desired angle
if (digitalRead(FIRST) == LOW) {
    desiredAngle = 0;
}

if (digitalRead(SECOND) == LOW) {
    desiredAngle = 90;
}

if (digitalRead(THIRD) == LOW) {
    desiredAngle = 180;
}

// Every 10ms "tick" the servo towards the desired
// angle by 1 degree
if (millis() - timestamp >= 10) {
    timestamp = millis();
    if (desiredAngle > currentAngle) {
        currentAngle++;
        myservo.write(currentAngle);
    } else if (desiredAngle < currentAngle) {
        currentAngle--;
        myservo.write(currentAngle);
    }
}


text:
How to fix memory-leak code in ESP8266/NodeMCU caused by string concenation?
I have following code in loop() in NodeMCU.
This part is before setup():
String serial_data_read = "";   // for incoming serial string data
String serial_data = "";   // for incoming serial string data

This part is in loop():
if ((last_weight_time < millis() - 1000)) {
   last_weight_time = millis();
   serial_data_read = "";
   Serial.print("P");
   while(Serial.available()) {
      character = Serial.read();
      serial_data_read.concat(character);
   }
   serial_data = serial_data_read;
}

I don't understand C programming that much, but I think it has something to do with memory leaking and eventually running out of memory. It runs for around 20 minutes and then just stops. When I manually restart NodeMCU it runs again fine.
I would be very grateful for any help, how to rewrite my code so it doesn't leak memory. Thank you very much.

Just don't use String, but char arrays instead

https://majenko.co.uk/blog/evils-arduino-strings

Re if ((last_weight_time < millis() - 1000)): This can fail badly if last_weight_time is right before a millis() rollover event. Use instead the idiom if (millis() - last_weight_time > 1000), which is rollover safe.

To write code that will not cause memory leak, you need to understand of where and what caused the memory leak first. The memory leak in this particular case is caused by the line
serial_data_read.concat(character);

When you instantiate a String object with String serial_data_read = "", Arduino String class create a memory allocation using dynamic memory allocation in the heap, and since your initialised it with "", it therefore create a minimum size of allocation. This is all good if you know how to the dynamic memory is created and how it going to be used.
The problem started when you start doing String concatenation with the line serial_data_read.concat(character), the original allocation for your global variable serial_data_read is no longer have enough space for the concatenated variable, so it create a temporary variable in the heap and do the concatenation, and then eventually put the result back to this newly allocated memory for serial_data_read on the heap, leaving a hole at the heap for the original serial_data_read variable (and the temp variable).
What make this worst is that this is happening for each iteration every 16 iterations(see Edgar Bonet's comment below) of the while loop. Theoretically the old serial_data_read prior the concatenation should be free-up at some point (e.g. if your while loop is within a function, the part of the heap might be free-up at the exit of the function), it however does not necessary be the case because your newly created serial_data_read stay on top of piles of to-be-free-up memory that blocking the free up(think of a piece of cheese with a lot of holes on it), so the heap memory get less and less at each iteration.
Short term fix - do not do String concatenation in a loop
String class is not always evil if you know what's going on and how to use it. One of the quick fix for your problem is simply do not do String concatenation within a loop. And if you are using it within a function, keep it local. This will minimise the heap fragmentation.
if ((last_weight_time < millis() - 1000)) {
   last_weight_time = millis();
   if (Serial.available() > 0) {
      String serial_data_read = Serial.readStringUntil('\n');
   }
}

BTW, you can add ESP.getFreeHeap() in your loop() to check if there is still memory leak.
Long term fix - Don't use String class
For a better fix, and especially for some one new to the programming or C/C++, do not use String class and learn how to use c string and array. Here is the version without using String class.
length = 80;
char buffer[length] = {0};
if ((last_weight_time < millis() - 1000)) {
   last_weight_time = millis();
   while(Serial.available()) {
      Serial.readBytesUntil('\n', buffer, length);
   }
}

Other resources to learn about
https://www.cplusplus.com/reference/cstring/ all the functions for c string and array manipulation to replace Arduino String class.
https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

Re “[heap allocation] is happening for each iteration of the while loop”: on the ESP8266, it happens once every 16 iterations, as the allocated size is grown by multiples of 16 bytes. Re “if your while loop is within a function, the part of the heap might be free-up at the exit of the function”: when concat() can't manage to grow the string in place, it will allocate a new buffer, copy the existing data, and free the previous buffer right away. This doesn't invalidate your point about the risk of memory fragmentation though.

The short answer is, don't use the String class at all. You need to read up on using C strings (which are simply null-terminated arrays of characters. There are C library functions for manipulating C strings. You'll want to avoid printf, scanf, and related functions, as the library that supports those is quite large
The basic idea is to use statically allocated C strings as buffers. Figure out the largest number of characters you need to store, and create a static array of characters at least one character larger (for the terminating null) and use that to collect the output you are building.

printf() and friends don't have much impact on - and cause no fragmentation of - data space. They take up more code-space than Serial.print() but most of us don't write sketches that push the code space limit.

@Duncan C - Thank you very much for your answer. Can you please add code example how my code would have to be rewritten ?

What @JRobert said. Avoiding String is good advice, avoiding printf, scanf is bad advice in this case; they don't cause issues with the heap and that's what this problem is.

Also the ESP8266 has plenty of code space (flash) even on a small variant. On small AVR chips the printf family use a cut-down version with floating point support removed to save space.

Good to know about the cut-down version of printf/scanf. To the OP: Disregard that part of my answer

even with printf support for floating point turn on via linker flags, it only impact the flash memory size by adding about 1500 bytes, it does not affect the use of SRAM.

SafeString is a great way to go.. only one instance of each SafeString can ever exist, and u can declare the length of each SafeString..


text:
Arduino Hardlid Unlocker
I am trying to build a unlocker on my hardlid for my ute. I have replaced the manual unlocking mechanism with 2 of these https://www.jaycar.com.au/slave-door-lock-actuator/p/LR8813.
Now my code below works sometimes and I cannot work out why. The way the code should work is

Press Unlock Button (Count increments)
Press Unlock Button again
When count = 2 turn relay on for 4 seconds then turn off
reset count to 0
If time between presses is longer than 10 seconds reset count to 0

Basic diagram below. Please note the push button is actually wired to a relay which is triggered by the car unlock remote and the LED is the actuators.

This is my code
int switchPin = 2; // choose the input pin (for a pushbutton)
int relayPin = 4; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
int counter = 0;
int currentState = 0;
int previousState = 0;
bool lockOn = false;

unsigned long currentMillis = 0;
unsigned long previousMillis = 0;

unsigned long LockcurrentMillis = 0;
unsigned long LockpreviousMillis = 0;

const long interval = 10000;
const long Lockinterval = 4000;

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

  pinMode(switchPin, INPUT); // declare pushbutton as input
  pinMode(relayPin, OUTPUT); // declare pushbutton as input

  Serial.println("Ready");
  Serial.print("IP address: ");

}

void loop() {

  currentMillis = millis();
  LockcurrentMillis = millis();
/*
  Serial.print("Current ");
  Serial.print(currentMillis);
  Serial.print(" | Previous ");
  Serial.println(previousMillis);
    //Serial.println(lockOn);

  Serial.print("Lock Current ");
  Serial.print(LockcurrentMillis);
  Serial.print(" | Lock Previous ");
  Serial.println(LockpreviousMillis);
  */
  if (lockOn == true){

    if (LockcurrentMillis - LockpreviousMillis >= Lockinterval) {
      // save the last time you blinked the LED
      LockpreviousMillis = LockcurrentMillis;
      digitalWrite(relayPin, LOW); // turn relayPin off
      lockOn = false;
      Serial.println("relay off");
    }
  }

  val = digitalRead(switchPin); // read input value
  if (val == HIGH) { // check if the input is HIGH (button released)
    currentState = 1;
  }
  else {
    currentState = 0;
  }
  if (currentState != previousState) {
    if (currentState == 1) {
      counter = counter + 1;
      previousMillis = currentMillis;   //reset timer
      Serial.println(counter);
    }
  }
  if (counter == 2) {
    counter = 0;
    digitalWrite(relayPin, HIGH); // turn relayPin on
    //delay(4000);
    //digitalWrite(relayPin, LOW); // turn relayPin off
    lockOn = true;
          LockpreviousMillis = LockcurrentMillis;

    Serial.println("relay on");
  }

  previousState = currentState;
  //delay(250);
  if (currentMillis - previousMillis >= interval) {
    // save the last time you presse the button
    previousMillis = currentMillis;
    //LockpreviousMillis = LockcurrentMillis;
    //if (counter >= 1) {
    Serial.println("Took too long reset count");
    counter = 0;
    lockOn = false;
    //}
  }
}

Any Help would be highly appreciated
Thanks

First thing: debounce the button.

Button debounce library: https://github.com/thomasfredericks/Bounce2

What's a ute?  Have you ever seen the movie "My Cousin Vinnie"?

@Delta_G, lol .... i was thinking the same thing

A ute :) ... https://edge.pxcrush.net/std/car/cil/mxu89gdw4v7sjx3evj47ec64d.jpg?width=900

Your circuit drawing seems very wrong, but it is not helpful since, as
you say, it doesn't represent the real circuit. Please, add a proper
diagram of the actual circuit.
As for your reliability problem, I did not dig into the logic of the
code you posted, but I suspect it may be caused by the lack of
debouncing. You could add you own debouncing code but, for the sake
of simplicity, I suggest you instead use a ready-made library, like
Bounce2.
For the kind of program you are trying to write, I find that the logic
becomes way easier to grasp if you think think of it as a finite state
machine. This is program construct based on the idea that the
system can be in any of a predefined set of possible states, and that
its behavior and the possible state transitions depend on what
particular state it is in. In this specific case, I would use three
states:

In the LOCKED state, the lid is locked and you need to press the
button twice in order to unlock it. Once you press the button once,
it transitions to the WAITING state.
In the WAITING state, the lid is still locked, but the first
button press has already been registered. If you press the button
again, the system transitions to the UNLOCKED state. If not,
after a timeout it transitions back to LOCKED.
In the UNLOCKED state the lid is unlocked. After another timeout it
transitions back to the LOCKED state.

Once you have this logic written down, it can be translated into code in
a very straightforward way:
#include <Bounce2.h>

const uint8_t  switch_pin = 2;
const uint8_t  relay_pin  = 4;
const uint32_t wait_interval = 10000;  // 10 s
const uint32_t lock_interval =  4000;  //  4 s

Bounce button;

void setup() {
    button.attach(switch_pin, INPUT_PULLUP);
    pinMode(relay_pin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Ready.");
}

void loop() {
    static enum { LOCKED, WAITING, UNLOCKED } state = LOCKED;
    static uint32_t last_change;  // not used in the LOCKED state

    button.update();
    uint32_t now = millis();
    switch (state) {
    case LOCKED:
        if (button.fell()) {
            Serial.println(F("Waiting for second button press."));
            state = WAITING;
            last_change = now;
        }
        break;
    case WAITING:
        if (button.fell()) {
            Serial.println(F("Unlocking."));
            digitalWrite(relay_pin, HIGH);
            state = UNLOCKED;
            last_change = now;
        } else if (now - last_change >= wait_interval) {
            Serial.println(F("Wait time out."));
            state = LOCKED;
        }
        break;
    case UNLOCKED:
        if (now - last_change >= lock_interval) {
            Serial.println(F("Locking."));
            digitalWrite(relay_pin, LOW);
            state = LOCKED;
        }
        break;
    }
}

Thank you Edgar. You code certainly looks much easier to read and follow. I will try you code now and report back.
Thanks Again

This works perfectly! I update schematic also. thanks


text:
guidance on Mikrobus NFC tag and connecting to arduino
I've recently purchased an NFC tag reader from MikroE and ive been a little lost on connecting the reader to my arduino board.
I've also been looking online for a library that i could use for this device, and have found little to nothing, though i maybe looking in the wrong place. If you could provide any guidance to the matter please respond.
any help would be much appreciated.
link to the tag: https://www.mikroe.com/nfc-tag-click

There is link on the mikroe.com website to a PDF that describes your circuit board: https://download.mikroe.com/documents/add-on-boards/click/nfc-tag/nfc-tag-click-manual-v100.pdf  The PDF tells you to go to https://libstock.mikroe.com for code samples.

To find an Arduino library for a device, you can search for the term combination
Arduino github <devicename>

because most libraries are hosted on github. The devicename here means the chip on the product, not the product itself. You won't find much for "Mikrobus NFC", but when you search for the chip on it - the  M24SR64 - you can find some promising results.
For example this library, which looks good to me. It was used for this blog article, which is where I found it (though that is a german site. I just wanted to link as reference for the german speakers). It has some examples, that show the usage of the library.

In general: Sometimes there might be no ready to use library for a chip or product to use with Arduino. In that case you need to write that code yourself. Let's take this product as example. It uses the I2C interface and the seller also links to the datasheet of the used chip. In the datasheet you can read, how the chip is used, including the communication protocol, that is imposes on the I2C interface. You could then write the corresponding I2C code using the Wire library.
Fortunate for you there already is a library, so you can first try that.


text:
Arduino Project Interrupt Error?
I have a project to be made i.e. water Billing System using RFID(Mfrc522) on Arduino NANO.
There is one difficulty that I haven't been able to overcome. I hope someone could help me out.
Project flow:

water or any liquid flows through the sensor and quantity of water gets recorded
now according to quantity of water flown there is price decided
this price needs to be deducted by swiping rfid card
issue:
i haven't been able to control interrupts
my program calculates the water flown
required:
edit code such that it as soon as water flows through it, it calculates and ask user to swipe card and as user swipes a amount deductes and process continues.

if not clear please ask and help me out
#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9          // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN);
String tagUID = "10 90 70 38";  // String to store UID of tag. Change it with your tag's UID
int bal =1000;

byte statusLed    = 13;
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

unsigned long oldTime;

void setup()
{

  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;
  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  Serial.begin(9600);    // Initialize serial communications with the PC
  while (!Serial);
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
}

/**
 * Main program loop
 */
void loop()
{

   if((millis() - oldTime) > 2000)    // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);

    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();

    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;

    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;

    unsigned int frac;

    // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space

    // Print the cumulative total of litres flowed since starting
    Serial.print("Output Liquid Quantity: ");
    Serial.print(totalMilliLitres);
    Serial.println("mL");
    Serial.print("\t");       // Print tab space
    Serial.print(totalMilliLitres/1000);
    Serial.print("L");
    rfid();

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

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

  Serial.println("In Rfid Loop");
  delay(3000);
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
        return;
      }
      // Select one of the cards
      if ( ! mfrc522.PICC_ReadCardSerial()) {
        return;
      }
  //Reading from the card
      String tag = "";
      for (byte j = 0; j < mfrc522.uid.size; j++)
      {
        tag.concat(String(mfrc522.uid.uidByte[j] < 0x10 ? " 0" : " "));
        tag.concat(String(mfrc522.uid.uidByte[j], HEX));
      }
      tag.toUpperCase();
       if (tag.substring(1) == tagUID)
      {
        bal=bal-20;
        delay(100);
        if(bal>=30)
        {
          Serial.println(bal);
          Serial.println("YOUR BALANCE");
          delay(400);

          // Reset the pulse counter so we can start incrementing again
          //pulseCount = 0;

          // Enable the interrupt again now that we've finished sending output
          //attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
        }
       else
        {
          Serial.println("INSUFFICIENT BALANCE PLEASE RECHARGE");
         }
        delay(100);

      }
      else
      {
        Serial.println("WRONG CARD ENTERED");

       }
}

And what is your actual problem with the interrupts? "haven't been able to control interrupts" is not a good problem description. Was did you expect your code to do and what did it actually do instead?

You have the interrupts detached for most of the time.  If you want to use the interrupt you need to have it attached.  Instead of detaching for all of loop, only detach for a very short time, make a copy of the pulseCount variable, and then turn interrupts back on.  Then use the copy you made in the calculations.

You are disabling interrupts for way too long. Interrupts are meant for
handling time-critical tasks that cannot wait for a full loop iteration.
If you ever disable them, it should be for a time as short as possible.
In your case, you only need to disable interrupts while accessing the
pulseCount variable, as this variable is shared between the ISR and
the regular code. This can be done in a very short "critical section" as
follows:
noInterrupts();
uint8_t pulseCountCopy = pulseCount;
pulseCount = 0;
interrupts();

In the rest of the loop you then only access pulseCountCopy. Note that
you don't really need to reset pulseCount to zero. Since it is
incremented using the rules of modular arithmetic, you can just compute
the differences between consecutive readings. You will get the correct
result even when it rolls over. This makes the critical section even
shorter:
static byte oldPulseCount;
noInterrupts();
uint8_t pulseCountCopy = pulseCount;
interrupts();
uint8_t pulseIncrement = pulseCountCopy - oldPulseCount;
oldPulseCount = pulseCountCopy;

And then note that, since reading a single byte is an atomic operation
(a single machine instruction), you do not even need to disable
interrupts al all! However, if the flow can ever be larger than
0.47 L/s, then 8 bits will not be enough for pulseCount. You
will have to use a 16-bit variable (uint16_t) and keep the critical
section.
As a side note, you are calling millis() several times per loop
iteration. This is bad practice, as there is no guarantee that you will
always get the same value, so you end up with your timing calculations
being somewhat sloppy. You should rather do something like
uint32_t now = millis();

at the start of loop(), and use the same value for the whole
iteration.
Another side note: you are differentiating the pulse count in order to
get a flow rate, then integrating the flow rate to get a total volume.
This is completely useless. The pulse count is already a measure of the
total volume. Basic arithmetics shows you that the calibration factor is
4.5 (pulses/s) / (L/min) = 270 pulses/L
Your calculations will be less sloppy (having less accumulated error) if
you just divide the total pulse count by 270 to get the total volume in
liters.


text:
CH340G Uploading problem
I've tried to copy CH340G from other schematics and existing Arduino Uno Clones...
Searched online & StackExchange but no good :/ My problem is almost the same as this one
Here is my schematic

I can read & send data from the serial monitor

OS: Win 10 64 Bit
USB Driver: 3.5.2019.1

Upload Options:

Arduino IDE version: 1.8.12
Board: Arduino Uno (also tired nano & nano old bootloader options)

What I've tried:

With & without the driver
Rebooted the computer
Tried different ports
Different cables
In case of IC not working, I've desoldered IC from working UNO
Changed RX, TX vice versa
Without R1 & R2
Different capacitors on C6 and C3
Buuut results are always the same as below

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

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

         Using Port                    : COM3
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xf3

avrdude done.  Thank you.

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

I appreciate any help, idea, suggestion
Regards

Have you installed the bootloader?

Yes @Majenko, I've burned bootloader and uploaded code via ISP. I can communicate with it already, but can not upload code via USB

What else is on the RESET line?

If you can use the CH340 as a Serial-USB bridge (Serial.print and Serial.read work) but you cannot upload a sketch without using a programmer, the bootloader (or fuses) are bad for some reason.

@KIIV, 10k resistor like Uno and Nano (5V and reset signals)

@DataFiddler, How we're uploading program to Uno in your scenario? We're only hitting the upload button, not upload with the programmer. Can you explain this, please?

There is what you have to check: 1) toggling DTR should reset the MCU 2) check if the clock is running properly (upload blink sketch and check the frequency) - then reupload the bootloader

Btw, on newer arduino boards there is also fast diode between RESET and Vcc power rail to suppress voltage spike to 10V - as it might be enough to enter High voltage serial programming mode.

The schematic is totally working. My mistake was after burning bootloader, I was uploading code via ISP. If you upload code via ISP, you're removing bootloader.
Thank you everyone who helped me to I wasn't mistaken at schematic and else...


text:
RFID RC522 Serial Communication converting problem
I am new to the RFID Scene and Serial communication as well.
So I am trying to use the RC522 RFID module and I wrote in block 22 - 0x36 which is 6. I want to write a code where I take whatever is in block 22 - 0x36, convert it into a float - 6.00 and then do some addition or deduction for example 6.00-2.5 = 3.5 and then I want to rewrite the value of 3.5 into that same sector but of course, convert it back to HEX ASCII - 33 2e 35. I've tried quite hard to find the solution online but couldn't.
  So is this possible to do?
Thanks.

yes, it is possible to do ... do you have any real questions?

why do you need to convert to hex?  ... 0x36, 54, '6', 0b00110110 are all the same data ... the only difference is the human readable form ... it is like uno, one, ichi, eins all being the same thing

can you provide a simple code then? I am having a problem with substracting the byte buffer with some number.

It is unclear to me, what exactly you have and what you want to do with it. Do you have a character buffer with hex in ASCII format? And then you wanto to make some float calculation to it? Please provide the code, that you already have. That would greatly help, since here the types of the variables are really important

@tsotniuspious, no ... you provide the code that you are having problems with and someone will check it over and provide advice

To be clear, what you want stored is ascii codes right?  So it's not hex or bin or dec, everything in computers is stored as binary.  If you store 0x12 in one slot and store 18 in another slot and compare then they are the same and in both cases 0b00010010 is what actually got stored.


text:
nrf24L01 with/without antenna
the function write in nrf24LO1 (without antenna) works perfectly
but in nrf24LO1 (with antenna) not works. why?!
the code
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>

 RF24 radio(7,8);
 const byte address[6] = "00001";
void setup() {
  radio.begin();
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_HIGH);
  radio.setCRCLength(RF24_CRC_8);
  radio.stopListening();
  Serial.begin(9600);
}

void loop() {
  const char text[] = "example";
  if(radio.write(&text,sizeof(text))) //<==problem here
    Serial.println("ok");
  Serial.println(text);
  delay(1000);
}

nrf24l01 with antenna :

nrf24l01 without antenna :

In what way does it "not works"?

not works : Not send data , function write return false with 0 data sending to recever

what makes you believe that the two modules are interchangeable? .. btw, both of the modules have an antenna

They actually are interchangeable. But your program has an error radio.write expects a pointer to some data. An array and a pointer are pretty much the same in C (this is a bit oversimplified but sufficient in this case). But you are passing a pointer to an array (the address of the array), which in turn would be a pointer to a pointer to data. Your program may or may not work just because of pure luck and the current flow of aether. Remove the apmersand in that method call.

Are you communicating between identical modules? How far apart are the modules?

Try increasing the distance between the two. Or use RF24_PA_LOW during testing.


text:
how can i download a file with http from sd card using the SdFat.h
I use the Arduino IDE 1.8.10 and the esp8266 core 2.7.1 and the Wemos-D1 with SD Card Module
For the SD Card i use the SdFat.h library, because i need to set the timestamp for the uploaded file.
I am not a expert to arduino programming.
Currently my scetcch can this:
List Files from the SD Card on a webpage and show Filename and Filesize. Working.
Delete selected File. Working.
My Goal:
Download a File over http from the SD Card to my Windows PC.
Upload a File over http to SD Card with Timestamp from the original File.
With sd.h a simple Upload is working. But the Timestamp is every time 1.1.2020 01:00
My Includes:
#include "SdFat.h"
#include "sdios.h"
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266mDNS.h>

My Old code with sd.h for download:
void SD_file_download(String filename){
  if (SD_present) {
    File download = SD.open(filename);
    if (download) {
      filename.replace(" ","_");
      int last_slash = filename.lastIndexOf('/') + 1;
      filename = filename.substring(last_slash);
      server.sendHeader("Content-Type", "text/text");
      server.sendHeader("Content-Disposition", "attachment; filename="+filename);
      server.sendHeader("Connection", "close");
      server.streamFile(download, "application/octet-stream");
      download.close();
    } else del = "2";
  } else ReportSDNotPresent();
}

My new Code for Download with SdFat.h:
void SD_file_download(String filename){
SdFile dl_file;
  if (SD_present) {
    if (dl_file.open(filename.c_str())) {
      filename.replace(" ","_");
      int last_slash = filename.lastIndexOf('/') + 1;
      filename = filename.substring(last_slash);
      server.sendHeader("Content-Type", "text/text");
      server.sendHeader("Content-Disposition", "attachment; filename="+filename);
      server.sendHeader("Connection", "close");
        size_t sent = server.streamFile(dl_file, "application/octet-stream");
      dl_file.close();
    } else del = "2";
  } else ReportSDNotPresent();
}

If i compile i get many errors
In file included from F:\Eigene Dateien\Arduino\esp_fileserver05\esp_fileserver05.ino:14:0:

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h: In instantiation of 'size_t esp8266webserver::ESP8266WebServerTemplate<ServerType>::streamFile(T&, const String&, HTTPMethod) [with T = sdfat::SdFile; ServerType = WiFiServer; size_t = unsigned int]':

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:177:50:   required from 'size_t esp8266webserver::ESP8266WebServerTemplate<ServerType>::streamFile(T&, const String&) [with T = sdfat::SdFile; ServerType = WiFiServer; size_t = unsigned int]'

F:\Eigene Dateien\Arduino\esp_fileserver05\esp_fileserver05.ino:211:60:   required from here

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:185:58: error: 'class sdfat::SdFile' has no member named 'size'

 _streamFileCore(file.size(), file.name(), contentType);

                                                      ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:185:58: error: 'class sdfat::SdFile' has no member named 'name'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:187:21: error: no matching function for call to 'WiFiClient::write(sdfat::SdFile&)'

   contentLength = _currentClient.write(file);

                 ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WebServer\src/ESP8266WebServer.h:187:21: note: candidates are:

In file included from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/ESP8266WiFi.h:39:0,

             from F:\Eigene Dateien\Arduino\esp_fileserver05\esp_fileserver05.ino:12:

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:59:18: note: virtual size_t WiFiClient::write(uint8_t)

virtual size_t write(uint8_t) override;

              ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:59:18: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'uint8_t {aka unsigned char}'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:60:18: note: virtual size_t WiFiClient::write(const uint8_t*, size_t)

virtual size_t write(const uint8_t *buf, size_t size) override;

              ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:60:18: note:   candidate expects 2 arguments, 1 provided

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:62:10: note: size_t WiFiClient::write(Stream&)

size_t write(Stream& stream);

      ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:62:10: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'Stream&'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:65:10: note: size_t WiFiClient::write(Stream&, size_t)

size_t write(Stream& stream, size_t unitSize) __attribute__ ((deprecated));

      ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\libraries\ESP8266WiFi\src/WiFiClient.h:65:10: note:   candidate expects 2 arguments, 1 provided

In file included from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Stream.h:26:0,

             from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/HardwareSerial.h:32,

             from C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Arduino.h:245,

             from sketch\esp_fileserver05.ino.cpp:1:

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:76:23: note: size_t Print::write(int8_t)

     inline size_t write(int8_t c) { return write((uint8_t) c); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:76:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'int8_t {aka signed char}'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:75:23: note: size_t Print::write(char)

     inline size_t write(char c) { return write((uint8_t) c); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:75:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'char'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:73:23: note: size_t Print::write(long unsigned int)

     inline size_t write(unsigned long t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:73:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'long unsigned int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:72:23: note: size_t Print::write(long int)

     inline size_t write(long t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:72:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'long int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:71:23: note: size_t Print::write(unsigned int)

     inline size_t write(unsigned int t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:71:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'unsigned int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:70:23: note: size_t Print::write(int)

     inline size_t write(int t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:70:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:69:23: note: size_t Print::write(short unsigned int)

     inline size_t write(unsigned short t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:69:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'short unsigned int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:68:23: note: size_t Print::write(short int)

     inline size_t write(short t) { return write((uint8_t)t); }

                   ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:68:23: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'short int'

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:64:16: note: size_t Print::write(const char*, size_t)

     size_t write(const char *buffer, size_t size) {

            ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:64:16: note:   candidate expects 2 arguments, 1 provided

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:58:16: note: size_t Print::write(const char*)

     size_t write(const char *str) {

            ^

C:\Users\pl\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.1\cores\esp8266/Print.h:58:16: note:   no known conversion for argument 1 from 'sdfat::SdFile' to 'const char*'

exit status 1
Fehler beim Kompilieren für das Board LOLIN(WEMOS) D1 R2 & mini.

i can't use te line:File download = SD.open(filename); with sdfat.h because i get a compiler error "reference to 'File' is ambiguous"
The problem is this line: size_t sent = server.streamFile(file, "application/octet-stream");
How can i solve this problem?
Thank you for Help...

You got your naming backwards: “download” means “transfer from some remote host to the local system”, whereas “upload” is from the local system to a remote host. From the point of view of your sketch, the board it runs on (the Wemos) is the local system. The Windows PC is the remote host.

No, this is not the problem. With another library sd.h the download and upload works fine. But sd.h can not write timestamps to uploaded files. Therefore i must use the sdfat.h library. Upload means from pc to Wemos SD Card. Download means from Wemos SD Card to PC

Re “Upload means from pc to Wemos SD Card”: no, it doesn't, unless you are talking from the perspective of the PC (you are writing software for the PC). “Upload” means “send to the network”; “download” means “receive from the network”. Whatever your PC is uploading is a download on the Wemos.

you are right... if i see it from another perspective. But it does not solve the coding problem.

The ESP8266WebServer library is written to use SD.h. If you want it to use a different SD library you will have to re-write that library to use it.


text:
NodeMCU Power Draw and charging Circuitry
I am planning to build a small wireless keyboard, around 5 buttons and 1 rotary encoder, that will connect via WiFi to my Spotify account. For this project, I was looking at the Node MCU for the board.
I could not find online how much of a battery I will need for this project. I read somewhere that it can draw up to 200mA, so, if I use 4 of these batteries and run them through a 3V3 regulator, i should have 20.000mAh, so it should be able to be powered on for at least 100 hours, right? But it will actually be more, as it does not draw 200mA consistently, right?
Should this work? Do you have any other suggestions? Maybe some different batteries?
Also, how should I go about to make it so that it can have an USB C port that can charge the batteries while it is still in use? Sorry if this question is stupid, this is my first real project.
I thought the easiest, cheapest and dumbest solution was to simply try and fit in a regular 28.000mAh power bank and charge the NodeMCU via USB. Is this a decent idea?

The average power draw would be very dependent on what your NodeMCU does. My experience is that, with the typical IoT applications I use them for (checking and responding to incoming messages, checking buttons or sensors, occasionally sending small amounts of data), the NodeMCU will typically not use more than about 15-20mA on average. This is without putting it in a sleep mode. Your application does not sound very different, unless it requires continuous Wifi traffic. My advice is to measure the power draw and base the battery capacity on that.

NodeMCU could take up to 180mA when connecting to WiFi, and the esp8266 operated at 3.0-3.6v. you need to make sure that the power supply could provide steady voltage at the sudden surge of current, in many of the early esp8266 dev board design, this was one of the problem that the sudden surge of the current cause voltage drop to below 3.0v even for very short period of time.

When selecting a voltage regulator for battery-powered application, you need to pay attention to quiescent current, the regular that you linked to has a quiescent current of 2-3mA, meaning that even your NodeMCU is in sleep mode, the regulator itself will drow 2-3mA.

The regulator that you referred to also has quite a big drop-out voltage (it requires 4.5v input to provide steady 3.3v output). This means that you need two batteries in serial, and this will complicate your charging circuit design. The best is to loop for LDO (Low Dropout) regulator that is designed for battery-power application, it typically have a dropout voltage of around 200-300mV.


text:
HC-05 TX,RX divider rule
I'm using the HC-05 Bluetooth module but I'm confused about the TX,RX pins.
I want to know when should I connect the RX to a divider circuit to convert 5v to 3.3v.
Because while searching, I saw both of the following:

either RX is connected to TX of the UNO and TX is connected to RX of the UNO without a divider circuit.
or RX is connected to a divider circuit and then connected to any digital pin , TX is connected to any digital pin as well.

So can you give me a thought about both the situations?
my thought is that only digital pins needs a divider rule, but the TX,RX pins can be connected directly and operates without any problems but if so, then what's the difference between both??
Note that I'm using HC-05 to turn on a LED.
Hope to see some good explanation that suits a new Arduino learner.
Thank you..

You need a logic level translator of some form (such as a resistive divider) if the Arduino runs at 5V. If it's a 3.3V Arduino then you don't need one since the logic levels will match.
You connect to the TX and RX pins (or TX1/RX1 etc) of the Arduino if you want to use a hardware UART (Serial, Serial1, etc). You connect to any pins you like (with certain exceptions for the Mega) if you use SoftwareSerial instead of a hardware UART.

While you should use a voltage divider on the Arduino TX --> BT RX signal, you honestly don't need to. Many people, including myself, have used HC-05s without voltage dividers and haven't let "the magic smoke" out of the device. Adding a voltage divider may, though, may increase the lifespan of the HC-05.


text:
Chance light intensity in a pwm pin using LDR using Arduino UNO
I am using proteus and Arduino software to simulate my circuit. What I need to do, is to have an LDR in my Arduino uno. When light intensity increases in my LDR, I need another LED which is connected to a PWM pin to react to this change in light intensity. The more light LDR detects I need my LED to get dimmer and vice versa.
I have uploaded my circuit picture. The potential probe that I have connected to LDR works fine, the more light there is, the higher voltage it has (ranged from 0 to 5v) but on the other side, my LED does not work properly. If LDR detects little light. my LED is turned on, surprisingly with no current passing the ammeter, when light intensity is less than some threshold, my LED starts blinking! again, no current passing through the ammeter! and the voltmeter always varies between 0 and 4.9 (voltmeter on my LED), it never has a value between 0 and 4.9, it seems it acts digitally, while I have used analogWrite. By the way, I mention again that I need my LED pin to have PWM.This is my code in Arduino:
void setup() {
Serial.begin(9600);
pinMode(A0,INPUT);
pinMode(10,OUTPUT);
}

void loop() {

int sensorValue = analogRead(A0);
Serial.println(sensorValue);

analogWrite(10,sensorValue/4);

delay(200);
}

By the way, I know the way I have coded, it means that LED follows the torch, and the more light intensity LDR feels, the brighter LED gets, I need it to be vice versa but I also did not know how to use it.
And finally, a minor question:
what does the  Serial.println() function do? I mean it must print it's content somewhere, but where? This feature would be useful for debugging, but I don't know how to see its printed value. I should also say that my code is a modified version of analogReadSerial example.
Thanks.

upvote for asking about the serial.print() ... it prints to the serial port ... you can view the output using the serial monitor in the arduino IDE ... you can also use any other serial terminal program such as PuTTY

@jsotola Hello.Thanks for your comment. It worked about printing issue, however I still have my main issue. I don't know how to upvote your comment, it only has a flag icon on it.

@jsotola By the way, I don't know why it only worked once. I mean it pooped up for the first time, but later times, when I tried to print it, didn't pop up :|

Welcome to the wonderful world of simulation. I'll bet if you did it with real hardware your results would be very very different.

@Majenko How is that possible? You mean it's IDE's fault and my board and code is perfectly ok?

I mean simulation is only an approximation, and Arduino simulation is notoriously bad.

It'd be better to use oscilloscope for watching PWM signal on the LED pin. It's hard to measure something even in real life if you don't have meter that supports measuring duty cycle or so.


text:
Does toCharArray prevent a String being created on the heap?
I know it's bad to use Strings due to the memory problems that can occur.
I've tried to remove all instances of strings from my code.
But I'm not sure about this line:
http.getString().toCharArray(ipAddressBuffer, lengthOfIPAddress);

Is calling toCharArray() enough to prevent memory problems? Or is there a string still being created on the heap?
If it's still created on the heap, how can I modify the code so it only deals with cstrings?
Here's my code:
void setIPAddress(char* ipAddressBuffer){
  HTTPClient http;
  http.begin("http://bot.whatismyipaddress.com/"); //Only allowed to call once per 5 mins.
  http.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36");
  int httpCode = http.GET();
  if (httpCode > 0) {
    http.getString().toCharArray(ipAddressBuffer, lengthOfIPAddress);
  }
  else {
    Serial.println("Error on HTTP request");
  }
  http.end();
}

I'm using the HTTPClient.h library btw.

BTW: Which HTTPClient library? I know one which allows for HttpClient objects, not for HTTPClient

The return value of getString allocates and the deletes a char array in heap for a temporary String object.
For ESP8266HTTPClient and ESP32 HTTPClient library you can use writeToStream or getStream()to read the response without using String class with getString(), where stream is WiFiClient& stream = client.getStream();
getStream, returns the underlying WiFiClient. You can read the data with classic while (stream.available()) { char c = stream.read; ... }
writeToStream copies the data to a stream. My StreamLib library has a stream wrapper over a char array. It is called CStringBuilder.

One caveat to your answer: I read in the ArduinoJson documentation that if you do client.getStream() you bypass the chunked transfer encoding code and that for that case you must fall back to HTTP1.0 using useHTTP10(true). Did you encounter that, and is that something you could incorporate in your answer?

Or would writeToStream(Stream * stream), which getString() uses internally be a good idea?

@hansmbakker my StreamLib has ChunkedStreamReader. see the ReadChunkedJson example. StreamLib is in the Library Manager

http.getString() creates a temporary Arduino String object and fills text into dynamic memory on the heap. Calling the method .toCharArraycopies this text to a char array, wherever you defined it.
Immediately after that, the temporary String gets out of scope and the text on the heap is deleted again.