text:
ESP8266 not responding after random intervals of time
4th Update:
I bought an ESP32 (the successor to ESP8266) and am getting the same problem. I used the same code except used the Wifi.h library instead, also removed the ESP8266WiFiGratuitous.h code. I added an LED flash at the start of the loop and can confirm the LED stops flashing, so I can confirm the loop() stops running.
This makes me think it must be something to do with my WIFI network.
3rd update:
I've removed all the code and instead uploaded a simple onboard LED blink sketch. The LED has been blinking for over 24 hrs which leads me to think there is something in the wifi code that is making the software crash.
2nd update:
I've even tried resetting the board at the start of the loop() body, every 10 mins, using the millisDelay.h library, calling this method to reset:
void(* resetFunc) (void) = 0;

but that doesn't help either. The loop() method seems to completey stop running.
Update:
I've added experimental::ESP8266WiFiGratuitous::stationKeepAliveSetIntervalMs(); but am still failing to get a response after 1hr, with about 15 requests made in that hour.
I have this code which works on my ESP8266:
    #include <ESP8266WiFi.h>
    #include <ESP8266WiFiGratuitous.h>

    const size_t input_buffer_length = 256;

    const char* ssid = "iiNetC2DAD7";
    const char* wifiPassword = "aM9PrxcbtkS";
    const char* passwordToOpenDoor = "/87"; //password should begin with a slash

    const int doorPin = 5;
    const int buzzerPin = 4;
    const int toneDuration = 700;

    int numOfRequests = 0;

    WiFiServer server(301); //Pick any port number you like
    WiFiClient client;

    void setup() {
      Serial.begin(115200);
      delay(10);
      Serial.println(WiFi.localIP());

      pinMode(LED_BUILTIN, OUTPUT);
      digitalWrite(LED_BUILTIN, 1);

      pinMode(doorPin, OUTPUT);
      digitalWrite(doorPin, 0);

      pinMode(buzzerPin, OUTPUT);
      digitalWrite(buzzerPin, 0);

      Serial.println();
      Serial.print("Connecting to ");
      Serial.println(ssid);

      WiFi.begin(ssid, wifiPassword);

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

      experimental::ESP8266WiFiGratuitous::stationKeepAliveSetIntervalMs();

      server.begin();
      Serial.println("Server started.");
      Serial.println(WiFi.localIP());
    }

    void loop() {
      client = server.available();
      if (!client) {
        return;
      }

      while(!client.available()){
        delay(1);
      }

      char request[input_buffer_length];
      client.readBytesUntil('\r', request, input_buffer_length);
      Serial.println(request);

      if(strstr(request, passwordToOpenDoor)) {//Is password correct?
        GenerateResponse("Password is correct");
        OpenDoor();
        CorrectPasswordSound();
      }
      //Got a GET request and it wasn't the favicon.ico request, must have been a bad password:
      else if (!strstr(request, "favicon.ico")) {
        GenerateResponse("Password is incorrect.");
      }
    }

    void OpenDoor() {
      digitalWrite(LED_BUILTIN, 0); //flash the onboard LED to help during testing.
      digitalWrite(doorPin, 1);
      delay(500);
      digitalWrite(LED_BUILTIN, 1);
      digitalWrite(doorPin, 0);
    }

    void GenerateResponse(const char *text) {
      Serial.println(text);
      client.print(
          "HTTP/1.1 200 OK\r\n"
          "Content-Type: text/html\r\n"
          "\r\n"
          "<!DOCTYPE HTML>\r\n"
          "\r\n"
          "

"
      );
      client.print(text);
      client.print("

Num of requests: ");
      client.print(++numOfRequests);
      client.print("
\r\n");
      client.flush();
    }

    void CorrectPasswordSound() {
      //Play 1700, 1800, 1900Hz
      for(int i = 17; i < 20; i++){
        int frequency = i * 100;
        tone(buzzerPin, frequency);
        delay(toneDuration);
        noTone(buzzerPin);
      }
    }

However, after a random amount of time, the software crashes and the device won't respond to HTTP requests anymore.

I've tested this by printing to the serial monitor every loop. It seems as though it crashes and the loop() function stops running since it stops printing to the monitor.

I noticed that it'll still reply to pings.

It won't reconnect after restarting the router, I need to press the reset button on the ESP8266 to get it to start working again.

I've tested it by sending an HTTP Get request every 5 mins for many hours (using a C# console app). Sometimes it failed after 45 mins, sometimes 7 hours.

I initially thought it was because I was using String objects, but after getting an answer to this question and testing it out with only C-strings, I still have the same problem.

I've been sending HTTP Get requests using Chrome on my phone and laptop, as well as the .NET Framework class System.Net.Http.HttpClient.

Spec:

Board: AI-Thinker ESP8266MOD
IDE: Arduino 1.8.12
ESP8266 Boards version = 2.6.3
IDE Settings:

I've tried resetting the connection using:
server.stop();
delay(1000);
server.begin();

Then this:
ESP.reset();

Then after those 2 didn't work, this:
ESP.restart();

Resetting it frequently did nothing.
Is there anything in my code that stands out?
If there's nothing wrong withe code, then maybe my only option is to hard reset the board every 30 mins some how.

Your code looks okay. A couple of suggestions. 1) move the WiFiClient client; into the loop() and can combined with server.available(); to form a one liner like this WiFiClient client = server.available();. 2) the only time that the loop() seems to stop running will be the time where if (!client) { return;} which is actually when server is not available. I would suggest instead of simply return, you print something out before the return to see if that's what happening.

@hcheung but then client won't be recognised in the GenerateResponse() function.

Oh, you are right. I guess it has to be at Global then.

make the WiFiClient a local variable. pass it to function as reference. void GenerateResponse(WiFiClient& client, const char *text) {

@Juraj will that provide any benefits?

in past there was a problem with a memory leak if the client object was reused

Have you ruled out any hardware issues, like marginal power supplies, bad connections,  etc? What does enabling the doorPin do?

@StarCat I'm going to try just turning the LED on and off, no wifi or anything and see what happens. The doorPin just turns on a relay.

I don't know if this is your problem, but I'll leave it here because it is certainly a potential bug.
This code in loop:
  while(!client.available()){
    delay(1);
  }

can cause a deadlock if you have a client that drops or doesn't talk.  Turn that around and let the loop keep running.
boolean haveClient = false;

void loop() {
  client = server.available();
  if (client) {
    haveClient = true;
  } else {
    haveClient = false;
  }

  if(haveClient && client.available()){

     // The rest of your loop where you read
     //  from the client goes inside here.

That way if you get a client and then available keeps returning false you can at least keep checking for a client.
This may not be and is not intended to be a code solution. This is probably not the best way to code what I'm trying to say.  I don't know if server.available will keep giving you back the same client or if it is going to cut you off to call that again before the client disconnects.  There may be some method in there to check the connection.  Either way, that's not the point.  The point is to never capture your code into a locked up while loop.  That is always asking for a deadlock.  It's bad practice except for cases like fatal errors where you truly want to lock the thing up.  Let the loop keep looping.  Use if statements to decide which parts get run when.
If you want to check that this is where you are locking up, put some sort of output before and after that while loop.  Print something or turn a light on before and off after.  That way you can tell if this is the spot you're locking up.

After implementing your change, it's worked the longest it ever has, over 7hrs!

Thanks to Delta_G for pointing me in the right direction.
The trick was to not get stuck in the loop() function, ie. no while loops.
The problem was that after you run client = server.available();, the client needs some time before client.available() returns true, which is what the while loop is for, however, for some reason, the client would lose its connection every now and then and client.available() would never return true, in which case you get stuck in the while loop. You need to give it a second chance and let the process start again.
By delaying about 50ms, it seems to be enough time for the client to establish a connection, and if it doesn't, it loops and tries again so quickly that it appears as though the client always gets the connection and the code works fine.
Here's the working code:
void loop() {
  WiFiClient client = server.available();

  if(client){
    delay(50);
    if(client.available()) {
        //rest of code here
    }
}

I'm facing the similar problem especially when the WIFI signal is weak. The connection drop prematurely, end up the software execution is stuck within the while(!client.available()) loop.
A fail-safe timer can be implemented to get out from this loop as follow:
  unsigned int u32FailSafeTimer = 3000;   /*Set 3s timeout*/
  while(!client.available())
  {
    u32FailSafeTimer--;
    delay(1);   /*pause for 1ms*/
    if (0 == u32FailSafeTimer)   /*Fail-safe timer elapsed, get out from unexpected error*/
    {
      Serial.printf("timeout (RSSI: %d dBm)\n\n", WiFi.RSSI());
      client.flush();   /*Kill and prepare for next session*/
      return;
    }
  }

I will take a SWAG and say it sounds like the watchdog may be getting you. I was getting similar problems but nothing to do with WiFi or anything like that. I determined that when it got stuck in a loop it would sit for a while and then crash. I was able to determine (guess) something was timing out and since the external hardware did not reset and yet it would run setup() again the processor was resetting itself. It would hang with some things appearing to work. After I dug down into it I found that I had to release my code to allow the watchdog to be reset by the internal ESP software. I based this on some information I found about the maximum time allowed for the delay() function. Hopefully this helps.

This will be the "server unreachable after a while" problem, which is solved solved by sending gratuitous ARP requests. In the esp8266 Arduino core 2.7 they added functions for this. The main function is experimental::ESP8266WiFiGratuitous::stationKeepAliveSetIntervalMs();. Include <#include "ESP8266WiFiGratuitous.h>
Notes:

You don't know if your loop stops. It doesn't print anything if no client can reach it.
remove the flush() after readBytesUntil(). it doesn't do what you think it does.

You means stationKeepAliveSetIntervalMs? or it is at somewhere else in the source code?

sorry it changed on the way from PR to release. yes stationKeepAliveSetIntervalMs

How do I read the password in the request URL without using readBytesUntil()?

Juraj is suggesting to delete the client.flush(), not the client.readBytesUntil().

Sorry! Misread the answer.

@DavidKlempfner, in setup() after successful connection to AP

Where do I put this line of code?:
WiFi.stationKeepAliveSetIntervalMs(interval).I tried "WiFi.stationKeepAliveSetIntervalMs(1000);" after "WiFi.begin(ssid, wifiPassword);" but got
'class ESP8266WiFiClass' has no member named 'stationKeepAliveSetIntervalMs'

and did you update to 2.7.0?

Yeah I updated the board manager ESP8266 to 2.7. Are there any extra #includes I need to add?

sorry I updated the answer. it is still an experimental function

@Juraj please see my updated question. I added that code but it still failed after 1hr.

@Juraj I tested again, it worked for 5.5hrs and did 82 requests before it timed out.


text:
Connecting a time on/off circuit and my adafruit neopixel light strip
I'm new to programming and hardware so be gentle.
I've used this tutorial Arduino Ultra Mega Timers to create a time on/off circuit.
I'm attempting to connect some adafruit neopixel led strips to a 5v relay. I've been trying to read up on how exactly relays work and what wires would go from GND, 5V, and Dout to NO and NC but I've hit a brick wall because all of the schematics I've found show light bulbs connecting to the relays. A detailed explanation of exactly how to connect the LED strip to the relay and why it works would be great as I am trying to learn!

You cannot find a tutorial for controlling neopixel strips with a relay, because that just does not make any sense. You don't need a relay to control the strip.
The Neopixels consist not only of the LEDs themselves, but also of one LED driver chip per LED (WS2811 and it's siblings). These driver chips control the LEDs based on the data, that you send through the data pin. Actually one Neopixel LED consists of 3 LEDs inside a single package, one LED each for the colors red, green and blue (so that you can create all the other colors with a combination of them). The driver chip controlls the brightness of all three colors.
Thus you only need to connect your 5V power source to the strip (5V and ground) - Be sure to connect the power lines directly to your power supply, so that the LED current does not flow through the Arduino (because that can fry your Arduino) - and the data In pin of the strip to a fitting digital pin of the Arduino. You can use the Adafruit Neopixel library or the FastLED library for controlling them.
To turn the strip on, you set the needed pixels to the wanted color and then call the show method of the library (which sends out the color data through the data pin). To turn the strip off, you simply clear all the pixels (the libraries have extra functions for that), which basically means setting all pixel to black (red, green and blue components all zero).
So forget about the relay and just use the strip directly. Also Adafruit has a very good guide on how to use the Neopixels.

Hey,
I really appreciate your reply Chris. I understand what you are saying. But I've already programmed the strip to blink for a certain time, at the intensity I want, and the color that I want. The problem is I want the Neopixels to turn on at a specific time during the day which is the reason why I'm using the RTC and the relay. Are you saying the RTC and the relay aren't necessary at all to do what I want? I want the LEDs turn on at 12 and off 2 on their own. If the relay isn't necessary to do what I asked, would you mind pointing me in in the right direction?
Thanks!

You need the RTC for time keeping. But you don't need the relay. The tutorial, that you linked, uses both, but that doesn't mean, that you always need to use them together. Divide the functionalities of your project up: 1. You want to keep and know the time; for that you need the RTC. 2. You want to control the LED strip (here you only need the strip). And the code should just put both things together.

You can still follow the tutorial, but instead of the code for turning the relay on and off, you should insert the code for turning your LEDs on and off. The relay is just not needed there; it has no function in your project.

source: Stack Exchange

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

sort: votes


text:
How to converte EPOCH time into time and date on Arduino?
I have a question on how to convert EPOCH timestamps, which I receive as char*, into DD.MM.YYYY and HH:MM:SS format separately?
Here is more information on my Arduino project: The Arduino is receiving through an ESP8266 module three different EPOCH timestamps from the OpenWeatherMap API for sunrise, sunset and the current date. I want these 3 pieces of information to be displayed on a 1,3" OLED display, the date in DD.MM.YYYY and the other two timestamps in HH:MM format.
I was looking in several time libraries like TimeLib and RTC for a solution, but I wasn't able to find one.
That's my code fragment on receiving the timestamps:
DynamicJsonBuffer jsonBuffer(4096);
JsonObject& root = jsonBuffer.parseObject(client);

const char* date = root["dt"];
const char* sunrise = root["sys"]["sunrise"];
const char* sunset = root["sys"]["sunset"];

How to convert those timestamps?

Epoch are seconds from 1970-01-01. Get it from JSON as unsigned long. They are a number in the returned JSON (no ")
from https://openweathermap.org/ doc:
"sys":{"country":"JP","sunrise":1369769524,"sunset":1369821049},

to convert it to string with TimeLib.h:
#include <TimeLib.h>
#include <ArduinoJson.h>

void setup() {

  Serial.begin(115200);

  const char* json = "{\"country\":\"JP\",\"sunrise\":1369769524,\"sunset\":1369821049}";

  DynamicJsonBuffer jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(json);

  unsigned long t = root["sunrise"];

  char buff[32];
  sprintf(buff, "%02d.%02d.%02d %02d:%02d:%02d", day(t), month(t), year(t), hour(t), minute(t), second(t));

  Serial.println(buff);
}

void loop() {
}

note you might need to divide the timestamp by 1000 if it includes ms, like JS's Dates for example.

@dandavis, I took the sample JSON from the openweathermap site

For sure, I'm just pointing out that there's two "epoc"s to be aware of from web services, in general.

For this example, it's not necessary to divide by 1000. Thank you very much for the help :)

@Juraj I have one more question to this topic: Can TimeLib also convert EPOCH timestamps to day names?(Monday, etc.)

dayStr(weekday(t)); or dayShortStr http://playground.arduino.cc/code/time

I'm was having a similar challenge with my custom Wifi library m_wifi..cpp for the ESP32 ( see here )
After reading and googling I ended up coding the solution below:
ESP32Time rtc(0);
long int epochTime;
...

rtc.setTime( epochTime  );
Serial.println( rtc.getDateTime(true) );

can it be used on a non esp32 Arduino as in the question?

yes. you can replicate the code to use on other than ESP32. Just need to find the compatible library for your specific MCU.

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


text:
Ability to connect 2 or more w5500 Modules and deal with them as objects
I wish to create a rudimentary ethernet in/out - switch/hub where I can (sort of) daisy chain my boards. (I don't wish to use a ethernet switch/router/hub)

One port would be acting as server
The other would be acting as a client
(and forward any messages received on the first port after some processing/modification)

I am using an STM32 Bluepill with 2 Mini w5500 Modules (adafruit) connected via SPI. Nothing else is connected to SPI. All the other GPIOs are connected to relay drivers.
I use the Ethernet library. I have made sure they are connected to different CS pins and I have tried to assign Ethernet.init(); before doing anything with specific Ethernet modules but that keeps disconnecting and is working very unreliably.
I understand that some modification in the library might be needed (I, by no means could figure out how and what).
References:
https://forum.arduino.cc/t/2-network-shields/111509
https://forum.arduino.cc/t/connect-multiple-ethernet-shields-to-arduino-uno-using-spi/284008/16
But no one seems to have gotten it to work. Please help.

it is not possible with the Arduino Ethernet library

Thanks @Juraj, I realized the same. Is there another way or has anyone modified this library to achieve this?

I would use a hub or Ethernet splitters. Ethernet wiring is a bus, but for practical reasons the bus was moved into hubs and  with that the topology looks like a start topology.  Then switches added optimized packets routing. https://en.wikipedia.org/wiki/Ethernet#Evolution

@Juraj Alright then, I feel it would be worth someone's while to modify the library for this, but for now I am convinced that the Arduino ethernet library isn't going to do it.


text:
How do you convert a formatted print statement into a string variable?
I'm using the following routine to print the current time on the com port. I would like to capture this as a string so I can display it using ePaper.
    void printLocalTime()
    {
      time_t rawtime;
      struct tm timeinfo;
      if(!getLocalTime(&timeinfo))
      {
        Serial.println("Failed to obtain time");
       return;
      }
     Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
    }

produces -

Saturday, May 12 2018 12:18:27

That's clever. How are you getting Serial.println to respond to that format?

try CStringBuilder from StreamLib

@Majenko, it is ESP32 Arduino core package

Oh, so nothing to do with Arduino then. It's non-standard functionality.

Personally I'd use sprintf() to place things into a char array - though you'd have to do the textual formatting (day names, etc) yourself.  Or the standard C library functions may work for you (or they may not).

It probably overloads to call strftime (http://www.cplusplus.com/reference/ctime/strftime/)

To achieve what you want you probably want to use the "string format time" function strftime (docs). You would write the result in a character buffer, which you can also print directly without having to convert it to String object.
So, the following code should work:
void printLocalTime()
{
  time_t rawtime;
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo))
  {
    Serial.println("Failed to obtain time");
   return;
  }
  char timeStringBuff[50]; //50 chars should be enough
  strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo);
  //print like "const char*"
  Serial.println(timeStringBuff);

  //Optional: Construct String object
  String asString(timeStringBuff);
}

The overload for Serial.print also does this exact same thing:
size_t Print::print(struct tm * timeinfo, const char * format)
{
    const char * f = format;
    if(!f){
        f = "%c";
    }
    char buf[64];
    size_t written = strftime(buf, 64, f, timeinfo);
    print(buf);
    return written;
}

Perfect, except  '&time_info);' should be &timeinfo);, Just what I was aiming for and missing.

@SimonMarkham corrected, thanks for spotting.


text:
Inconsistent results when reading input looking for spike patterns
I'm writing a library that will interface with a control unit on a refrigerator compressor pump (QDZH35G). One of the features of the control unit is that it can detect what problems it's encountering and report them via a flashing LED. Operational errors will cause the LED to flash a number of times. The number of flashes depends on what kind of operational error was recorded. Each flash will last 1/4 of a second. After the actual number of flashes, there will be a delay with no flashes, so that the sequence for each error recording is repeated every 4 seconds.
My goal (as it relates to this post) is to monitor the signal from the diagnostic lead and report what error the control unit has detected. I used my oscilloscope to monitor the diagnostic port, here are some pictures of that (fault codes 1 and 4):

(more photos here)
So the signal looked simple and clean enough. But just to be sure, I wanted to make sure Arduino was seeing it as my Oscilloscope was. I hooked the diagnostic port up to my Arduino digital port 8 and analog pin A0 (I wanted to monitor both to decide what would be the best to use for this) and uploaded the following sketch:
#define DIGITAL_DIAGNOSTIC_PIN 8
#define ANALOG_DIAGNOSTIC_PIN A0

void setup() {
  Serial.begin(9600);
  pinMode(DIGITAL_DIAGNOSTIC_PIN, INPUT);

  Serial.println("millis,analogRead,digitalRead");
}

void loop() {
  Serial.print(millis());
  Serial.print(",");
  int currentAnalogValue = analogRead(ANALOG_DIAGNOSTIC_PIN);
  int currentDigitalValue = digitalRead(DIGITAL_DIAGNOSTIC_PIN);

  Serial.print(currentAnalogValue);
  Serial.print(",");
  // Bump binary 1 to int 1023, to make it easier to see in the logs
  Serial.print(currentDigitalValue == 0 ? 0 : 1023);

  Serial.println();
}

And oddly enough, the signal Arduino was giving back seemed to be all over the place for both the digital and analog pins. While there was some pattern visible it's a pretty big mess.
Then I used CoolTerm to monitor and export the serial data into a CSV file which I then imported into a Google Docs spreadsheet (here) to create some graphs. I captured 10+ seconds in each of the following scenarios:

No fault/control (zero blinks)
Fault #1 (1 blink then 4-second pause)
Fault #3 (3x 0.25 second blinks separated by 0.25 seconds, then 4-second pause)

Here are the screenshots of the graphs (also in the Google spreadsheet doc and imgur gallery):

Finally - The question..
Why is the data seen by Arduino seem considerably less stable than that seen by my oscilloscope? I know that when reading a signal from some sensors (pressure transducer, thermocouple, etc) you get much more accurate and consistent results by averaging the last n readings, but the diagnostic voltage port isn't really a "sensor", it's just a voltage reading.
Additionally, it's reading from a pump powered by a DC desktop power unit, which has very stable voltages (I only say this because I know the voltage affects the level of the peaks from the diagnostic port).

Comments have been moved to chat; please do not continue the discussion here. Before posting a comment below this one, please review the purposes of comments. Comments that do not request clarification or suggest improvements usually belong as an answer, on [meta], or in [chat]. Comments continuing discussion may be removed.

A lot of comments, but no answers posted. If the situation is resolved please post an answer. @Justin - you can answer your own question if you think you have the solution. Thanks!

Where to start?  Your O'scope photo shows about 3 vertical divisions when the fault line is 'high'. The labelling at the bottom shows '5.00V', which I'm going to assume means '5V per vertical division'.  This would mean your 'high' voltage is about 15V, much too high for the 5V max input either analog or digital input on the Mega.
So, you need something like a 3:1 voltage divider just to start with.  The 'bottom' resistor on the divider will set the output impedance driving your analog (and digital) inputs, so this needs to be reasonably low (10K or so).
Before connecting the voltage divider to the Mega, look at the voltage divider output with your O'scope to verify the 'high' voltages are <= 5V. Then, and only then, connect the voltage divider output to the Mega with the O'scope still connected.  If you see a big drop in the 'high' voltage, it means the Mega input impedance is loading down the voltage divider output, which means the voltage divider resistor values are too high - choose lower values (same ratio of course).
The specs for the Arduino Mega show a top speed of about 10,000 readings per sec, so your loop speed should be OK as long as adjacent millisec printouts are different.
I suspect you will find that the Mega analog input is loading down the signal.

The analog input of the Mega is basically a 14 pF capacitor. Not really a high load.

Yeah, that sounds right, but even 14pf can form a low-pass filter if the output impedance of the 'diagnostic lead' is high enough.  For sure something is causing a >5V signal to read like 2V.  That's why I wanted to make sure the OP kept the O'scope connected when they connected the diagnostic lead to the Arduino analog input.

The OP's data does not look like a low-pass filtered version of the expected signal. Besides, for an RC filter to have a large effect at this time scale you would need R ≥ 200 ms / 14 pF = 14 GΩ.

I think you mean 14MegOhms?   200x10-3/14x10-9 = 14x10+6.  I don't know about you, but 14MegOhm output impedance wouldn't be out of the question for a 'diagnostic lead'.  I'm not sure how you came to the conclusion that the reported values "don't look like a low-pass output" - maybe you could elaborate on that?

I mean 14 GΩ: a picofarad is 1e-12 F. Even 14 MΩ would be unusually high for a diagnostic port. Keep in mind that a typical scope has an input impedance of 1 MΩ. Re “don't look like a low-pass output“: here is what a square wave through an RC filter looks like. Nothing like the collection of spikes in the OP's data.

Yep - you are right - I misread the link showing the prefix meanings.  However, when I looked a the OP's graph, I came to the conclusion that the 'spikes' are the instantaneous readings from the A/D converter.  If so, then drawing a line from 'spike' to 'spike' would give the analog equivalent


text:
Read byte and time into EEPROM, then display with a comma between the time and the value?
I have bytes of natural numbers 1-60 coming in at random times:
Example of send data
// Uno send

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

  int integersToSend[] = {1, 22, 30, 4, 50};
  for (int i = 0; i < 5; i++)
  {
    Serial.print(integersToSend[i]);  // send as characters
    delay(1000);
  }
}

void loop() {}

I want to log the time (any time format) and what value was received into EEPROM:
#include <EEPROM.h>

const int timeRefreshDisplay = 30000;
const int EEPROM_SIZE = 100; // Define size of EEPROM available
int addr = 0; // EEPROM address pointer

unsigned long programStartTime;

void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600); // Initialize Serial1 for data input
  programStartTime = millis(); // Record program start time
}

void loop()
{
  if (Serial1.available())
  {
    int receivedData = Serial1.read();

    if (receivedData != 0 && receivedData <= 60)
    {
      byte receivedValue = receivedData; // Convert?

      // Calculate the timestamp based on program start time
      unsigned long currentTime = programStartTime + millis();

      // Store the received timestamp and value in EEPROM
      EEPROM.put(addr, currentTime);
      addr += sizeof(unsigned long);
      EEPROM.put(addr, receivedValue);
      addr += sizeof(int);
    }
  }

  if (millis() - programStartTime >= timeRefreshDisplay)
  {
    programStartTime = millis();
    displayEEPROMData();
  }
}

void displayEEPROMData() {
  // Display all positions stored in EEPROM
  Serial.println("EEPROM:");

  for (int i = 0; i < EEPROM_SIZE; i += sizeof(unsigned long) + sizeof(int)) {
    if (i >= EEPROM_SIZE) {
      i = 0; // Start reading from the beginning when reaching the end of EEPROM
    }

    unsigned long timestamp;
    int value;
    EEPROM.get(i, timestamp);
    EEPROM.get(i + sizeof(unsigned long), value);

    // Display position data with timestamp in HH:MM:SS format
    Serial.print(String(i / (sizeof(unsigned long) + sizeof(int)) + 1) + ": ");
    Serial.println(String(timestamp) + ", " + String(value));
  }
}

Serial monitor
EEPROM:
1: 17330, 22272
2: 101, 27943
3: 4143972352, 116
4: 0, 0
5: 0, 0
6: 0, 0
7: 0, 0
8: 0, 0
9: 0, 0
10: 0, 0
11: 0, 0
12: 0, 0
13: 0, 0
14: 0, 0
15: 0, 0
16: 0, 0
17: 0, 0

I'm not quite sure how it is reading data into EEPROM. That has to be where the issue is. I just don't know how to fix it. I tried clearing out the memory:
    #include <EEPROM.h>

    void setup() {
       // initialize the LED pin as an output.
       pinMode(13, OUTPUT);

       for (int i = 0 ; i < 22; i++) /*EEPROM.length()*/
          EEPROM.write(i, 0);

       // turn the LED on when we're done
       digitalWrite(13, HIGH);
    }

    void loop() {}

Serial monitor again
EEPROM:
1: 0, 0
2: 0, 0
3: 0, 0
4: 0, 4
5: 70, 1
6: 22, 3
7: 230, 2
8: 182, 4
9: 134, 50
10: 234, 49
11: 209, 50
12: 213, 50
13: 185, 51
14: 189, 48
15: 161, 52
16: 137, 53
17: 140, 48

I'm using a Leonardo to receive.

An EEPROM cell can tolerate only a limited number of write cycles. You should be very careful when writing to it continuously in the loop().
You are writing 2 associated data items to the EEPROM per cycle. It would be better to use a struct to pack the two items and do the write operation in one go using the put() method. For unpacking, use the get() method.

It could be that you have already damaged some EEPROM cells by exceeding the write cycle limit. You could start at say cell 100 instead of cell 0 to see if the results are more consistent. Hovever, don't allow the code to write endlessly to the EEPROM and remember that an unwritten to EEPROM cell is '1' filled.

My EEPROM library supports update which will only write if there is a change. Try using that. Also you can use FRAM and have unlimited R/W cycles.

This works.
#include <EEPROM.h>

const int EEPROM_SIZE = 100; // Define size of EEPROM available
int addr = 0; // EEPROM address pointer

unsigned long programStartTime;

void setup()
{
  Serial.begin(9600);
  while (!Serial);
    Serial1.begin(9600);

  programStartTime = millis(); // Record program start time

  // Initialize EEPROM data
  //  for (int i = 0; i < EEPROM_SIZE; i++) {
  //    EEPROM.write(i, 0);
  //  }
  displayEEPROMData();
}

void loop()
{
  if (Serial1.available())
  {
    int receivedData = Serial1.read();

    if (receivedData >= 1 && receivedData <= 60)
    {
      byte receivedValue = static_cast<byte>(receivedData); // Convert to byte

      // Calculate the timestamp based on program start time
      unsigned long currentTime = millis() - programStartTime;

      // Store the received timestamp and value in EEPROM
      EEPROM.put(addr, currentTime);
      addr += sizeof(currentTime);
      EEPROM.put(addr, receivedValue);
      addr += sizeof(receivedValue);

      displayEEPROMData();
    }
  }

  if (addr >= EEPROM_SIZE) {
    addr = 0; // Wrap around if the EEPROM is full
  }

}

void displayEEPROMData() {
  // Display all positions stored in EEPROM
  Serial.println("EEPROM:");

  for (int i = 0; i < EEPROM_SIZE; i += sizeof(unsigned long) + sizeof(byte)) {
    unsigned long timestamp;
    byte value;
    EEPROM.get(i, timestamp);
    EEPROM.get(i + sizeof(timestamp), value);

    // Display position data with timestamp in HH:MM:SS format
    Serial.print(String(i / (sizeof(unsigned long) + sizeof(byte)) + 1) + ": ");
    Serial.println(String(timestamp) + ", " + String(value));
  }
}

Well done, answering your own question, really. For future visitors including your future self in some weeks, you might extend your answer with some explanation what was wrong. Comparing source code shows the result, but not the way to it.

You appear to have another problem that you are sending integers (int datatype) from a Uno to the receiver. An int is represented as two bytes on the Uno. On the receiver you are getting individual bytes but making no attempt to collect pairs of these to reconstruct the original int.


text:
I get the following error when I typed the below code. " Stray'\302" in the programme .I tried to sort it but failed
#include <Keypad.h>

#include<LiquidCrystal.h>

#include<EEPROM.h>

LiquidCrystal liquid_crystal_display(9,8,7,6,5,4,);

char password[4];

char initial_password[4],new_password[4];

int i=0;

int relay_pin = 10;

char key_pressed=0;

const byte rows = 4;

const byte columns = 4;

char hexaKeys[rows][columns] = {

{'1','2','3','A'},

{'4','5','6','B'},

{'7','8','9','C'},

{'*','0','#','D'}

};

byte row_pins[rows] = {A0,A1,A2,A3};

byte column_pins[columns] = {A4,A5,3,2};

Keypad keypad_key = Keypad( makeKeymap(hexaKeys), row_pins, column_pins, rows, columns);

void setup()

{

  pinMode(relay_pin, OUTPUT);

  liquid_crystal_display.begin(16,2);

  liquid_crystal_display.print(" DIYhacking.com");

  liquid_crystal_display.setCursor(0,1);

  liquid_crystal_display.print("Electronic Lock ");

  delay(2000);

  liquid_crystal_display.clear();

  liquid_crystal_display.print("Enter Password");

  liquid_crystal_display.setCursor(0,1);

  initialpassword();

}

void loop()

{

  digitalWrite(relay_pin, HIGH);

  key_pressed = keypad_key.getKey();

  if(key_pressed=='#')

    change();

  if (key_pressed)

  {

    password[i++]=key_pressed;

    liquid_crystal_display.print(key_pressed);

      }

  if(i==4)

  {

    delay(200);

    for(int j=0;j<4;j++)

      initial_password[j]=EEPROM.read(j);

    if(!(strncmp(password, initial_password,4)))

    {

      liquid_crystal_display.clear();

      liquid_crystal_display.print("Pass Accepted");

      digitalWrite(relay_pin, LOW);

      delay(2000);

      liquid_crystal_display.setCursor(0,1);

      liquid_crystal_display.print("Pres # to change");

      delay(2000);

      liquid_crystal_display.clear();

      liquid_crystal_display.print("Enter Password:");

      liquid_crystal_display.setCursor(0,1);

      i=0;

    }

    else

    {

      digitalWrite(relay_pin, HIGH);

      liquid_crystal_display.clear();

      liquid_crystal_display.print("Wrong Password");

      liquid_crystal_display.setCursor(0,1);

      liquid_crystal_display.print("Pres # to Change");

      delay(2000);

      liquid_crystal_display.clear();

      liquid_crystal_display.print("Enter Password");

      liquid_crystal_display.setCursor(0,1);

      i=0;

    }

  }

}

void change()

{

  int j=0;

  liquid_crystal_display.clear();

  liquid_crystal_display.print("Current Password");

  liquid_crystal_display.setCursor(0,1);

  while(j<4)

  {

    char key=keypad_key.getKey();

    if(key)

    {

      new_password[j++]=key;

      liquid_crystal_display.print(key);

    }

    key=0;

  }

  delay(500);

  if((strncmp(new_password, initial_password, 4)))

  {

    liquid_crystal_display.clear();

    liquid_crystal_display.print("Wrong Password");

    liquid_crystal_display.setCursor(0,1);

    liquid_crystal_display.print("Try Again");

    delay(1000);

  }

  else

  {

    j=0;

    liquid_crystal_display.clear();

    liquid_crystal_display.print("New Password:");

    liquid_crystal_display.setCursor(0,1);

    while(j<4)

    {

      char key=keypad_key.getKey();

      if(key)

      {

        initial_password[j]=key;

        liquid_crystal_display.print(key);

        EEPROM.write(j,key);

        j++;

      }

    }

    liquid_crystal_display.print("Pass Changed");

    delay(1000);

  }

  liquid_crystal_display.clear();

  liquid_crystal_display.print("Enter Password");

  liquid_crystal_display.setCursor(0,1);

  key_pressed=0;

}

void initialpassword(){

  for(int j=0;j<4;j++)

    EEPROM.write(j, j+49);

  for(int j=0;j<4;j++)

    initial_password[j]=EEPROM.read(j);

}

https://majenko.co.uk/blog/common-arduino-errors-and-warnings

You should always include the full error message (which also describes the line, where the error happened) into your question. 2. Look at the declaration line of liquid_crystal_dysplay. There is a comma too much


text:
Powering 3 servo motors and Arduino Uno with one 9 V battery
I wish to power an Arduino Uno board AND 3 servo motors using a single 9 V battery.
I have connected the positive terminal of the 9 V battery to the VIN pin. The negative terminal of the battery is connected to the GND pin immediately following. This, I believe, powers the Arduino Uno board.
Next, I have connected the power wires of all 3 servo motors to the 5 V pin on the Arduino board ( using jumper wires and a  breadboard). Similarly, all the servo ground wires have been connected to the second GND pin in the 'POWER' set of pins on the Arduino Uno board. And finally, the 3 signal wires from the servos have been connected to the three PWM pins on the 'DIGITAL' row, exactly pins 9, 10 and 11. THE SERVOS ARE NOT OPERATED SIMULTANEOUSLY, THEY ARE BEING OPERATED ONE-BY-ONE (but the load is still attached to each of them, a couple of grams is all).
Since the servo motors operate between 4.8 V - 6 V, and I don't have any spare AA batteries to approximate a 6 V battery, I thought this could solve the problem.My question is, does this pose any problems for the board or devices, does this draw a higher current? Will it damage the Arduino Uno board or the servo motors or any of the individual pins?  Please let me know soon, thank you very much.

Do you have any of the specifications for any of the things you are connecting?

@IgnacioVazquez-Abrams. Servo motor specifications: Operating voltage: 4.8 - 6 V. Operating speed: 0.2s/60 deg (at 4.8 V), 0.16s/60 deg (at 6 V). Stall torque: 3.8 kgcm (at 4.8 V), 4.5 kgcm ( at 6 V). Temp range: 20 degC - 60 degC. Is this what you were asking for?

I don't think anything should get damaged; the regulator is rated for 1A, and even beefy servos don't draw more than 200mA when moving against heavy load. The problem is that your battery won't last long. Even the heavy-duty Li primary 9V batteries are under 1000mAh, and the actual capacity is heavily dependent on the discharge rate.
Why can't you use a rechargeable Li-ion pack with an appropriate step-up or step-down converter?

I do have a rechargeable 9V Li-ion battery. Are you talking about a DC-DC converter? Isn't the Arduino's voltage regulator enough? Can you please explain why you suggested that setup. Thank you.

I'm sorry, since my question wasn't clear on this point. The servos are not being operated simultaneously, they're being operated one-by-one. In such a case, wouldn't the battery last longer than otherwise? If so, could you explain why? Thank you.

The 5V regulator on the Arduino is a linear regulator, not a switching regulator. In any case, you probably won't damage anything. Just connect it up and see how long it lasts, and whether that's enough for you.

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


text:
Debugging with an ATtiny?
I have an ATtiny hooked up to two line scan modules. I'm sending digital signals to the line scan modules then receiving the analog output and storing it in an array. I have an if statement that will make the LED on the ATtiny programmer blink when the number are below a certain range (meaning that lens is covered).
Here is my code:
#include <SoftwareSerial.h>
const int rx=0;
const int tx=1;

SoftwareSerial mySerial(rx,tx);
int CLK = 2;
int SI = 1;
int Aout = A3;
int Aout1 = A2;

int LED = 0;

int pixelsArray[128];   //Array to hold the values of the individual pixles.
int pixelsArray1[128];

 void outputPixels()
{
  for(int j = 0; j < 128; j++)
  {
    digitalWrite(LED, LOW);

    if(pixelsArray[j] < 100)
    {
      digitalWrite(LED, HIGH);
      delay(500);
      digitalWrite(LED, LOW);
      delay(500);
    }
  }
}

The problem that I am having is that when I test my code with one line scan module it works just fine. You will notice that in the readPixels() I have the statement pixelsArray1[i]=analogRead(Aout1); commented out. However, when I try to use it with two the LED start blinking regardless of how much light is hitting the line scanner.
The strange thing is that EVEN when I comment out the digitalWrite(LED, HIGH); statement in the outputPixels() method...THE LED STILL BLINKS!!!
Since the ATtiny does not support URT and can't use the console in Arduino I have no idea how to debug this. Does anyone here have any clue what is wrong?
Here is the datasheets
ATtiny: http://www.atmel.com/Images/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
ATtiny Programmer: https://learn.sparkfun.com/tutorials/tiny-avr-programmer-hookup-guide/?_ga=1.59946280.467360091.1464906372

The ATtiny2313 has only 128 bytes of RAM. Your two pixel arrays, together, need 512 bytes. No way this can work.

Sorry I linked the wrong datasheet. I am using the ATtiny85 which has 512  bytes of RAM.

That's still not enough. Your arrays are eating all the RAM of the ATtiny85, thus corrupting the stack.

If I am reading the ATtiny datasheet correctly then I have a total of 512 bytes of RAM. Meaning that u should have enough space for two 128 arrays. What am I missing? Sorry if I'm being stupid, but I'm really outside of my field right now.

Your program needs RAM for storing all its globals (in the “data” and “bss” sections of the RAM), and the return addresses for the functions you call (“stack” section). You cannot allocate all the RAM to your arrays and expect it to work.

Since you do not have enough RAM for your arrays, something has to
give. A few options:

Do you really need the 10-bit precision of the ADC? If you can live
with 8 bits, then use 8-bit arrays (type uint8_t) and store only
the 8 most significant bits of each reading
(pixelsArray[i]=analogRead(Aout)>>2). This will make the arrays
half as big.
If you really need 10-bit precision, maybe you do not need 128-pixel
resolution? Then you could store only every other pixel. This will
also halve the array sizes.
If you do need both the full precision and the full resolution, then
you will have to pack the bits tight. You can pack up to 4 readings
in 5 bytes. But this will increase the complexity of your program.

Addendum: To declare the arrays as being made of 8-bit integers,
just replace
int pixelsArray[128];
int pixelsArray1[128];

by
uint8_t pixelsArray[128];
uint8_t pixelsArray1[128];

Here “uint8_t” means “unsigned 8-bit integer”, whereas “int” is a
regular integer, i.e. signed and, on the AVRs, 16-bits long.

These are pixels so I don't need a lot of precision, but how can I use 8-bit arrays? Do I just add the >> like you said or do I need to change it in the declaration? Also doesn't each integer take up 2 bytes?

@FortunaIwasaki: You have to change the declaration also. See the amended answer.

Thank you so much for your help, but could you also explain what you meant by "pack the bits tight"? How can you keep the same number of pixels and still store them as integers, yet use less space?

@FortunaIwasaki: By using bitwise operations, you can manage the storage at the bit- (instead of byte-) level. Then, you would allocate 10 bits per pixel, which amounts to 2560 bits (320 bytes) for the 256 pixels.

According to the Specs of the Attiny, this microcontroller only has 128 bytes of memory (RAM).
In the code you declare two arrays:
int pixelsArray[128];   //Array to hold the values of the individual pixles.
int pixelsArray1[128];

which will occuppy much more memory than the available on this microcontroller.
Try to reduce the size of the array. Each int entry occupies 2 bytes according to the link.

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


text:
Precise On/Off control for IR LED
My goal is to be able to send/receive IR messages in my own custom format and send messages ~10 bytes long. My message object will get serialized down to individual bits, which are transmitted by turning the IR LED on/off at specific timings of my choosing to represent logical ones and zeros. From what I've seen, an IR LED can be turned on/off in either a while loop or as a PWM signal in order to transmit the message. I'm under the assumption the only thing gained by using a PWM signal is that the work there is done on a timer callback and let other code run seemingly simultaneously. For simplicity, I opted for the while loop approach.
The issue I am seeing is one of two. Either the receiver is not reading the timings right, or the transmitter is not turning the LED on/off as fast as I would expect.
For the example code below, the IR LED is turned on for 600 microseconds, and off for 300. (Eventually, my custom messages will be built up using something along these lines.) However, as you can see in the Sample Outputs below the receiver is not seeing the IR signal as on or off for anywhere near that amount of time.
Not sure if this is a setup issue, or something else. The two Arduino boards I'm using are both Arduino Pro ATmega328p boards. For the board sending the IR signal, Pin 6 goes to a 330 Ohm resistor, then to the LED, then to ground. The IR Receiver on the other board has no resistors, just direct connections to pins. When reading the IR signals, I hold the receiver a few centimeters away from the LED.
My questions are:

Is this a viable setup? Should this work? Or am I all wrong in my assumptions and need to look some other way of doing this?
Is my assumption about turning the LED on/off with a while loop vs. a PWM signal true? Or should I remove the loop concept and only use a PWM signal.

IR Transmit Code:
#define IRpin          6

void setup() {
  pinMode(IRpin, OUTPUT);
}

void loop() {
  //LED On
  PORTD |= (1 << IRpin);
  delayMicroseconds(600);

  //LED Off
  PORTD &= ~(1 << IRpin);
  delayMicroseconds(300);
}

IR Receive Code (taken from an online example, only modifications are to output text):
#define IRpin_PIN      PIND
#define IRpin          2

// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
#define RESOLUTION 20

uint16_t pulses[300][2];  // pair is high and low pulse
uint8_t currentpulse = 0; // index for pulses we're storing

void setup(void) {
  Serial.begin(9600);
  Serial.println("Ready to decode IR!");
}

void loop(void) {
  uint16_t highpulse, lowpulse;  // temporary storage timing
  highpulse = lowpulse = 0; // start out with no pulse length

  while (IRpin_PIN & (1 << IRpin)) {
    // count off another few microseconds
    highpulse++;
    delayMicroseconds(RESOLUTION);

    // If the pulse is too long, we 'timed out' - either nothing
    // was received or the code is finished, so print what
    // we've grabbed so far, and then reset
    if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
      printpulses();
      currentpulse = 0;
      return;
    }
  }
  // we didn't time out so lets stash the reading
  pulses[currentpulse][0] = highpulse;

  // same as above
  while (! (IRpin_PIN & _BV(IRpin))) {
    // pin is still LOW
    lowpulse++;
    delayMicroseconds(RESOLUTION);
    if ((lowpulse >= MAXPULSE)  && (currentpulse != 0)) {
      Serial.println("Breaking - Hit max Pulse Low");
      printpulses();
      currentpulse = 0;
      return;
    }
  }
  pulses[currentpulse][1] = lowpulse;

  // we read one high-low pulse successfully, continue!
  currentpulse++;
}

void printpulses(void) {
  uint32_t totalMicroseconds = 0;
  for (uint8_t i = 0; i < currentpulse - 1; i++) {
    Serial.print("On(");
    Serial.print(pulses[i][1] * RESOLUTION , DEC);
    Serial.print(");");
    Serial.println("");
    Serial.print("   Off(");
    Serial.print(pulses[i + 1][0] * RESOLUTION , DEC);
    Serial.println(");");

    totalMicroseconds += pulses[i][1] * RESOLUTION;
    totalMicroseconds += pulses[i + 1][0] * RESOLUTION;

    if (i % 8 == 0) {
      Serial.println("");
    }
  }

  Serial.print("On(");
  Serial.print(pulses[currentpulse - 1][1] * RESOLUTION, DEC);
  Serial.print(");");
  totalMicroseconds += pulses[currentpulse - 1][1] * RESOLUTION;

  Serial.println("");
  Serial.print("Total Microseconds: ");
  Serial.println(totalMicroseconds, DEC);
}

Sample Outputs:
Ready to decode IR!
On(20);
   Off(62064);

On(0);
   Off(12060);
On(360);
   Off(1860);
On(440);
   Off(8940);
On(20);
   Off(15460);
On(80);
   Off(25672);
On(40);
Total Microseconds: 127016
On(40);
   Off(6740);

On(300);
   Off(6740);
On(20);
   Off(8520);
On(40);
   Off(6740);
On(1540);
   Off(15720);
On(40);
   Off(34860);
On(20);
Total Microseconds: 81320

On(3000);
   Off(35384);

On(40);
   Off(14180);
On(1220);
   Off(54440);
On(980);
Total Microseconds: 109244

On(200);
Total Microseconds: 200
On(20);
   Off(29160);

On(60);
   Off(26700);
On(60);
   Off(22880);
On(20);
   Off(2928);
On(20);
Total Microseconds: 81848

I don't know for sure, but my guess is that while 65 milliseconds is a long time for a microprocessor, it may not be a long time for LED lighting and receiving.  It may take the LED longer than you or I would think to emit at a readable level, for instance- I don't know. I would at least consider slowing things waaaay down-  like seconds - and see if you get reliable transmission and reception at very very slow speeds. You may also need to consider outside light interference, movement of your hand, etc

@mikeY - See What is the latency of an LED?. Depending upon LED type: 2 nS to 1.2 µS

What IR receiver are you using ? If it is a 3 pin TSOP type, used in say television remote control applications,  these generally require a carrier of around 38kHz or a period of 26 uS.  Your transmitter appears to be sending a carrier of 900us, that is around 1kHz. You then have to modulate the carrier to encode data onto it. Oh. I've just noticed that this is 5 years old and has probably been stirred up by the "community Bot"

I ended up also asking this question at electronics.stackexchange.com. I know that's frowned upon, but the topic really did toe the line between being an Arduino subject or electronics.
To summarize the accepted answer, no IR messages cannot be sent/received the way I thought. The IR LED needs to be on/off at a frequency that matches what the receiver is set to be able to receive. Generally 38kh. So On for 13 microseconds, then Off for 13 microseconds. Then repeat.
https://electronics.stackexchange.com/questions/417387/precise-on-off-control-for-ir-led/417391


text:
I have a cash counter with RS232 in the back of it, I want to read the data that supposed displayed on the projector
I have cash counter with RS232 in the back of it. I want to read the data that supposed displayed on the projector with RS232 to TTL convertor and arduino.
Here is all my setup

Now I

Connect the MAX3232 TX pin to the RX Arduino pin
and Connect the MAX3232 RX pin to the TX Arduino pin
and the Vcc to 5V
and MAX3232  GND to arduino  GND
and plug the MAX3232  to the cash counter and the arduino to the pc
and flash

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

void loop() {
  int data = Serial.read();
  if (data != -1) {
    Serial.println(data);
  }
}

And the output comes like this
50
56
48
67
49
52
48
8
10
106
13
51
56
56
76
147
48
51
12
13
83
106
51
1
13
64
10
1
49
254
254
254
254
252
254
255

How can I read the data from this device?

you have to determine what data is actually sent by the counter ... until you have that information available, the question is not about arduino

Use Serial.write() instead of Serial.println(). Printing interprets the data as a number (integer) into the ASCII representation, while writing sends the data unchanged. If the device sends ASCII encoded data you then will be able to read it in the serial monitor

Posting the make, model will help all of us. Also what does the instruction manual tell you?

From the labels in the pictures supplied by the OP and a some minutes with Google it appears to be a Proware Mix Value Counter STS 6000-T https://www.facebook.com/ProWare-117664076286992/videos/currency-counter-machine/760314631226329/. Some technical reference from the manufacturer would help but the interface may be proprietary and not published. It will be used at least for uploading profiles of new bank notes. Some similar machines allow you also to download the bank note details like serial numbers etc.

thank u i send message to them i hope the can help me with any info about this problem  @6v6gt

there is no information about the model till now i dont have any useful info to share :( @Gil


text:
When I use AnalogueWrite the voltage doesn't vary properly
I have a project where I want to control a pump, I use an Arduino, connected to a driver L298N and I will connect the pin 5, 6, 7 of the arduino to the pin IN2, IN1, ENA of the driver respectively and the motor will be connected to the output
My materiel :

Arduino Uno R3
Multimeter
Arduino IDE 2.1.1

The issue :
When I use the function analogWrite the voltage vary only between two value (0v or 5.5v).
The pin used was the Digital pin n°7, noted in the code 7.
The code :
#define PUMP_DIR_1 5
#define PUMP_DIR_2 6
#define PUMP_PWM 7
#define INVERTED 0

void setup() {
  Serial.begin(9600);
  pinMode(PUMP_PWM, OUTPUT);
}

void set_pump_speed(int speed){
  Serial.print("Set speed ");
  Serial.print(speed);
  Serial.print("\r\n");
  analogWrite(PUMP_PWM, speed);
}

void loop() {
  set_pump_speed(255);
  delay(3000);
  set_pump_speed(0);
  delay(3000);
  set_pump_speed(125);
  delay(3000);
}

As output I obtained :

00:32:17.184 -> Set speed 0
00:32:20.175 -> Set speed 125
00:32:23.178 -> Set speed 255
00:32:26.182 -> Set speed 0
00:32:29.197 -> Set speed 125
00:32:32.201 -> Set speed 255

From the mutlimeter I obtained :

0v when speed = 0
0v when speed = 125
5.5v when speed = 255

The arduino is not wired to anything

Pin 7 isn't a PWM pin. Use, say, pin 6 and you will get correct results. The PWM pins are marked with a "~" on the board.

Thank your for your answer, I feel stupid, because it is not the first time I use PWM on Arduino and I never took this in consideration.

@Nept0 Don't worry! It must have worked last time by chance, now you know why. :)


text:
DS18B20 Error in Proteus 8.13
I am using the below code to check temperatures from 36 DS18B20 sensors using Arduino Mega 2560.  If any one of them go above 50 deg. celsius, then it sets the output pin to HIGH.
I am trying to run the code on Proteus 8.13, but during the same run, sometimes the virtual terminal prints -127 deg. celsius for all, sometimes right for some sensors and wrong for the other ones (usually the wrong value is also 85 deg. celsius). Is it something wrong with the simulator, or my code?
    #include <OneWire.h>
    #include <DallasTemperature.h>

    #define NUM_SENSORS 36
    #define START_PIN 14
    #define OUTPUT_PIN 2

    OneWire oneWire[NUM_SENSORS];
    DallasTemperature sensors[NUM_SENSORS];

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

      for (int i = 0; i < NUM_SENSORS; i++) {
        oneWire[i] = OneWire(START_PIN + i);
        sensors[i] = DallasTemperature(&oneWire[i]);
        sensors[i].begin();
      }

      pinMode(OUTPUT_PIN, OUTPUT);
      digitalWrite(OUTPUT_PIN, LOW);
    }

    void loop() {
      float celsius[NUM_SENSORS];

      for (int i = 0; i < NUM_SENSORS; i++) {
        sensors[i].requestTemperatures();
        celsius[i] = sensors[i].getTempCByIndex(0);
      }

      bool aboveThreshold = false;

      for (int i = 0; i < NUM_SENSORS; i++) {
        if (celsius[i] > 50.0) {
          aboveThreshold = true;
          break;
        }
      }

      digitalWrite(OUTPUT_PIN, aboveThreshold);

      printSensorData(celsius);

      delay(1000);
    }

    void printSensorData(float celsius[]) {
      for (int i = 0; i < NUM_SENSORS; i++) {
        Serial.print("Sensor ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.print(celsius[i]);
        Serial.print(" C  ");
        Serial.print(sensors[i].toFahrenheit(celsius[i]));
        Serial.println(" F");
      }
    }

+85 degC is the value returned by these sensors after a power-on/reset (of that sensor) - maybe not so coincidentally. Could the device(s) that returned that value have had a (simulated) power interruption?

The -127 indicates a fault on the hardware side, generally an open circuit. Also it sounds like your pull up resistor is not installed or way out of range.For the Mega. UNO and other 5V units 4.7K is a good size and 3.3K for the 3V3 systems. Note the resistor goes from VCC to the sensor output.

DS18B20 is using one-wire protocol, no SDA, nor SCL.

It appears that each sensor is on a separate pin - 36 1-Wire busses, as it were. If that is correct, is there a reason you haven't put the sensors on just a few 1-Wire busses? It would require many fewer pullup resistors and there will be many fewer mechanical connections to fail. There is an helpful application-note, "Guidelines for Reliable 1-Wire Networks" that discusses how to make reliable large networks and what the limits are.


text:
Can Arduino UNO/MEGA master assert SPI SS LOW on multiple slaves at once if Full Duplex is unnecessary?
I have a computer talking serially to an UNO SPI Master and, beyond it, multiple MEGA Slaves.  The slaves never talk back to the master.
I understand it is normal and correct to assert SS LOW to select one slave at a time, such that the master clocks bits via MOSI to the selected slave on the same clock edges the slave sends bits to the master via MISO.
Multiple slaves clocking on MISO would garble the communication back to the master.  But what if I don't care?  Instead, on a system with a pulled-up MISO pin that does not even have MISO wires attached, what if the master selects all the slaves at once, then clocks a byte out on MOSI with a bit set calling for one specific slave (of 8 possible) to respond to subsequent bytes?  That is way faster than the master sorting out with code which slave should get the message originating in the computer.  ALL the slaves can check the bit they expect and ignore the subsequent bytes of the SPI message if the bit is CLEAR-- they are not doing anything else at the moment anyway, say.
What is wrong with this idea?  Are there electronic issues in the UNO or MEGAs I am not thinking of?  Is this done?  Why not?

The electronic circuit of an SPI work this way,  when a slave device is not been selected (i.e. its CS pin is not asserted), its MISO line will be in tri-state output, i.e. it is in a high impedance floating state, electrically disconnect, this allows multiple devices sharing the same MISO bus. For this reason, you can't tie all the slave devices with a single CS pin as all the MISO outputs from the devices will be activated.
If you don't care about the MISO data clocking in from the slave devices, you simple don't connect the MISO pin to the bus.

try-state -> Tri-state (as in 3 states). Otherwise, I agree with you.

Ops. Thanks for pointing that out.

What is wrong with this idea?

Nothing, this is perfectly possible. The main advantage is the avoidance of multiple SS lines, reducing pin count and/or decoding hardware.
The SPI main device does not know the number of SPI sub devices, and it will happily sample the level at the MISO pin, whatever you give it.
Each SPI sub device does not know that the other SPI sub devices receive the very same bytes. As you write, if the first byte (or any other protocol detail) tells it to ignore the rest of the transmission, it will.

Are there electronic issues in the UNO or MEGAs I am not thinking of?

You need to read the data sheet to learn about the load of each input of the SPI sub devices, and the guaranteed provided drive capability of each output of the SPI main device, that means SS, SCLK, MOSI. Then make sure the driver can drive all receivers.
Commonly you can connect a two-digit number without any concern.You write that you have eight, so just go ahead.
You can leave the MISO outputs of the SPI sub devices simply unconnected. At the SPI main device make sure you have a pull-up or pull-down resistor on its MISO input.

Is this done?

I have no personal experience or example, but I'm sure it is done.

Why not?

When you actually need responses from the SPI sub devices, you need to do it differently. However, even then you can combine all the MISO outputs of the SPI sub devices with some clever digital logic.

Note: I prefer "main" and "sub", which still match the abbreviations, instead of the old terms of the former century.


text:
Not registering complete rotary encoder input
I am working on a project using a Rotary Encoder and I am trying to receive the output from the encoder. As it stands I am able to get a count for degrees of change and direction of rotation, however depending on the speed the encoder spins I get a varying rotational output. For example if I rotate it slowly I can get 100's of counts for 180 degrees of rotation, but if I do so fast, then I could get 10 or so counts.
I believe my Arduino is running too slow to count each of the signals from the encoder, I measured the wavelength of a signal to be ~25 us when spun quickly but using the following code I found that my arduino is running at a loop rate of 200 loops per second.
void loop() {
  if(counter <= 1000){
    counter++;
    Serial.println(counter);
  }
}

The code for the Rotary Encoder:
Dt and CLK pin representing the 2 signal wires, both being pulled up
void loop(){

  //take clk pin state
  clkState = digitalRead(clkPin);

  //if clk state changed then wheel is rotating, react to rising edge to avoid double count
  if(clkState != preClkState && clkState == HIGH){
    Serial.write(digitalRead(dtPin));
    //check direction of spin based on dtpin
    if(digitalRead(dtPin)== HIGH){
      counter++;

      clockwiseDirection = true;
    }else{
      counter--;

      clockwiseDirection = false;
    }

    //output values
    Serial.write("Direction: ");
    if(clockwiseDirection){
      Serial.write("Clockwise | Counter: ");
    }else{
      Serial.write("Counter Clockwise | Counter: ");
    }

    Serial.print((int)counter);
    Serial.print("\n");

  }

  //update pre pos
  preClkState = clkState;

}

Is it possible that all of the data printed to the Serial Monitor maybe slowing things down a bit?

you should use interrupts instead of digitalRead to ensure responsive scrolling. and yeah, don't print each detent.

Serial transmission takes time. Let's assume that you have set up the Serial with 9600 baud. This means 9600 bits per second. A single byte transmission commonly consists of a start bit, the data bits, and a single stop bit. This gives a total of 10 bits per byte. Therefore, your transfer rate is 9600 bits/s / 10 bits/byte = 960 bytes/s.
Estimating with a quick look at your source, each loop of your sketch sends about 40 characters, commonly encoded as a byte per character. And you claim that it achieves 200 loops per second, so the transfer rate is 40 bytes/loop * 200 loops/s = 8000 bytes/s.
Calculating back to bits/s results in a baudrate of roughly 80000 bits/s. So presumably you set up your Serial with 57600 or 115200 baud.

How to solve the issue?
Separate the acquisition of the encoder data from the transmission of the counter value. You can use interrupts, for example on the clock signal. However, this is not for the faint heart.
The Serial uses a transmission buffer of unspecified size. See the last paragraph of its documentation:

As of Arduino IDE 1.0, serial transmission is asynchronous. If there is enough empty space in the transmit buffer, Serial.write() will return before any characters are transmitted over serial. If the transmit buffer is full then Serial.write() will block until there is enough space in the buffer. To avoid blocking calls to Serial.write(), you can first check the amount of free space in the transmit buffer using availableForWrite().

You can check that the transmit buffer has room for your message. Send only, if there is enough room.


text:
Reading serial data from Arduino in Python continually
Using a stepper motor and a range finder (TFLuna), I am trying to build a "Lidar" (like a Radar, but with light). Here is the algorithm:

Turn motor one step, calculate angle, measure distance to whatever it hits, giving polar coordinates;
Calculate Cartesian coordinates and send to Python;
Collect a few hundred measurements and show the scatter plot.

This works, but only if I restart the sketch and the Python routine at the same time. After I collected all the data for one plot, I cannot restart the Python script to collect another round of data - it shows that there is no data in waiting. Also, the Arduino script never hangs due to the buffer getting full (as Python has stopped reading).
How can I make it so that the Arduino and the motor do their thing (swinging back and forth 180º, looking at stuff), and I am able to collect an amount of data in Python intermittently -- whenever I choose to restart the script one more time?
Here is the code. First, Arduino. "count" is the number of steps by which the motor has rotated; tflI2C is the range-finder object.
#include <Stepper.h>
#include <Arduino.h>
#include <Wire.h>        // Instantiate the Wire library
#include <TFLI2C.h>      // TFLuna-I2C Library v.0.1.1
#include <math.h>

TFLI2C tflI2C;
int16_t  tfDist;    // distance in centimeters
int16_t  tfAddr = TFL_DEF_ADR;  // Use this default I2C address

const int stepsPerRevolution = 2048;  // change this to fit the number of steps per revolution

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);
int stepCount = 0;         // number of steps the motor has taken

void serialFlush(){
  while(Serial.available() > 0) {
    char t = Serial.read();
  }
}

void setup() {
  // initialize the serial port:
  Serial.begin(115200);
  Wire.begin();           // Initalize Wire library
  myStepper.setSpeed(10);
  //myStepper.step(stepsPerRevolution/2);
  //delay(1000);
  //myStepper.step(-stepsPerRevolution/2);
}

void coordinates(int count){
  struct Polar {
    float angle;
    int16_t distance;
  } pPoint;
  struct Cartesian {
    float xCoord;
    float yCoord;
  } cPoint;

  float angle = count*(2.0*PI)/stepsPerRevolution;
  byte flag = 0;
  //Serial.flush();
  while (Serial.availableForWrite() < sizeof(struct Cartesian)){}
  if(tflI2C.getData(tfDist, tfAddr)){
    pPoint.angle = angle + PI/2.0;
    pPoint.distance = tfDist;
    cPoint.xCoord = pPoint.distance * cos(pPoint.angle);
    cPoint.yCoord = pPoint.distance * sin(pPoint.angle);
    if (pPoint.distance <= 50 ){
      Serial.write((char*)&cPoint, sizeof(struct Cartesian));
    }
  }
  return;
}

void loop() {
  // step one step:
  for (int k=0; k<stepsPerRevolution/4; k++){
    myStepper.step(1);
    coordinates(stepCount);
    stepCount += 1;
    delay(10);
  }
  for (int k=0; k<stepsPerRevolution/2; k++){
    myStepper.step(-1);
    coordinates(stepCount);
    stepCount -= 1;
    delay(10);
  }
  for (int k=0; k<stepsPerRevolution/4; k++){
    myStepper.step(1);
    coordinates(stepCount);
    stepCount += 1;
    delay(10);
  }
  delay(5000);
}

and here is Python:
ardu = serial.Serial('/dev/cu.usbserial-1460', baudrate=115200, timeout=.1)
radarImage = []
structSize = struct.calcsize("ff")
ardu.reset_input_buffer()

i = 0;
while True:
    if ardu.in_waiting >= structSize:
        arduRead = ardu.read(structSize)
        point = list(struct.unpack("ff",arduRead))
        if i <= 10:
            print(point)
        radarImage.append(point)
        i += 1
    else:
        pass
    if i > 2000:
        break
ardu.close()

Here is a sample from a "first round" data collection. Yes, my desk is messy...

the arduino code does not compile without error

I'm not surprised - I only gave you the code that pertains to the serial communication. I'll pop in the entire thing if that helps. Hold on...

RE: "I cannot restart the Python script to collect another round of data" - perhaps you have an issue with the python code too?

What Arduino are you using? It is unclear to me, what exactly happens, when you restart the python script. When exactly did you try to restart it? During the 5s delay? Or during a measurement round? What exactly does happen then? Currently your Serial code doesn't have any possibility to sync between Arduino and python. The python script is not able to detect the start of a new point struct inside the serial stream (you didn't implement any protocol for that).

You might want to reduce your sources to the minimum, reproducible and compilable example that shows the behavior. For example, start removing the Lidar stuff and replace it, if necessary, with a simple dummy.

@chrisl: I have tried to restart the Python at various points during the Arduino execution. I have tried to print "in_waiting" and it gives me zero. You are right about the syncing as such -- but I'd accept nonsensical data for a first draft. I am puzzled why the Arduino code isn't simply stopping at "Serial.availableForWrite()" when I stop reading data on the Python side -- it keeps on running. If there isn't a simple idiom I am missing, I'll try to work with explicit "start running" and "stop running" bytes from Python to Arduino...way more complicated than I wanted for a proof of principle.

@thebusybee: Understood. However, I was really hoping someone would know of a code "idiom" that'd contain the right combination of "waiting for data" and/or "flushing the buffer" for a middle-of-runtime restart of the data transmission. If not -- no big deal. Reducing the code to a minimum is just as much work as upgrading the code to have proper hand-shake communication with explicit start and stop "commands" issued by the Python code...a lot more effort that I wanted because ultimately I just want to visualize the data on a TFT display.

Well, you do not expect each of us to invest the time to wade through all that code, do you? ;-) Lesson to learn: develop software in baby-steps, not as big-bang. Separate issues. Experiment to understand how things work.

@thebusybee: Absolutely not!! If the solution isn't obvious, or what I am missing isn't trivial, I wouldn't expect anyone to go into more troubleshooting efforts than I am willing to engage in. However, sometimes it happens that a problem has a, "Oh, you simply do..." solution. It's worth checking whether there is. :) It is very hard to be diligent when the purpose of the code is to simply check whether the quality of the provided data makes in even worth to pursue the project any further.

I am puzzled why the Arduino code isn't simply stopping at "Serial.availableForWrite()" when I stop reading data on the Python side -- it keeps on running.

This depends on the Arduino board used - specifically on if it has native USB support. Boards without native USB support (like Uno or Nano) use a second chip, which receives UART (Serial) data from the main chip and interfaces that to USB. The main chip cannot know about the state of the USB chip, so it will send regardless of a program listening.
Boards with native USB support somewhat depend on the OS/driver/program to collect the data from the USB endpoints. If your program doesn't collect that data, but also doesn't close the connection, then the data will pile up in the buffer and availableForWrite() should return 0 when the buffer is full (blocking further writing to Serial). But if your program closes the connection correctly (as it should on exiting), then the Serial data doesn't even get send, but discarded. See Majenkos answer to this question, which is relevant here.
So generally: No, the Arduino won't stop sending data, only because you don't listen. Building a simple command system to tell the Arduino to start/stop sending data is a common way to handle this situation. Or you could implement a protocol, which lets the python script correctly detect start and end of each data packet.

This was way more effort than what was warranted for a quick-and-dirty data dump and visualization, but ultimately I did succeed, sort of, by implementing a "Send 'TURN' command to Arduino, Arduino calculates struct and sends to Python, Python sends next 'TURN' command," song and dance. After that it was STILL hanging randomly until I added a whole bunch of explicit buffer flushes and carefully timed "delay()-s" into both codes. The irony is that the data ultimately didn't even look that impressive -- not impressive enough to polish the project further.


text:
Updating multiple Arduino Nanos with same INO file
BTW - I have, unsuccessfully, searched for an answer before posting.
I have an NodeMCU connected to a bunch of Arduino Nanos over the I2C bus. The WiFi-enabled NodeMCU has the capability to do OTA updates on itself, which I've mastered but I want to update the same code into all of the slave Nano devices.
Is this possible? If so, what is the easiest way? The devices will be installed on a wall, so I don't want a bunch of USB cables trailing out of it.
Can I use/share the WiFi connection on the NodeMCU, with the Nanos, via the I2C bus? Or is there a better way?
PS - I have read about compiling the .INO file into a hex or bin file but still don't understand the process properly.
PPS - updating .INO files OTA on an ESP8266/WiFi enabled NodeMCU is great but they are bigger (wider) that a Nano and would cost a lot of money as I would need about 30 or so.

The compilation and linking process turns the .INO file into a .HEX file which is basically the machine-code that gets loaded into the processor. It is easy enough to get hold of that file as part of the compilation process.
To update the firmware in your Nanos, you basically need to replace the existing bootloader (which updates via the serial interface) with one which updates via I2C.
I see such a bootloader exists here on Github.

Is this possible?

Sounds like it.

If so, what is the easiest way?

Depends what you mean by "easiest". If the devices are mounted on a wall, that may be the easiest way.
What you might do is, after booting up, each device would query the master to see if an update was available*. If it was, they would take turns to get the update supplied to them via I2C. If the update failed half-way through it might be hard to recover. You might want to have some sort of system where the bootloader checks if the main code is valid (eg. by a sumcheck) and if not, request another update.
I think it could be done, the mechanics could provide an interesting challenge. Have fun with it!

* One possibility would be for the master to make an I2C broadcast (maybe every 10 minutes) of what the current software version is, and if the slave finds that it doesn't have the latest version, request an update. If the master was busy (perhaps because it was updating another slave) the slave might wait 5 minutes and try again.


text:
interrupt from a button and wait until serial port 1 has a message
I'm a little bit loss because I'm learning how to use the interruptions on Arduino.
I'm creating a program to read an RFID code that arrives if an RFID transmitter is close to the antenna (a little antenna board RFID). I  have two operating modes: one where I associate my board to an RFID, so I will act only where my RFID code is identified ( I save the RFID code on the board). and another mode where I read all the RFID codes and I save it.
I have one configuration step where if the user push a button, I want to wink a led to indicate that we are waiting for the presentation of the RFID code to associate to the board. I try to make a code and I have some problems to get out of the condition where I'm waiting for the RFID code (serial1).
Here is my code:
#include <Wire.h>

//const int reception_rfid = 15;
const int btnAssociation = 2; // bouton pour indiquer que l'on souhaite faire l'appareillage des RFID (interruption)
const int SwitchModeConfig = 4;
const int LedAssociationEnCours = A0;

int compteurLedAsso;

const int BUFFER_SIZE_RFID = 13;
char buf[BUFFER_SIZE_RFID];

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onRequest(requestEvent); // register event
  Serial.begin(9600);
  Serial1.begin(9600);
  pinMode(SwitchModeConfig, INPUT_PULLUP);
  pinMode(btnAssociation, INPUT_PULLUP);
  pinMode(LedAssociationEnCours, OUTPUT);
  ConfigurationAssociation();
  digitalWrite(LedAssociationEnCours, HIGH);
}

void loop() {
  delay(100);
}

void ConfigurationAssociation(){
  int stateSwitch = digitalRead(SwitchModeConfig);
  if(stateSwitch == LOW){
      attachInterrupt(digitalPinToInterrupt(btnAssociation), InterruptAssociation, RISING);
      Serial.println("Mode association");
    }else{
      detachInterrupt(digitalPinToInterrupt(btnAssociation));
      Serial.println("Mode aleatoire");
    }
}

void InterruptAssociation(){
  compteurLedAsso = 0;
    Serial.println("Ouverture de l'Association d'un code RFID");
    while (Serial1.available() == 0 && compteurLedAsso <= 600)
    {
      // clignoter la led rouge sur A0
      digitalWrite(LedAssociationEnCours, LOW);
      delay(5000);
      digitalWrite(LedAssociationEnCours, HIGH);
      delay(5000);
      compteurLedAsso++;
      Serial.println(compteurLedAsso);
    }

    if(Serial1.available() > 0){
      int codeRFID = Serial1.readBytes(buf, BUFFER_SIZE_RFID);
      Serial.println("CodeRFID: ");
      for(int i = 0; i < codeRFID; i++)
        Serial.print(buf[i]);
    }
      //Serial.println(compteurLedAsso);
      //compteurLedAsso++;
    Serial.println("Fin de l'attente code RFID");
}

void requestEvent() {

}

First problem: I know that when we are inside a interruption we can't count the time pass on a while, I would like to wink the led 2 minutes: waiting the presentation of the RFID code to save and once the 2 minutes pass away I get out of the interruption. How make to wait 2 minutes for RFID code on serial1 port inside an interruption? my reception RFID board works fine and TX is connected to RX1 (pin 19) of Arduino mega (I verify on another code where reading RFID works)

Second problem: when my board is inside the interruption that comes from a push button (connected on pin 2) I stay always on the while loop even when my RFID transmitter is reading an RFID code, I can't get out of and I don't know why! maybe you can help to understand and find a solution please?

The thing is: Inside an ISR (Interrupt Service Routine) not only does time measuring with millis() not work, delay() also won't work (it uses the same interrupt mechanism as millis() in the background). Neither does anything else, that depends on their own ISR to execute - like receiving serial data. The hardware Serial interface can receive single bytes without depending on interrupts, but to get these bytes into the buffer (and to actually use them via Serial) you need to let other ISRs execute.
You should NEVER write an ISR, which executes for a long time. Keep it in the microseconds, maximum in the very low millisecond range. How long you can get here until you see negative effects depends on other factors. You really should only do minimal work in an ISR and the rest in the main code.
A common code structure for this looks as follows:

In your main code you don't use any delay() calls. Everything timed should be done with millis() (like in the BlinkWithoutDelay example that comes with the Arduino IDE), so that it won't block execution. Also no long loops inside of loop(). Make sure, that your loop() function can iterate freely and fast.
In global scope you define a flag variable. A simple one byte variable, marked as volatile.
In your ISR you are doing nothing but setting this variable. Depending on your situation you might wanna set it depending on an digital input via digitalRead(), which is still fast, so OK to do.
In your main code you use an if statement to check for this flag variable to be set. On most loop() iterations this won't be executed. Only, if the flag variable got set inside the ISR, it will get executed. This is the place where you write the code handling the event. At the end of the block you then only need to reset the flag variable, so that you are ready for the next interrupt to happen.

This would look somewhat like this:
int button_pin = 2;
volatile bool button_flag = false;

void setup(){
  pinMode(button_pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(button_pin), button_ISR, RISING);
}

void loop(){
  if(button_flag){
    // Handle interrupt here
    button_flag = false; // Reset flag variable to be ready for next interrupt
  }
}

void button_ISR(){
  button_flag = true;
}

Note, that the button_flag variable is defined as volatile, so that the compiler doesn't cache its value is some register and instead always reads the actual current value of it (not optimizing it).
In your code you should probably use another coding concept named Finite State Machine (FSM). This is the easiest method to implement a code with different states/stages while still keeping it non-blocking. You can read up about FSMs on the web (or for example in my answer to this question).
The gist is, that you use a variable, that represents the state, that your code is currently in. In loop() you then only ever execute the code for the current state. Changing to a different state is done by setting the state variable. The state, that your current code needs, are probably CHECK_FOR_SINGLE_RFID_TAG and ASSOCIATE_SINGE_RFID_TAG (though you can name these like you want). A simple FSM with this can look like the following:
#define CHECK_FOR_SINGLE_RFID_TAG 0
#define ASSOCIATE_SINGLE_RFID_TAG 1

// single byte variable so that we don't need to bother about atomic reads/writes
uint8_t state = CHECK_FOR_SINGLE_RFID_TAG;

void loop(){
  switch(state){
    case CHECK_FOR_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here, check the RFID tag ID against the saved one
        // and execute code accordingly
      }
      break;

    case ASSOCIATE_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here and save the new RFID tag ID in a variable
        // then reset the state variable to automatically go back to check mode
        // after the new RFID tag is enrolled
        state = CHECK_FOR_SINGLE_RFID_TAG;
      }
      // Use the BlinkWithoutDelay idiom to blink your LED non-blocking
      // something like
      // if(millis() - led_timestamp > led_interval){
      //   digitalWrite(led, !digitalRead(led));
      // }
      break;
  }
}

You see, how we define out possible states, save the current one in a variable and act according to it inside of loop()? This concept is really powerful, so it is totally worth it to learn.

Note: I've used a variable of type uint8_t (a single byte) to keep this interrupt safe (you can read up about this by searching for something like arduino interrupt atomic read or arduino interrupt safe variable) for the next part and the defines to give each value a readable name. You could use an enum for that, though while writing this I got on a tangent about the size of an enum, which seems 16 bits on AVR (like the Arduino Mega), unless you use a specific compiler flag, according to this blog article. This explanation is not that important for you right now, but I also wanted to explain, why this doesn't use enums.

Now we can combine this with our interrupt code from above. In this case we don't need a seperate flag variable anymore. We can directly set the state variable inside the ISR:
#define CHECK_FOR_SINGLE_RFID_TAG 0
#define ASSOCIATE_SINGLE_RFID_TAG 1

volatile uint8_t state = CHECK_FOR_SINGLE_RFID_TAG;

int button_pin = 2;

void setup(){
  pinMode(button_pin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(button_pin), button_ISR, RISING);
  Serial.begin(115200);
  Serial1.begin(115200);
}

void button_ISR(){
  state = ASSOCIATE_SINGLE_RFID_TAG;
}

void loop(){
  switch(state){
    case CHECK_FOR_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here, check the RFID tag ID against the saved one
        // and execute code accordingly
      }
      break;

    case ASSOCIATE_SINGLE_RFID_TAG:
      if(Serial1.available()){
        // read Serial1 here and save the new RFID tag ID in a variable
        // then reset the state variable to automatically go back to check mode
        // after the new RFID tag is enrolled
        state = CHECK_FOR_SINGLE_RFID_TAG;
      }
      // Use the BlinkWithoutDelay idiom to blink your LED non-blocking
      // something like
      // if(millis() - led_timestamp > led_interval){
      //   digitalWrite(led, !digitalRead(led));
      // }
      break;
  }
}

You can see, the button_ISR() is very small, thus very fast. And our loop() also runs unblocked, so the next iteration of it will come very fast and it will then execute the state, that we set in the ISR.
Note: When reading from Serial, make sure, that you don't use functions, that block for a long time. For example Serial.readString() will take 1s to execute (since that is the default timeout), which would block the non-blocking code (no good).

Hi! whao!! Thank you so much for all these super explanations very complete and clear! :) i'm gonna read all and see the exemples of FSM because i don't know anything about it for be honest. I will back with news or maybe answers about my problem if is ok with u. Again, thank u for ur help :)

*i will back with news or maybe QUESTIONS instead :)

I come back with news, thanks to your help @chrisl and EdgarBonet i understand how to make FSM to improved my arduino code.  it's working! thank u so much again to the both! :)

chrisl's answer brings many excellent points, and I highly recommend you
study it in detail. There are just a few points I would personally add
or amend:

an ISR should probably not last more than a few tens of microseconds,
and many bad things could happen during a 1 ms ISR (missed clock
tics, lost serial input...)
a loop() iteration should not take more than a few milliseconds
there is no point in using an interrupt for reading a button: the user
will keep the button pressed for many milliseconds, and you will have
many opportunities for catching it in loop(); interrupts bring
complexity that is only worth it when you have to deal with
sub-millisecond timings
do not worry about the size of an enum unless you need to care about
sub-microsecond timings

Now, my take at this problem. The first step is to define the state
machine. I may call the states NORMAL and ASSOCIATION. The
transitions would be:

NORMAL → ASSOCIATION when a button press is detected
ASSOCIATION → NORMAL when either an RFID code is read or after a
timeout

My tentative implementation:
// Attempt to read an RFID without blocking.
// Returns the found RFID code as a pointer to a NUL-terminated buffer,
// or nullptr if no RFID is available right now.
char *read_rfid() {
    // Implementation left as an exercise to the reader.
}

void loop() {
    static enum {NORMAL, ASSOCIATION} state;
    static uint32_t started_association;  //  association start time

    char *rfid = read_rfid();
    switch (state) {
        case NORMAL:
            if (rfid) {
                Serial.print("Read RFID code: ");
                Serial.println(rfid);
            }
            if (digitalRead(btnAssociation) == LOW) {
                Serial.println("Starting association");
                mode = ASSOCIATION;
                started_association = millis();
            }
            break;
        case ASSOCIATION:
            if (rfid) {
                assocate_rfid(rfid);
                Serial.println("Association successful, code: ");
                Serial.println(rfid);
                mode = NORMAL;
            }
            if (millis() - started_association >= assocation_timeout) {
                Serial.println("Association timeout");
                mode = NORMAL;
            }
            break;
    }
}

There are a few things I left out here, most notably:

The LED blinking, which should be done in the style of the Blink
Without Delay example
The function read_rfid() that reads the serial port in a
non-blocking fashion. For this, you will need to have a rule for
deciding when a message is complete. This could be a message
terminator (if the reader does send one) or a timeout.

Finally, I would recommend you read a couple of blog posts by Majenko:

The Finite State Machine is a tutorial on the implementation of
finite state machines
Reading Serial on the Arduino teaches you how to read the
serial port in a non-blocking fashion.

Thank you so much for your help :) with your responses i can understand so many things and improve my code :) i keep going on my projet! thanks for ur help! :)