body:
Ok, I got it working now, here's what was happening:

Turns out the file wasn't being opened. Why? seems like there's a limitation on the filename length, I noticed this after adding the lines:

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

And sure enough my file was not detected as **single_byte.dat** but it was something like: **single_~.dat** so I renamed the file to **test.dat** and tada! code now works like a charm.

I guess I overlooked this restriction on the documentation, so keep this in mind when you use an SD card.

Also, make sure to check if you are really opening your file because no exception will be thrown if you reference an uninitialized file pointer I guess.

Just make sure to have:

    file = SD.open(filename, FILE_READ);
    if(file){
        // Do things here.
    }
    else{
        Serial.println("You're out of luck: Can't open file");
    }

Ok, there goes my Sunday. Thanks all for reading!!!


sender: user

message:
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][1]). 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):

[![Fault code #1][2]][3]
[![Fault code #4][4]][5]

(more photos [here][6])

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:
```c++
#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][7]) to create some graphs. I captured 10+ seconds in each of the following scenarios:

 1. No fault/control (zero blinks)
 2. Fault #1 (1 blink then 4-second pause)
 3. 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):

[![Graph of control scenario - no fault (zero blinks)][8]][8]
[![Graph of fault code 1][9]][9]
[![enter image description here][10]][10]

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

  [1]: http://www.frigochem.com/pdf/HTB1t59FHVXXXXcyXpXX.PRXFXXXU.pdf#page=6
  [2]: https://i.stack.imgur.com/TUFJGm.jpg
  [3]: https://i.stack.imgur.com/TUFJG.jpg
  [4]: https://i.stack.imgur.com/jdqR3m.jpg
  [5]: https://i.stack.imgur.com/jdqR3.jpg
  [6]: https://imgur.com/a/ZAmFXGi
  [7]: https://docs.google.com/spreadsheets/d/1IeaqH9RQtn5xjXG500wL4Sm3EI2CuzoQiU8Qc_ooYFg/edit?usp=sharing
  [8]: https://i.stack.imgur.com/4IlzS.png
  [9]: https://i.stack.imgur.com/As7Ja.png
  [10]: https://i.stack.imgur.com/0Sdyx.png

sender: assistant

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


message:
Connecting pressure sensor to Arduino to collect pressure and time data

I'm trying to build a pressure data logger using an Arduino and Mindman MP47P-03-F1 (https://www.mindman.com.tw/proimages/pdf/E_MP47_S.pdf) pressure sensor, the sensor is connected to an outer 12-24 VDC power source.
I've connected the analog wire to the the Arduino's A0 and added another wire from the GND to the sensor. I get a stable voltage (~1V) reading but the pressure is wrong and it doesn't respond to pressure changes.
Can someone tell me what I'm doing wrong?
this is the sample code:

    const int analogPin = A0;
    const float slope = -0.1;
    const float intercept = 0.6;
    const unsigned long startTime = millis();

    void setup() {
      Serial.begin(9600);
      Serial.println("Time (s)\t\tPressure (MPa)");
    }

    void loop() {
      unsigned long elapsedTime = millis() - startTime;
      int sensorValue = analogRead(analogPin);
      float voltage = sensorValue * (5.0 / 1023.0);
      float pressure = slope * (voltage - intercept);

      Serial.println(sensorValue);
      Serial.print(elapsedTime / 1000.0);
      Serial.print("\t\t");
      Serial.println(pressure);

      delay(1000);
    }

edit: i've changed the code to as suggested by some on the arduino forum:

    const int sensorPin = A0;
    const int offset = 201; // zero pressure adjust
    const int fullScale = 1023; // max pressure adjust
    float sensorType = 1000.0; // kPa
    float pressure; // final pressure
    const unsigned long startTime = millis();

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

    void loop() {
      unsigned long elapsedTime = millis() - startTime;
      pressure = (analogRead(sensorPin) - offset) * sensorType / (fullScale - offset);

      Serial.print(analogRead(sensorPin));
      Serial.print("\t\t");
      Serial.print(elapsedTime / 1000.0);
      Serial.print("\t\t");
      Serial.println(pressure, 4);
      delay(1000);
    }
the pressure is 0 but i keep getting jumps in the readings of the pressure when no pressure is applied. here is the picture of the wiring. [![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/KCLQC.jpg

body:
As jsotola mentions in the comments, you should definitely verify that the pressure sensor works with a multimeter first, preferably on a bench that has a variable power supply from which you can power your sensor. Make sure that you can measure the pressure you are putting into the sensor by some other means; a simple pressure gauge could work.

Then, you'll have to correct your equation - it is flipped, since the graphs show the pressure as an input and an output as a voltage, but when you're converting a voltage to a pressure, the process is flipped, so we calculate the slope as follows: take the pressure range (output) and divide it by the voltage range (input) -> 1.1 MPA / 4.4 V = 0.25 V_in. Now, we know that at 0.6V, the pressure output is -0.1 MPA, so we set up a linear equation of the form that you did -> y = mx + b and plug in the values: -0.1 MPA = 0.25 MPA/V * (0.6V) + b. If you solve for b, you'll get -0.25.

Therefore, pressure = 0.25X - 0.25 should be the equation that you check the pressure you're putting into the sensor against the voltage that you are measuring.

If you discover that with this equation you're measuring the right pressure, but once you re-implement your Arduino program you still have no luck, I'd check that the grounds are wired together correctly - it's crucial to have all of the involved grounds at the same 'level'. As a bonus, depending on the Arduino, you could utilize the chip's differential ADC channels, but as far I know, you'd have to write directly to registers to do that.


message:
Why does my Arduino stop uploading to the Thingspeak server after several hours?

I'm using a Maduino Zero 4G SIM7600 device to upload data from 28 sensors to a ThingSpeak IoT server. It works well for a few hours, then stops uploading the data. Sometimes it starts again after an inconsistent amount of time (an hour or two), sometimes it doesn't.

I can confirm that it's only the SIM7600 and/or Thingspeak functions that are failing, as the serial monitor demonstrates the other I2C related operations on the Arduino board are still working fine even when the server uploads fail.

Here's the relevant part of the code:

```
void setup(){
    SerialUSB.begin(115200);
    SerialUSB.println("Serial initialized");
    Serial1.begin(115200);
    Wire.begin();

    pinMode(LTE_PWRKEY_PIN, OUTPUT);
    digitalWrite(LTE_RESET_PIN, LOW);
    delay(100);
    digitalWrite(LTE_PWRKEY_PIN, HIGH);
    delay(2000);
    digitalWrite(LTE_PWRKEY_PIN, LOW);

    pinMode(LTE_FLIGHT_PIN, OUTPUT);
    digitalWrite(LTE_FLIGHT_PIN, LOW);//Normal Mode

    delay(5000);

    sendData("AT+CCID", 3000, DEBUG);
    sendData("AT+CREG?", 3000, DEBUG);
    sendData("AT+CGATT=1", 1000, DEBUG);
    sendData("AT+CGACT=1,1", 1000, DEBUG);
    sendData("AT+CGDCONT=1,\"IP\",\"sp.mb.com\"", 1000, DEBUG);

    delay(5000);
}

void loop(){
  getData();

  //Sensors 0-6
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey1 + "&field1=" + (String)hallData[0] + "&field2=" + (String)hallData[1] + "&field3=" + (String)hallData[2] + "&field4=" + (String)hallData[3] + "&field5=" + (String)hallData[4] + "&field6=" + (String)hallData[5] + "&field7=" + (String)hallData[6] + "\"\r\n";
  SerialUSB.print("Sent to Channel 1: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 7-13
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey2 + "&field1=" + (String)hallData[7] + "&field2=" + (String)hallData[8] + "&field3=" + (String)hallData[9] + "&field4=" + (String)hallData[10] + "&field5=" + (String)hallData[11] + "&field6=" + (String)hallData[12] + "&field7=" + (String)hallData[13] + "\"\r\n";
  SerialUSB.print("Sent to Channel 2: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 14-20
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey3 + "&field1=" + (String)hallData[14] + "&field2=" + (String)hallData[15] + "&field3=" + (String)hallData[16] + "&field4=" + (String)hallData[17] + "&field5=" + (String)hallData[18] + "&field6=" + (String)hallData[19] + "&field7=" + (String)hallData[20] + "\"\r\n";
  SerialUSB.print("Sent to Channel 3: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 21-27
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey4 + "&field1=" + (String)hallData[21] + "&field2=" + (String)hallData[22] + "&field3=" + (String)hallData[23] + "&field4=" + (String)hallData[24] + "&field5=" + (String)hallData[25] + "&field6=" + (String)hallData[26] + "&field7=" + (String)hallData[27] + "\"\r\n";
  SerialUSB.print("Sent to Channel 4: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);
}

String sendData(String command, const int timeout, boolean debug){
  String response = "";
  Serial1.println(command);

  long int time = millis();
  while ( (time + timeout) > millis()){
    while (Serial1.available()){
      char c = Serial1.read();
      response += c;
    }
  }
  if (debug){
    SerialUSB.print(response);
  }
  return response;
}
```

All SIM7600 related operations are taken directly from the Makerfabs examples, found on [this page][1]. One thing of note is that in their example, they use the command `AT+HTTPACTION=0`, which, according to [this page][2], means READ. This does work but it sometimes returns ERROR instead of OK. I've changed it to `AT+HTTPACTION=1`, which means POST, which seems to work a bit better - at least there are no ERROR messages. But the same problem still persists.

UPDATE #1: The ERROR messages sometimes return even with the `AT+HTTPACTION=1` adjustment. Something I've noticed is that generating new API keys for each of the Thingspeak pages (there are 4 in total, 7 sensors per page) causes it to work for a while when it didn't before. No explanation for why that is.

Any advice would be greatly appreciated.

Hardware wise, I'm powering this from an AC adapter through a DC-DC 5V converter. I'm also using a 3.7 battery for backup power.

  [1]: https://github.com/Makerfabs/Maduino-Zero-4G-LTE/blob/main/example/4G_HTTP_DHT11_V1.0/4G_HTTP_DHT11_V1.0.ino
  [2]: https://m2msupport.net/m2msupport/athttpaction-perform-getposthead-http-action/

body:
From the [ThingSpeak License Options page][1]:

> ThingSpeak is available as a free service for non-commercial small projects (<3 million messages/year or ~8,200 messages/day).

Could you be hitting that limit?

  [1]: https://thingspeak.com/prices


message:
SoftwareSerial and HardwareSerial lost data

I need two Serial ports. One port is some sort of modified Software Serial, where I have to be listening constantly and send responses immediately if the port requires it. There is no XY problem hidden here, promise.

On the other hand I have a device on the hardware serial.

If I'm listening on the Software Serial, sometimes I lose data on the hardware serial. How can this be? Isn't the Hardware Serial "hardware", meaning independent of the CPU?

body:
Software Serial turns off interrupts. Depending on the baud rate, they may be off for so long that the interrupt generated by the hardware serial is not serviced in time. Depending on the chip, the hardware serial may only have a buffer of a couple of bytes. Turn off interrupts long enough and one will be lost.

The external interrupts are higher priority than the UART interrupts, which won't help. I am referring to the Uno here.

**It would help** in future if you provide code to reproduce the situation, and also state what Arduino you are using. The lack of information about that in the question would be why you were downvoted.


message:
HardwareSerial and SoftwareSerial not compatible

The HardwareSerial requires to run an interrupt to store received bytes in the buffer. Look at [this][1] file from the Arduino Core.
If I am now constantly receiving and writing on the Software Serial, the data from the HardwareSerial cannot be buffered, since external interrupts are higher priority.

In my application, I need to constantly listen to the SoftwareSerial and respond immediately to incoming data (actually inside the receive interrupt of the SoftwareSerial, so its modified), so the SoftwareSerial has higher priority. But when I do this, I lose data on the HardwareSerial.

Is there any way to circumvent this limitation, without disabling any interrupts or getting a chip with more UART ports?

EDIT: the actual interrupt vector is [here][2]

EDIT2: This is question is not answered by the answers in my previous question. It is clearly a fact that HardwareSerial needs its receive interrupt to store data in a buffer. My question now is how I can still use the SoftwareSerial while it is constantly receiving.

  [1]: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial_private.h
  [2]: https://github.com/arduino/ArduinoCore-avr/blob/eabd762a1edcf076877b7bec28b7f99099141473/cores/arduino/HardwareSerial0.cpp

body:
If you are sending something in SoftwareSerial ISR handler that means ISRs are disabled and you are blocking other ISRs being called (if needed).

If you're using some crazy slow baudrate like 9600 then it means over 1 millisecond per character sent and during that time you might be missing other interrupts calls (millis, HW serials). If there is only one character, it's not problem, it'll be handled after interrupts are enabled again, but if there will be second or more character, previous are lost, as the've never been readed out from the UDR register (that should set flag for buffer overrun or how it's called).

If your Hw serial has some nice speed like 115200, you can lose up to 12 characters during sending single characted on software serial with speed 9600

The cli() in [software serial library](https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.cpp#L436C22-L436C22) but as you wrote it's called from ISR handler and the ISRs are disabled anyway already during whole ISR handler


message:
ESP8266 seems to be killing a while loop

When i was testing out a program I found a strange behavior of esp8266

It seems to get out of a while loop even when there's no option of getting out on code

I don't know if these are related but here's the code
(the program is just two different visual patterns of leds toggled by a button)
```
#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
unsigned long previousTime;
unsigned int difference;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop(){
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);         //when the while loop change, this should delete interference
  digitalWrite(led4, LOW);
  previousTime = millis();

  while (!change){                                      //default visual pattern of leds
    difference = millis()-previousTime;

    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference>=400){
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference>=800){         //after here, all the leds should be HIGH
      digitalWrite(led4, HIGH);
    }
    if (digitalRead(led4) && difference>=1000){
      digitalWrite(led4, LOW);
    }
    if (digitalRead(led3) && difference>=1200){
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led2) && difference>=1400){
      digitalWrite(led2, LOW);
    }
    if (digitalRead(led1) && difference>=1600){        //after here, all the leds should be LOW
      digitalWrite(led1, LOW);
      previousTime = millis();
    }

    if (!digitalRead(button) && millis()-pressedButton>200){       //check if button was pressed to break while loop
      pressedButton = millis();
      break;
    }
  }

  while (change){                                         //alternative of visual pattern of leds
    difference = millis()-previousTime;

    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
      digitalWrite(led4, HIGH);
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference>=400){
      digitalWrite(led1, LOW);
      digitalWrite(led4, LOW);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      previousTime = millis();
    }

    //if (!digitalRead(button) && millis()-pressedButton>=200){     //check if button was pressed to break while loop
    //  pressedButton = millis();
    //  break;
    //}
  }

  change = !change;         //after a break in one of the while loops, this will make the program go to the other while loop
 }

```
Is there something wrong with the code?
Here is a link of a video of the behavior for more details
https://drive.google.com/file/d/1822MHNGQn-A2-HGHhRXz_8xydz-wM4Ha/view?usp=sharing

body:
You can't trap an ESP in a while loop like that. There are things it needs to get back to main and do between loops. Instead, let the loop function be your loop. Make the while statements if statements and where you have break, that's where you change the change variable. Put the code at the top in an if statement that checks to see if change has changed.

    #define led1 D0
    #define led2 D1
    #define led3 D2
    #define led4 D3
    #define button D7

    unsigned long pressedButton;
    bool change = 0;
    bool oldChange = 1;
    unsigned long previousTime;
    unsigned int difference;

    void setup() {
      pinMode(led1, OUTPUT);
      pinMode(led2, OUTPUT);
      pinMode(led3, OUTPUT);
      pinMode(led4, OUTPUT);
      pinMode(button, INPUT_PULLUP);
    }

    void loop() {
      if (change != oldChange) {
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        digitalWrite(led3, LOW);  //when the while loop change, this should delete interference
        digitalWrite(led4, LOW);
        previousTime = millis();
        oldChange = change;
      }

      if (!change) {  //default visual pattern of leds
        difference = millis() - previousTime;

        if (!digitalRead(led1) && difference >= 200) {
          digitalWrite(led1, HIGH);
        }
        if (!digitalRead(led2) && difference >= 400) {
          digitalWrite(led2, HIGH);
        }
        if (!digitalRead(led3) && difference >= 600) {
          digitalWrite(led3, HIGH);
        }
        if (!digitalRead(led4) && difference >= 800) {  //after here, all the leds should be HIGH
          digitalWrite(led4, HIGH);
        }
        if (digitalRead(led4) && difference >= 1000) {
          digitalWrite(led4, LOW);
        }
        if (digitalRead(led3) && difference >= 1200) {
          digitalWrite(led3, LOW);
        }
        if (digitalRead(led2) && difference >= 1400) {
          digitalWrite(led2, LOW);
        }
        if (digitalRead(led1) && difference >= 1600) {  //after here, all the leds should be LOW
          digitalWrite(led1, LOW);
          previousTime = millis();
        }

        if (!digitalRead(button) && millis() - pressedButton > 200) {  //check if button was pressed to break while loop
          pressedButton = millis();
          change = true;
        }
      }

      if (change) {  //alternative of visual pattern of leds
        difference = millis() - previousTime;

        if (!digitalRead(led1) && difference >= 200) {
          digitalWrite(led1, HIGH);
          digitalWrite(led4, HIGH);
          digitalWrite(led2, LOW);
          digitalWrite(led3, LOW);
        }
        if (digitalRead(led1) && difference >= 400) {
          digitalWrite(led1, LOW);
          digitalWrite(led4, LOW);
          digitalWrite(led2, HIGH);
          digitalWrite(led3, HIGH);
          previousTime = millis();
        }
      }

      change = false
    }


message:
Stack Mega Shield

I need to support 18 push buttons and 66 IR sensors on my Arduino Mega (model railway). I have a Mega Sensor Shield, but won't have enough pins for all the sensors. Can I get a second sensor shield and nest it some way?

https://www.aliexpress.com/item/1005004554959620.html?spm=a2g0o.order_list.order_list_main.31.1cda18022wJnOM

body:
I may be interpreting your question wrong, but it seems that you're asking if you can somehow get more input pins for your sensor (general-purpose input/output), with which your sensor shield will not help with that. If you want to get more inputs for your sensors, you'll need to use shift registers.

[Link to understanding how to add more digital GPIO pins][1]

  [1]: https://www.digikey.com/en/maker/blogs/2022/how-to-add-more-digital-gpio-pins-to-arduino-projects-using-shift-registers#:~:text=Using Shift Registers to Add,inputs of the register IC.


body:
For a model railway, this may not work as well as you are expecting. Sending 66 sensors values and 18 push-buttons along long cable lengths, as may be expected for a model railway, could introduce noise which would give bogus readings. The noise in long, adjacent, cables could be from one cable inducing a voltage in its neighbour, or simply from the railway operations themselves.

It may be better to use something like [RS485](https://en.wikipedia.org/wiki/RS-485) which is a balanced protocol. That is, of the two data wires connecting nodes, one is positive and one is negative simultaneously, for a signal to be considered genuine. Noise would tend to influence the cables in the same direction (eg. both positive) and would thus be discarded.

As described in the [Wikipedia article](https://en.wikipedia.org/wiki/RS-485), RS485 is used in aircraft for reliability. The wiring is minimal: two wires for data, plus an earth wire. You would also need 5V power available at the nodes.

What I would suggest here is a series of nodes, spread around your railway layout. Each node could be an inexpensive Atmeg328P processor (around $3 on eBay) with a couple of supporting resistors and capacitors. You would use 3 pins for the RS485 (transmit, receive and enable) which would leave 17 inputs for your sensors and switches per node. Thus, around 5 nodes.

You would keep the cabling for the sensors running to each node as short as possible, to reduce noise. Maybe use shielded cable.

I wrote an [RS485 non-blocking library](https://github.com/nickgammon/RS485_non_blocking) - available on Github.

There are some explanations about using it [on my website](https://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=11428) most of which is also on the Github page.

Basically what you would do is give each node an address (stored in EEPROM) and then have a master query each node in turn for the values on its sensors or switches. The node would reply, and then the master could move onto the next one.

---

I realise this isn't directly answering the question about the Mega shield, but I am trying to answer the underlying problem of how to connect 84 sensors and switches to one Arduino reliably.


message:
sim800l gsm module response isn't completed

I am using the `sim800l gsm module` with `nodemcu esp8266` and comunicating with it using AT+ commands. The module is working correctly but I am trying to use the command `AT+CLCC` to get all the current calls' state but it responds with only the first call information and a part of the second call.

This is the response while there are two active calls
```
15:37:19.156 -> AT+CLCC
15:37:19.156 -> +CLCC: 1,0,1,0,0,"+0123456789",145,"name"
15:37:19.156 ->
15:37:19.156 -> +CLCC: 2,
```
I think it is the Serial buffer's problem because the size of the serial buffer is 64 bytes and the response is more than that but I don't know how to handle that

I hope someone can help.

EDIT: this is the code i am using

```
#include <SoftwareSerial.h>
#include <cstring>

#include <Arduino.h>

#define simTX D3
#define simRX D4

SoftwareSerial sim800l(simRX, simTX);  //RX, TX

void setup() {

  Serial.begin(115200);  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)

  sim800l.begin(115200);  //Begin serial communication with Arduino and SIM800L

}

void loop() {

  updateSerial();

}

//Start
// this method takes input from the serial monitor the pass it to sim800l via serial communication
void updateSerial() {
  delay(500);
  while (Serial.available()) {
    sim800l.write(Serial.read());  //Forward what Serial received to Software Serial Port
  }
  while (sim800l.available()) {
    Serial.write(sim800l.read());  //Forward what Software Serial received to Serial Port
  }
}
//End
```

body:
Just for someone in the future who is having the same issue.

the problem was because of the boadrate 115200 is pretty fast for a software serial implementation so i just changed it to 9600

```
 sim800l.begin(9600);  //Begin serial communication with Arduino and SIM800L
```

good luck from the past :)


message:
Connecting Arduino to a cheap Graphics Card for VGA Output

**I understand that** the Arduino is generally not fast or powerful enough to generate a suitable VGA/HDMI signal with higher resolution.

However, I've noticed that there are **inexpensive PC graphics cards** available that can easily maintain a stable screen on a monitor.

----

Back in the DOS era, it was relatively straightforward to write a short program that could output text to CGA/EGA/VGA cards using BIOS calls and a few assembly instructions. The BIOS itself surely was not overly complex or large.

---

So my idea is to take an Arduino, use shift registers like the 74HC595 to create a sufficiently long bus, and connect it to a cheap, obsolete GPU (e.g., an NVIDIA card from a discarded PC) along with a regular monitor. I would then write Arduino code to emulate a BIOS call, such as 10h, which would shift out the "bus status" to the 74HC595s, send the signal to the GPU, and continue this process until the characters are transferred to the GPU.

The GPU can easily generate VGA/HDMI signals and work with any modern monitor. It also has enough memory to support screen resolutions like 80x25, 80x50, or even 132x60 for text-based displays. In fact, it might even be possible to run at full graphical resolutions such as 640x480 or even 2560x1440, with the Arduino slowly sending graphic primitives to display.

While the GPU's performance would be severely degraded, it would still be a better alternative than throwing it away.

-----

**My question** is whether it is possible or even feasible to connect a GPU to such a slow source. If it is, I would like to know if there are any readily available and understandable documentation or even someone who has already attempted this approach.

(Or should I post it somwere else? Where?)

body: This doesn't answer your question about the cheap graphics card, but see https://forum.arduino.cc/t/toorums-quest-ii-atmega328p-based-retro-video-game-with-256-color-graphics/192920 for where Petri Häkkinen did an arcade-style game with an Atmega328 and the AD725 chip for generating the VGA signal.


message:
TMC2208 Stepper Motor does not change its RPM linearly

This is my first project working with stepper motors, so I may have a bit of a shaky understanding of the electronic side of the project. I'm trying to create a simple device with 4 buttons connected to a stepper motor driver/NEMA 17 motor, with the ability to increase/decrease RPM, switch motor spin direction, and run the motor with the button being held down. (LCD screen included for output as well)

I'm noticing that when changing the RPM on my motor, i.e. from 3.2 to 3.1 to 3.0, the speed of the motor is really slow, then when set to 3.0, suddenly increases a lot, but goes down when setting the RPM back down to 2.8 or so. This occurs multiple times along different intervals of RPMs that I have tested as well.

I think that there may be an issue with the method with which I am calculating the pulse delay given the RPM in my function `setRPM()` at the end of my code or with the way that I am micro-stepping, which I am doing because I need extremely precise movement.

Included below is the code that I used to run with my TMC2208 driver. (Sorry if it is rather long, but I included comments to document my thought process when programming the Arduino.)

Included list of RPMs and pulse delays

| rpm | pulse_delay (us)   |
|:---:|:------------------:|
| 1   | 37500 (too fast)   |
| 2   | 18750 (too fast)   |
| 2.25| 16666.6667 (works) |
| 2.5 | 15000  (works)     |
| 3   | 12500  (works)     |
| 5   | 7500   (works)     |
| 10  | 3759   (works)     |

```c
// Stepper motor run code with TMC2208 driver and LCD code
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Stepper.h>
// Define Pins for Step Motor Driver
#define stepPin 7  // define pin for step
#define dirPin 8   // define pin for direction
#define enPin 9    // define pin for enable ^^ Do I need this?

// Define Buttons for Speed and Direction
#define buttGo 10      // define pin for button input
#define buttSwitch 11  // define pin for button input
#define incSpeed 12    // define button for increasing speed
#define decSpeed 13    // define button for decreeasing speed

// Define LCD pinout
const int en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;  // Adapter Pinout
const int i2c_addr = 0x27;                                                 // Adapter pinout
LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

/* Formulas for determining RPM
Assuming one step per pulse, delay is: wait = (μs/min)*(1/rpm)*(1/pulses per revolution) - overhead
Overhead = extra time it takes to run digitalWrite twice and loop
RPM = (steps per second)/(steps per revolution) * (60 seconds/minute)
step angle = 1.8 degrees ; 200 steps per revolution ; .005 revolutions per step
Solving for Steps Per Second: SPS = (RPM)/((REV_P_STEP)*(60 sec/min))

According to Notes:
  C0 = 15 * M_PI ; Motor X Circumference
  XSPR = 1 * (200 * 11) ; Motor X Steps per Rotation
  dVx = dS * (XSPR/C0) ; Desired X-Axis time from mm/s to x-axis steps/sec (dS represents desired x-axis speed)
  Assuming we use a button/knob, each increment/decrement would change the mm/s by 0.1
  So, to get the necessary pulse delay, increment/decrement by:
    dVx = 0.1 * (1 * (200 * 11))/(15*M_PI)

  Example: If we have an initial target rpm of 10, that gives us a dS of 10
  As such, dVx which is our speed in steps will be 10 * (1 * (200 * 11)) / (15 * M_PI)
  All of these variables are set globally
  wait = (microsecondsPminute)*(1/RPM)*(1/pulsesPrevolution) - overhead
  rpm / 60 = rps
  60 / rpm = spr
  (60 / rpm)/360 = spd
  ((60 / rpm)/360) * 1.8 = sps
***
Frequency = (RPM)/((Resolution/360)*60)
Resolution =  360/(Steps/Revolution)
For us, Resolution = 360/(200); so Resolution = 1.8**
Frequency = (RPM)/(0.005 * 60) = RPM/(0.3)
*
T_inc = incremental torque produced with each microstep
T_hfs = holding torque (full-step operation)
SDR = step division ratio (number of microsteps per full step)

T_inc = T_hfs * sin(90/SDR)
T_inc = 0.14 * sin(90/256)
T_inc = 0.00085902385
*/
float resolution = 1.8;
float rpm = 10;
float pulse_delay;  // Temporary starting value that will change after void setup
bool buttonState = false;
bool onState = false;

// Set up output types
void setup() {
  Serial.begin(9600);  // Change this baud rate to whatever rate the LCD screen runs on - should generally be 9600
  // Set up LCD screen
  pulse_delay = setRPM(rpm, resolution);
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.setCursor(0, 0);
  lcd.print("Current RPM: ");
  lcd.setCursor(12, 0);
  lcd.print(rpm);
  lcd.setCursor(0, 1);
  lcd.print("MOVE RIGHT");

  // Sets up buttons
  pinMode(buttSwitch, INPUT);
  pinMode(buttGo, INPUT);
  pinMode(incSpeed, INPUT);
  pinMode(decSpeed, INPUT);

  // Establish initials
  pinMode(enPin, OUTPUT);
  digitalWrite(enPin, HIGH);  // deactivate driver
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, HIGH);
  pinMode(stepPin, OUTPUT);
  digitalWrite(enPin, LOW);  // activates driver
}

// Revolutions per second should be able specified to the tenths
// Run code to continual
void loop() {
  // Read Buttons Being Pressed
  int pressSwitch = digitalRead(buttSwitch);
  int pressGo = digitalRead(buttGo);
  int pressInc = digitalRead(incSpeed);
  int pressDec = digitalRead(decSpeed);
  pulse_delay = setRPM(rpm, resolution);  //pulse_delay = (rpm * 200)/60;

  if (pressSwitch == HIGH)  // Moves motor Right (Counter-Clockwise)
  {
    if (buttonState == 0) {
      digitalWrite(dirPin, LOW);  // sets direction of the motor turning
      buttonState = 1;
      lcd.setCursor(0, 1);
      lcd.print("MOVE  LEFT");
      delay(500);
    }
    else {
      if (buttonState == 1) {
        digitalWrite(dirPin, HIGH);  // sets direction of the motor turning
        buttonState = 0;
        lcd.setCursor(0, 1);
        lcd.print("MOVE RIGHT");
        delay(500);
      }
    }
  }

  if (pressGo == HIGH)  // Moves motor
  {
    digitalWrite(stepPin, HIGH);  // This LOW to HIGH change is what creates the "Rising Edge" so the easydriver knows when to step.
    delayMicroseconds(pulse_delay);
    digitalWrite(stepPin, LOW);
  }

  if (pressInc == HIGH)  // Increases RPM
  {
    rpm = rpm + 0.1;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }

  if (pressDec == HIGH)  // Decreases RPM
  {
    rpm = rpm - 0.1;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }
}

// Function to get pulse delay time based off of inputted RPM value
float setRPM(float rpm, float resolution) {
  /*
  float temper = ((60 / rpm) / 360);
  float pulsetime = ((temper * resolution) * 1000000);
  1 rpm = 37500 us delay (too fast)
  2 rpm = 18750 us delay (too fast)
  2.25 rpm = 16666.6667 us delay
  2.5 rpm = 15000 us delay
  3 rpm = 12500 us delay
  5 rpm = 7500 us delay
  10 rpm = 3750 us delay
  */
  unsigned int pulsetime = (60000000 / (1600 * rpm));
  return pulsetime;  // Converts to microseconds
}
```

body:
[The documentation][1] says:

> Currently, the largest value that will produce an accurate delay is 16383; larger values can produce an extremely short delay.

The value given to `delayMicroseconds()` seems to be processed by a modulo 16384 operation. That means that the value is divided by 16384, and the remainder of this division is the effective delay in microseconds.

If we apply this to the delays in your table, we get:

|desired rpm|calculated delay (µs)|effective delay (µs)|effective rpm|
|-|-|-|-|
|1|37500|4732|7.9|
|2|18750|2366|15.8|
|2.25|16666|16666|2.25|
|2.5|15000|15000|2.5|
|3|12500|12500|3|
|5|7500|7500|5|
|10|3750|3750|10|

One possible solution is presented in the same documentation:

> For delays longer than a few thousand microseconds, you should use `delay()` instead.

You might want to consider to use both functions, depending on the necessary delay.

---

And then there is the other issue with the time when the output is low. Currently, it is determined by the time the code takes to quit `loop()`, do its internal looping, call `loop()` and your statements until the pin goes high again.

You might want to divide the pulse period in two halves and take control of this low phase, too.

  [1]: https://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/


body:
For reference for any future readers who have had similar problems using a TMC2208 Stepper Motor - I have attached my annotated code to this answer for your use. In the annotation, I also include equations that can be used to determine spacings for a coiling setup.

```
// Stepper motor run code with A4988 driver and LCD code
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Stepper.h>
// Define Pins for Step Motor Driver
#define stepPin 7  // define pin for step
#define dirPin 8   // define pin for direction
#define enPin 9    // define pin for enable ^^ Do I need this?

// Define Buttons for Speed and Direction
#define buttGo 10      // define pin for button input
#define buttSwitch 11  // define pin for button input
#define incSpeed 12    // define button for increasing speed
#define decSpeed 13    // define button for decreeasing speed

// Define LCD pinout
const int en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;  // Adapter Pinout
const int i2c_addr = 0x27;                                                 // Adapter Pinout
LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

/* Formulas for determining RPM
Assuming one step per pulse, delay is: wait = (μs/min)*(1/rpm)*(1/pulses per revolution) - overhead
Overhead = extra time it takes to run digitalWrite twice and loop
RPM = (steps per second)/(steps per revolution) * (60 seconds/minute)
step angle = 1.8 degrees ; 200 steps per revolution ; .005 revolutions per step
Solving for Steps Per Second: SPS = (RPM)/((REV_P_STEP)*(60 sec/min))

According to John Craig:
  C0 = 15 * M_PI ; Motor X Circumference
  XSPR = 1 * (200 * 11) ; Motor X Steps per Rotation
  dVx = dS * (XSPR/C0) ; Desired X-Axis time from mm/s to x-axis steps/sec (dS represents desired x-axis speed)
  Assuming we use a button/knob, each increment/decrement would change the mm/s by 0.1
  So, to get the necessary pulse delay, increment/decrement by:
    dVx = 0.1 * (1 * (200 * 11))/(15*M_PI)

  Example: If we have an initial target rpm of 10, that gives us a dS of 10
  As such, dVx which is our speed in steps will be 10 * (1 * (200 * 11)) / (15 * M_PI)
  All of these variables are set globally
  wait = (microsecondsPminute)*(1/RPM)*(1/pulsesPrevolution) - overhead
  rpm / 60 = rps
  60 / rpm = spr
  (60 / rpm)/360 = spd
  ((60 / rpm)/360) * 1.8 = sps
***
*Assume from measured diameter with calipers that it is 12 mm (Check 11.85 as well)
To get Spacings: V_extruder / RPM_rod
V_extruder = M_PI * Diam_extruder * RPM_extruder (in (mm*rev)/min)
RPM_rod = 13 rpm (set from original bought parts)
V_extruder = M_PI * 12 mm * X
Spacing = (M_PI * 12 * X) / 9.64507699 RPM
Spacing = 3.90863773 * X
For Spacings of 3 mm... 0.76753084 rev/min ~= 0.77 rev/min
For Spacings of 5 mm... 1.27921807 rev/min ~= 1.28 rev/min
For Spacings of 7 mm... 1.79090529 rev/min ~= 1.79 rev/min
*
y = 1.0715x + 2.6653
y = Voltage Setting
x = RPM
For Voltage Setting of 13, RPM = 9.64507699

T_inc = incremental torque produced with each microstep
T_hfs = holding torque (full-step operation)
SDR = step division ratio (number of microsteps per full step)

T_inc = T_hfs * sin(90/SDR)
T_inc = 0.14 * sin(90/256)
T_inc = 0.00085902385
*/
float resolution = 1.8;
float rpm = 3;
unsigned int pulse_delay;  // Temporary starting value that will change after void setup
bool buttonState = false;
bool onState = false;

// Set up output types
void setup() {
  Serial.begin(9600);  // Change this baud rate to whatever rate the LCD screen runs on - should generally be 9600
  // Set up LCD screen
  pulse_delay = setRPM(rpm);
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.setCursor(0, 0);
  lcd.print("Current RPM: ");
  lcd.setCursor(12, 0);
  lcd.print(rpm);
  lcd.setCursor(0, 1);
  lcd.print("MOVE RIGHT");

  // Sets up buttons
  pinMode(buttSwitch, INPUT);
  pinMode(buttGo, INPUT);
  pinMode(incSpeed, INPUT);
  pinMode(decSpeed, INPUT);

  // Establish initials
  pinMode(enPin, OUTPUT);
  digitalWrite(enPin, HIGH);  // deactivate driver
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, HIGH);
  pinMode(stepPin, OUTPUT);
  digitalWrite(enPin, LOW);  // activates driver
}

// Revolutions per second should be able specified to the tenths
// Run code to continual
void loop() {
  // Read Buttons Being Pressed
  int pressSwitch = digitalRead(buttSwitch);
  int pressGo = digitalRead(buttGo);
  int pressInc = digitalRead(incSpeed);
  int pressDec = digitalRead(decSpeed);
  pulse_delay = setRPM(rpm);  //pulse_delay = (rpm * 200)/60;

  if (pressSwitch == HIGH)  // Moves motor Right (Counter-Clockwise)
  {
    if (buttonState == 0) {
      digitalWrite(dirPin, LOW);  // sets direction of the motor turning
      buttonState = 1;
      lcd.setCursor(0, 1);
      lcd.print("MOVING  LEFT");
      delay(500);
    } else {
      if (buttonState == 1) {
        digitalWrite(dirPin, HIGH);  // sets direction of the motor turning
        buttonState = 0;
        lcd.setCursor(0, 1);
        lcd.print("MOVING RIGHT");
        delay(500);
      }
    }
  }
// Both of the next functions move the motor, but switches between Microseconds and Milliseconds in delay time to fit.
  if (pressGo == HIGH && pulse_delay >= 16383)  // Moves motor
  {
      digitalWrite(stepPin, HIGH);  // This LOW to HIGH change is what creates the "Rising Edge" so the easydriver knows when to step.
      delay(pulse_delay/1000);
      digitalWrite(stepPin, LOW);
  }

  if (pressGo == HIGH && pulse_delay < 16383)
  {
      digitalWrite(stepPin, HIGH);  // This LOW to HIGH change is what creates the "Rising Edge" so the easydriver knows when to step.
      delayMicroseconds(pulse_delay);
      digitalWrite(stepPin, LOW);
  }

  if (pressInc == HIGH)  // Increases RPM
  {
    rpm = rpm + 0.01;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }

  if (pressDec == HIGH)  // Decreases RPM
  {
    rpm = rpm - 0.01;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }
}

// Function to get pulse delay time based off of inputted RPM value
float setRPM(float rpm) {
  /*
  float temper = ((60 / rpm) / 360);
  float pulsetime = ((temper * resolution) * 1000000);
  1 rpm = 37500 us delay (too fast)
  2 rpm = 18750 us delay (too fast)
  2.25 rpm = 16666.6667 us delay
  2.5 rpm = 15000 us delay
  3 rpm = 12500 us delay
  5 rpm = 7500 us delay
  10 rpm = 3750 us delay
  */
  unsigned int pulsetime = (60000000 / (1600 * rpm));
  return pulsetime;  // Converts to microseconds
}

```


message:
How to estimate the storage room for txt file when writing data to SD card module?

I'm planning to use Arduino UNO to do some measurements and record it in a SD card module. The measurements is going to last for a year or 20 month. I need some advice on how to estimate how long can the SD card storage last without overflow. Right now I'm doing measurements every second, each second contains 13 lines of data, each line is roughly 30 characters. How big is the txt file gonna be if I left the Arduino unit recording for a year?

body:
This is just a multiplication problem.

13 lines times 30 characters is 390 bytes per measurement.

There are 86400 seconds in one day.

86400 * 390 = 33,696,000

So that's around 34 megabytes per day.

After 1 year it would be:

365 * 33.696 = 12299 MB or a little more than 12 GB.


body: What type of SD card are you using? Based on the capacity, you can calculate SD card storage time to overflow with data/second. Since a character has a size of one byte, the amount of data used per day should be 30 * 13 * 86400 (sec/day) = 33696000 bytes or 0.033696 gb per day.


message:
Trying to resolve invalid conversion from 'byte' {aka 'unsigned char'} to

I'm trying to use an existing Arduino library on the Raspberry Pi Pico.  The library is here:

https://github.com/j-bellavance/EdgeDebounce/tree/master

It's based on some interesting insight at Jack Ganssel's blog:
http://www.ganssle.com/debouncing.htm

The library works great on an ATMega 328, but I got two errors when changing to the Raspberry Pi Pico.

The first one was resolved by editing the last line of EdgeDebounce.h like this:

    //#endif;  // Arduino ATMega version
    #endif   // Pico version, also works on ATMega

The second is a bit more complex.  Here's the relevant section of code, these are lines 78 - 102 in EdgeDebounce.cpp :

      byte EdgeDebounce::debounce(byte pin) {
      unsigned long pinStatus;
      do {
        pinStatus = 0xffffffff;
        for (byte i = 1; i <= MYsensitivity; i++) pinStatus = (pinStatus << 1) | digitalRead(pin);
      } while ((pinStatus != debounceDontCare) && (pinStatus != 0xffffffff));
      return byte(pinStatus & 0x00000001);
    }//debounce------------------------------------------------------------------------------------------------

    //updateStatus===================================================================
    //After releasing EdgeDebounceLite, I realized that EdgeDebounce could do more
    //With this small piece of code, EdgeDebounce can return if a switch is
    //  .isclosed();  //Conducting current
    //  .isopen();    //Not conducting current
    //  .rose();      //Just went from open to closed
    //  .fell();      //just went from closed to open
    //-------------------------------------------------------------------------------
    void EdgeDebounce::update() {
      byte newStatus = debounce();
      if (MYmode == PULLUP) newStatus = !newStatus;
      if (MYstatus == OPEN && newStatus == CLOSED) MYrose = true;
      else                                         MYrose = false;
      if (MYstatus == CLOSED && newStatus == OPEN) MYfell = true;
      else                                         MYfell = false;
      MYstatus = newStatus;
    }//update-------------------------------------------------------------------------

When I try to compile, I get this error:

    c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp: In member function 'void EdgeDebounce::update()':
    c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp:102:14: error: invalid conversion from 'byte' {aka 'unsigned char'} to 'pinStatus' [-fpermissive]
      102 |   MYstatus = newStatus;
          |              ^~~~~~~~~
          |              |
          |              byte {aka unsigned char}

    exit status 1

    Compilation error: exit status 1

So I see that the byte of "newStatus" doesn't convert to "pinStatus" which is an unsigned long.  I've done a bunch of Google searches but can't quite figure out what the fix is.

body:
`pinStatus`  is an enum:

    enum pinStatus {OPEN, CLOSED};

The pinStatus you posted is a local variable, nothing to do with `pinStatus` in the EdgeDebounce.h file.

The error is pointing out that you can't assign an unsigned char to an enum which can only hold OPEN and CLOSED. The unsigned char might hold various other values.

Whoever coded that has made some confusing code.


body:
In C and in much pre-standard C++ nothing stops you just assigning an integer value to a variable of enumeration type.  In standard C++ (from 1998 onward) that requires an explicit type conversion (a "cast").

The [AVR Arduino core
supplies](https://github.com/arduino/ArduinoCore-avr/blob/1.8.6/platform.txt#L28)
the `-fpermissive` option to the compiler which among other things allows the implicit
conversion they're doing despite not being standards compliant C++.  Whatever you're using (odds are [this](https://github.com/earlephilhower/arduino-pico/blob/3.3.0/platform.txt) or [this](https://github.com/arduino/ArduinoCore-mbed/blob/4.0.2/platform.txt)) for RPI Pico Arduino core does not provide the `-fpermissive` option. A lot of Arduino cores don't and probably shouldn't.

You *could* modify the RPI Pico core's platform.txt to give the `-fpermissive` option to g++, but it is probably better to make the code compliant.

## Minimal change

There are probably dozens of ways to do this, but a combination of *mimimal* and *pleasing* to C++ nerds probably looks like:

```c++
MYstatus = static_cast<pinStatus>(newStatus);
```

### Alternative Casts

```c++
MYstatus = static_cast<decltype(MYstatus)>(newStatus); // fancier
MYstatus = (pinStatus)newStatus;  // traditional cast
MYstatus = pinStatus(newStatus);  // function-style cast
MYstatus = (decltype(MYstatus))newStatus;  // uhhh
MYstatus = (decltype(MYstatus))(newStatus);  // sure... why not?
```

The `static_cast` declares in intent in a way that other types of cast don't. `decltype` would make that line survive changes to the type of MYstatus better, but `decltype` is not as widely understood.

### Alternately not type-converting at all

You can also observe that `return byte(pinStatus & 0x00000001);` is the [only point of return](https://github.com/j-bellavance/EdgeDebounce/blob/ff33c6/EdgeDebounce.cpp#L84) from
`byte EdgeDebounce::debounce(byte pin)`. So you know this function returns either 0 (false) or 1 (truthy). That's just what's going to happen with applying `& 1`.

They've [defined the enumeration type](https://github.com/j-bellavance/EdgeDebounce/blob/ff33c6/EdgeDebounce.h#L34):
```C++
enum pinStatus {OPEN, CLOSED};
```

The rules of C and C++ (even pre-standard C++) will assign these constants
numeric values 0 and 1, where they weren't explicitly given values and were listed in that order.

So, you could replace `MYstatus = newStatus;` with:

```c++
{
  if (newStatus) {
   MYstatus = CLOSED;
  } else {
   MYstatus = OPEN;
  }
}
```

Or use the ternary operator if you want don't mind people trying to argue with you:

```c++
MYstatus = newStatus ? CLOSED : OPEN;
```


message:
Why this simple serial monitor code not working?

The follwoing code echoes whatever arduino recieves through reciever pin. The idea is that arduino will echo whole data in the buffer on the same line and starting from the new line while echoing the next data recieved in the buffer.

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

    void loop()
    {
      if(Serial.available())
        {
            int count = Serial.available();
            for(int i = 0; i < count; i++)
            {
                char character = Serial.read();
                Serial.print(character);
            }
            Serial.print("\n");
        }
    }

When I run the code it prints the characters line by line. for example if I enter the word "QUICK" it echoes the following

    Q
    U
    I
    C
    K
Whereas I think it should be echoing

    QUICK
Please help me out.

body:
You seem to have the assumption, that the string "QUICK" is send as one package of characters, because you send it with one keypress from the Serial Monitor. But Serial (UART) is a "serial" protocol, meaning, that each byte (aka character for ASCII encoding) is send sequentially.

At 9600 baud each byte will take about 1ms to transmit. Also: small random delays can be introduced by the PC or in the USB communication (if you are communication through a USB to Serial chip, like when you connect the Uno via USB).

Your code runs faster than the data arrives at the Unos microcontroller. The first `if` clause is entered as soon, as there is one byte in your Serial buffer. Then you start reading the data from the buffer, but at that time no further bytes did arrive. So the loop is exited after one iteration.

If you want to process the Serial data line by line, you should send a line ending from the Serial Monitor (or whichever program you are using) via the Line ending option. The common way is to use `\n` aka the newline character as line ending. Then in your code you should read the data until you receive the newline character.

That can be done in multiple ways. One way is to read each arriving character into your own buffer, which is big enough to hold the maximum number of characters, that can occur in your messages. Then, when receiving the newline character you can process the data in the buffer. A variables holds the current position in the buffer:

    unsigned int pos = 0;
    char buffer[20] = ""; // enough space for 19 characters + the null character for terminating the string correctly

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

    void loop(){
      if(Serial.available()){
        char c = Serial.read();
        if(c != '\n'){
          buffer[pos] = c; // Adding the received character to the buffer
          if(pos < sizeof(buffer) - 1){
            // incrementing the position variable to point to the next position in the buffer
            // but only, if there is enough space in the buffer left
            // otherwise this code will overwrite the last character
            pos++;
          }
        } else {
          buffer[pos] = 0; // Terminating the string correctly
          // Process the message here
          Serial.println(buffer);
          // Reset buffer by setting the position back to zero
          pos = 0;
        }
      }
    }

Note: This code needs your `loop()` function to iterate fast enough, so that you won't miss more data, than the internal buffer of Serial can hold (I think 32 characters). So you probably don't want to use long delays (which is nearly always a bad idea anyways, see non-blocking coding and the `millis()` function).


message:
LED doesn't completely turn off with digitalWrite(led, LOW);

When I was testing out a program I found a strange behavior of ESP8266.

LEDs don't turn off completely in the first `digitalWrite(led, LOW)`, just the brightness of the LED goes down, but it does turn off in the second `digitalWrite(led, LOW)`.

I don't know if it's related to the code or the circuit, so here are both (the program is just two different visual patterns of LEDs toggled by a button)
```
#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
unsigned long previousTime = millis();
unsigned int difference;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop(){
  if (!digitalRead(button) && millis()-pressedButton>200){       //check if button was pressed to change visual pattern of leds
      pressedButton = millis();
      change = !change;
      digitalWrite(led1, LOW);         //here led completely turn off
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
      digitalWrite(led4, LOW);
      previousTime = millis();
  }

  difference = millis()-previousTime;

  if (!change){                                     //default visual pattern of leds
    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference>=400){
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference>=800){
      digitalWrite(led4, HIGH);
    }
    if (difference>=1000){
      digitalWrite(led4, LOW);           //the leds just shrink here
    }
    if (difference>=1200){
      digitalWrite(led3, LOW);
    }
    if (difference>=1400){
      digitalWrite(led2, LOW);
    }
    if (difference>=1600){
      digitalWrite(led1, LOW);
      previousTime = millis();
    }
  }

  if (change){                    //alternative pattern
     if (!digitalRead(led1) && difference>=200 && change){
       digitalWrite(led1, HIGH);
       digitalWrite(led4, HIGH);
       digitalWrite(led2, LOW);
       digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference>=400 && change){
       digitalWrite(led1, LOW);
       digitalWrite(led4, LOW);
       digitalWrite(led2, HIGH);
       digitalWrite(led3, HIGH);
       previousTime = millis();
    }
  }
}

````
[![][1]][1]
Actually, it's a NodeMCU Esp8266, with the pins defined on the code and a 470 ohms resistor.  (obs: resistor is not shorted, in my breadboard those rows are separated)

  [1]: https://i.stack.imgur.com/Xf24I.png

body:
<!-- language: lang-c++ -->

    if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference>=800){
      digitalWrite(led4, HIGH);
    }
    if (difference>=1000){
      digitalWrite(led4, LOW);           //the leds just shrink here
    }
    if (difference>=1200){
      digitalWrite(led3, LOW);
    }

Consider what will happen when the difference is >= 1000.

If the LED is off you turn it on (because it passes the first test, the difference is >= 600), and a moment later you turn it off. So the LEDs are being turned on and off in quick succession, which makes them look dim.

Try re-ordering the tests, and add `else` for each subsequent one. That seems to work for me:

<!-- language: lang-c++ -->

      if (!change){                                     //default visual pattern of leds
        if (difference>=1600){
          digitalWrite(led1, LOW);
          previousTime = millis();
        }
        else if (difference>=1400){
          digitalWrite(led2, LOW);
        }
        else if (difference>=1200){
          digitalWrite(led3, LOW);
        }
        else if (difference>=1000){
          digitalWrite(led4, LOW);
        }
        else if (!digitalRead(led4) && difference>=800){
          digitalWrite(led4, HIGH);
        }
        else if (!digitalRead(led3) && difference>=600){
          digitalWrite(led3, HIGH);
        }
        else if (!digitalRead(led2) && difference>=400){
          digitalWrite(led2, HIGH);
        }
        else if (!digitalRead(led1) && difference>=200){
          digitalWrite(led1, HIGH);
        }
      }

---

Also, that resistor on the bottom row isn't achieving anything because all the pins on the bottom row are connected together so it is just shorted out. Not good for the LEDs or the processor.


message:
What is the max output rating of the pins on the Arduino Mega?

I have conflicting information on the max output rating for the Arduino Mega.  Some say 200 mA and others say 800 mA like the Uno board.  I am running 8 model railroad signal devices that have (3) 3mm LEDs (Red, Yellow, and Green) in each signal.  Of the 24 LEDs, only 8 are energized at any point in time.  8*.020 = 160 mA.  I believe I am good, but confused as to why the Uno board with 13 digital output pins can handle 800 mA and the Mega board with 40 or so output pins (not including all the TX RX IO pins) can only handle 200 mA.  Lots of forum discussion on this, but most go over my head without answering the question! LOL

Simply, how many mA can all of the digital pins combined provide?

---

Well theory (math) is nice, and a good starting point, but reality is better.

The signals I am talking about are (model) railroad trackside warning signal devices that have a red, yellow and green light, and depending on which light is lit, tells the train's Engineer if it is safe to continue down the track.

[![Signal][1]][1]

Each of these signals are 2.1/2" in height and the LEDs use 30 gauge wires and a 1K resistor.

I connected the red LED on all 8 signal devices to my variable power supply, turned it on and lit all 8 red LEDs with 5 volts, and wow, all 8 only used .023 amps total.

I then disconnected 7 of them and a single red LED only used .002 - .003 amps.  I connected the rest of the signals one at a time, and 2 signals used .006 amps, 3 signals used .009 amps, 4 signals used .011 amps, 5 signals used .014 amps, 6 signals used .017 amps, 7 signals used .020 amps and all 8 signals again only used .023 amps.

If this is the case, that is less than the max output from a single pin.

So, my plan is to connect the signals to the Arduino Mega 2560 on at a time, monitor the total current the Arduino in using after connecting each signal, and see just how much these signals are using.

  [1]: https://i.stack.imgur.com/6PZ0O.jpg

body:
The answers are right there in the [datasheet](https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf).

The datasheet of the ATMega2560 (and 1280 etc.), page 355, states an absolute maximum current of 200 mA for the ATMega package and 40 mA per I/O pin.

In addition (thank you for the comment, @NickGammon), there are some further restrictions that are described from page 356 of the linked datasheet:

 - The sum of current which can be *sunk* from various ports cannot exceed 100 mA, and from others, 200 mA.
 - The same is true for the amount of current that can be sourced from various ports.

For example, for ports A0-A7 you cannot source a total of more than 100 mA (under steady conditions) and not 40 mA * 8 like you might expect.

So, if you had 8 LEDs on at once, continuously, you would only have 12.5 mA available for each of those ports (for a total of 8 x 12.5 mA = 100 mA).

That means that the 160 mA mentioned in the question could easily be out of spec.

It's not recommended to stay at or near the Absolute Maximum values mentioned in the datasheet for an extended amount of time. It's better to design your solution so that these abolute maximum values are never approached.

For your particular situation I would look into external (TTL) buffers between your Mega and your LEDs.

Alternatively, you could reduce the amount of current through the LEDs to make sure the total amount of current will always stay well below 200 mA or the other limitations mentioned above.


message:
How to turn LEDs based on voltage readings?

I am trying to turn LEDs in an LED bridge based on the voltage reading from a power source. when the Voltage is zero nothing is ON and then the LEDs gradually turn ON as increase the voltage connected to the Ao pin. ( I am using a pro trinket 3V 120 MHZ)

This is my code:

```c++
const int analogPin = A0; // the pin that the potentiometer is attached to
const int ledCount = 7; // the number of LEDs in the bar graph

int ledPins[] = { 3, 4, 5, 6, 8, 9, 10}; // an array of pin numbers to which LEDs are attached

void setup() {
    // loop over the pin array and set them all to output:
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
        pinMode(ledPins[thisLed], OUTPUT);
    }
}

void loop() {
    // read the potentiometer:
    int sensorReading = analogRead(analogPin);
    // map the result to a range from 0 to the number of LEDs:
    int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);

    // loop over the LED array:
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
        // if the array element's index is less than ledLevel,
        // turn the pin for this element on:
        if (thisLed < ledLevel) {
            digitalWrite(ledPins[thisLed], HIGH);
        }
        // turn off all pins higher than the ledLevel:
        else {
            digitalWrite(ledPins[thisLed], LOW);
        }
    }
}
```

However, I am not getting the outcome I want. when there is 0 voltage one LED turns ON instead of nothing. when there is a voltage all connected LEDs turn ON regardless of what the voltage is

when there is no voltage connected (floating wires), I get this:

[![enter image description here][1]][1]

when I put any amount of Voltage as long as the power supply is ON the results is the same:

[![enter image description here][2]][2]

Note: What am I doing wrong?
edit: connections are something like that but with fewer digital pins.
[![enter image description here][3]][3]

Note: What am I doing wrong!EDIT:
I was able to get around and print the serial monitor result:
- when the power source is OFF, the reading at A0 (sensorreading) is:

[![enter image description here][4]][4]

Note: What am I doing wrong!- when the power source is ON at any value, the reading at A0 (sensorreading) is:

[![enter image description here][5]][5]

  [1]: https://i.stack.imgur.com/0Itc3.png
  [2]: https://i.stack.imgur.com/e99yj.png

(Note: What am I doing wrong!)

  [3]: https://i.stack.imgur.com/yjNZJ.png
  [4]: https://i.stack.imgur.com/RhxP6.png
  [5]: https://i.stack.imgur.com/OsuIp.png

body:
You are using a Full-size breadboard, for the full-size breadboards, the power rails are divided into two half sections as shown in this picture, and you need to have jumpers to bridge the two half-sections if you want to use them as a single power trail full-size section.
[![enter image description here][1]][1]

So on your photo, you thought that your blue wire (for GND) is connected to the rest of GND pins, but it is actually not connected.

  [1]: https://i.stack.imgur.com/9wZuA.png


body:
I can say your code is working but you need to check the wirering of your circuit .

Note that the voltage on the analogread pin should not be an oscillating voltage at low frequency like AC voltage. It should be  a direct stable voltage to get the correct output.

Here is my diagram below for you to make changes with yours .
Ive testedit on my simulation app and its working perfectly.

The code

```

const int analogPin = A0; // the pin that the potentiometer is attached to
const int ledCount = 7; // the number of LEDs in the bar graph
int ledPins[] = { 3, 4, 5, 6, 8, 9, 10}; // an array of pin numbers to which LEDs are attached

void setup() {
Serial.begin(9600);
// loop over the pin array and set them all to output:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
pinMode(ledPins[thisLed], OUTPUT); }
}

void loop() { // read the potentiometer:
int sensorReading = analogRead(analogPin);
Serial.print("sensor read : ");
Serial.println(sensorReading);

// map the result to a range from 0 to the number of LEDs:
int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);
Serial.print("led Level : ");
Serial.println(ledLevel);

// loop over the LED array:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
// if the array element's index is less than ledLevel, // turn the pin for this element on:
if (thisLed < ledLevel) {
digitalWrite(ledPins[thisLed], HIGH);
}

// turn off all pins higher than the ledLevel:
else {
digitalWrite(ledPins[thisLed], LOW);
} }

//delay(500); //for debugging
 }

```

The diagram

[![voltage-follower][1]][1]

Note that if you're tryingto measure a voltage higher than 5 volts, make sure to build the voltage divider circuit with the appropriate resistor values for you to get 5v output as that is the highest volt the arduino can carry.
measure
Example below shows a 12 volts dc battery voltage measure(note that 5 volts is the highest voltage supplied to the arduino, not the full 12 volts):

[![12 volts][2]][2]

  [1]: https://i.stack.imgur.com/Ji1xW.png
  [2]: https://i.stack.imgur.com/zqAKB.png


message:
ArduinoHTTPClient POST multipart/form-data from SD card returning 400 Bad Request

I have been having trouble trying to send a small txt file to my server using the following function with TinyGSM. I know I am connected to the internet and reaching the web server, however, I keep receiving a `400 Bad Request` code. I think something is wrong with my `PostHeader`, but I have no clue where or what it could be... I know I am connecting to my server as I try a default get and return webpage text...

    TinyGsm modem(SerialAT);
    TinyGsmClient client2(modem);
    HttpClient client(client2, server, port);

    void fileUpload(String filename){
      if(!initSD()){
        return;
      }
      File dataFile = SD.open(filename.c_str());
      Serial.println("Uploading File...");
      if (!client.connect(server, port)) {
        Serial.println("Failed connecting to Server");
        return;
      }
      String fileType = "text/plain";
      String content = "--boundary1\r\n";
      content += "Content-Disposition: form-data; name=\"fileToUpload\"; filename="+String(filename)+"\r\n";  // the fileToUpload is the form parameter
      content += "Content-Type: "+fileType+"\r\n\r\n";
      //after this, post the file data.
      String closingContent = "\r\n--boundary1--";
      //Serial.println(content);
      client.println(String("POST ") + "/upload.php" +" HTTP/1.1\r\n");
      client.println(String("Host: ") + server + "\r\n");
      client.println("Content-Type: multipart/form-data; boundary=boundary1\r\n");
      client.println("Connection: close\r\n");
      client.println("Content-Length: "+String(content.length()+dataFile.size()+closingContent.length())+"\r\n");
      client.println(content);
      client.println();
      if (dataFile) {  // start sending file content
        while (dataFile.available()) {
          char c = dataFile.read();
            client.print(c);
          }
        dataFile.close();
      }
      client.println(closingContent);
      Serial.println("File Sent.");
        // read the status code and body of the response
      int statusCode = client.responseStatusCode();
      String response = client.responseBody();

      Serial.print("Status code: ");
      Serial.println(statusCode);
      Serial.print("Response: ");
      Serial.println(response);
    }

body:
There were a couple issues that I finally managed to solve... I was able to get it to work by *not* using `ArduinoHTTPClient`. Here is working code for anyone else who stumbles here.

    TinyGsmClient client(modem);

    void fileUpload(String filename){
      File dataFile = SD.open(filename.c_str());
      Serial.println("Uploading File...");
      if (!client.connect(server, port)) {
        Serial.println("Failed connecting to Server");
        return;
      }
      String fileType = "text/plain";
      String content = "--boundary1\r\n";
      content += "Content-Disposition: form-data; name=\"fileToUpload\"; filename="+String(filename)+"\r\n";  // the fileToUpload is the form parameter
      content += "Content-Type: "+fileType+"\r\n\r\n";
      //after this, post the file data.
      String closingContent = "\r\n--boundary1--\r\n";
      //Serial.println(content);
      client.println(String("POST ") + "/upload.php" +" HTTP/1.1"); // or wherever you need to call/print to.
      client.println(String("Host: ") + server);
      client.println("Content-Length: "+String(content.length()+dataFile.size()+closingContent.length()));
      client.println("Content-Type: multipart/form-data; boundary=boundary1");
      client.println();
      client.println(content);
      if (dataFile) {  // start sending file content
        String data = "";
        while (dataFile.available()) {
          char c = dataFile.read();
          data += c;
          //write every line break...
          if(c == '\n'){
            client.write(data.c_str());
            data = "";
          }
        }
        dataFile.close();
      }
      client.print(closingContent);
      unsigned long timeout = millis();
      while (client.connected() && millis() - timeout < 50000L) {
        // Print available data
        while (client.available()) {
          char c = client.read();
          Serial.print(c);
          timeout = millis();
        }
      }
      client.stop();
    }


message:
Arduino UNO Power interruption

Do you have to upload the UNO after the applied power is disconnected?

Does the UNO retain the code without any power?

And when the power is disconnected, if the code is retained, will the timers retain their values?
Thanks

body:
>Do you have to upload the UNO after the applied power is disconnected?

No.

>Does the UNO retain the code without any power?

Yes.

>And when the power is disconnected, if the code is retained, will the timers retain their values?

No.


body:
This answer simply add some detail to that provided by VE7JRO to make it more generally applicable but this does look rather like a school assignment.
Program code is stored in flash memory and this is retained after a power down.  It is not necessary to reload it. The registers which hold timer values or other data from a running program are stored in RAM memory and this is lost on power off. It is possible also to save some data from a running program in EEPROM (or in some cases flash memory) which also survives after a power down.


message:
Pin Change Interrupt Flag timing on 1284P

I want to ask about pin change interrupts on a 1284P chip using MightyCore.  I have a question about the timing of multiple interrupts on one port.  Specifically, if I am servicing a PCINT vector and another pin in the port changes while I am in the ISR, will it generate another interrupt immediately following the one I am servicing?

When I read the datasheet I see:

> Bit 2 – PCIF2: Pin Change Interrupt Flag 2 When a logic change on any
> PCINT[23:16] pin triggers an interrupt request, PCIF2 will be set. If
> the I-bit in SREG and the PCIE2 bit in PCICR are set, the MCU will
> jump to the corresponding Interrupt Vector. The flag is cleared when
> the interrupt routine is executed. Alternatively, the flag can be
> cleared by writing '1' to it.

When it says that the flag is cleared when the interrupt routine is executed, does that mean when it enters or exits the ISR?  If it is at the end, can I clear the flag in the first line of the ISR and allow another pin change to set it again even if it happens before I exit the ISR?

body:
When it is entered. The wording is slightly vague but I think "when the interrupt routine is executed" means the commencement of execution. Otherwise multiple pin-change interrupts could be easily missed, depending on how long you took inside the ISR.

I suggest writing a simple test that saves somewhere what the flag is, upon entering the ISR, and check it is cleared already.

---

I wrote this test for the Uno (which is the same basic architecture):

<!-- language: lang-c++ -->

    volatile bool firstTime = true;
    volatile byte PCIFR_copy = 0;

    ISR (PCINT0_vect)
     {
     // handle pin change interrupt for D8 to D13 here

     if (!firstTime)
       return;

     firstTime = false;
     PCIFR_copy = PCIFR;
     }  // end of PCINT0_vect

    void setup ()
      {
      pinMode (9, INPUT_PULLUP);
      Serial.begin (115200);

      // pin change interrupt (for D9)
      PCMSK0 |= bit (PCINT1);  // want pin 9
      PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
      PCICR  |= bit (PCIE0);   // enable pin change interrupts for D8 to D13
      }  // end of setup

    void loop ()
      {
      Serial.print ("First time is ");
      Serial.print ((int) firstTime);
      Serial.print (", Flag is ");
      Serial.println ((int) PCIFR_copy);
      delay (1000);
      }  // end of loop

The PCIFR flag was always zero, even after triggering the pin-change interrupt, which shows that it was cleared upon **entering** the ISR.

> will it generate another interrupt immediately following the one I am servicing?

So, based on the above, the answer is yes it will. Upon leaving the ISR one more instruction will be executed and then the next interrupt will be serviced (assuming a higher-priority interrupt doesn't get in first).

---

Another way of looking at it is that the pin change will always set that flag. Between instructions the processor would check that flag (and the flags for the other interrupts) and for the highest priority interrupt, if that flag is set, then it would clear that flag and then commencing processing that interrupt. That is really the only logical way it could work.

---

Also, it makes more sense from the design of the processor to clear the flag upon entering the ISR. Apart from the problem that interrupts could be missed if it didn't, when it enters the ISR the processor "knows" which interrupt it is servicing, because it would have checked the PCIFx flag, it would have checked the PCIEx flag (to see if the interrupt should be executed) and it would have then changed the program counter to the appropriate address for that interrupt, after pushing the current program counter onto the stack. This would be the logical time to clear that flag while all this information is in the processor's "head" so to speak.

At the end of the ISR the code simply executes a RTI (Return from Interrupt) instruction which doesn't have associated with it which interrupt it is returning from. Thus it would be hard to clear the flag at that point.


message:
PlatformIO and const PROGMEM

I'm using the DuinoWitchery LCD library (https://github.com/duinoWitchery/hd44780) in a PlatformIO Arduino project with CLion.

The following code works if I stick it in main.cpp:

~~~
// near top of class...
const PROGMEM uint8_t decimalDigit[10][8] = {
        {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
        {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
        {0x07, 0x01, 0x07, 0x04, 0x07, 0x18, 0x18}, // .2
        {0x07, 0x01, 0x07, 0x01, 0x07, 0x18, 0x18}, // .3
        {0x5,  0x05, 0x07, 0x01, 0x01, 0x18, 0x18}, // .4
        {0x07, 0x04, 0x06, 0x01, 0x06, 0x00, 0x18, 0x18}, // .5
        {4,    4,    7,    5,    7,    0,    0x18, 0x18}, // .6
        {7,    1,    1,    1,    1,    0,    0x18, 0x18}, // .7
        {7,    5,    7,    5,    7,    0,    0x18, 0x18}, // .8
        {7,    5,    7,    1,    1,    0,    0x18, 0x18}, // .9
};

hd44780_I2Cexp lcd(0x27);

// ... snip ...

void setup() {
    for (int x=0; x<8; x++)
       lcd.createChar((uint8_t)x, decimalDigit[x]);
    // ...snip...
}
~~~

... but if I move the code into another class, like:

**Renderer.h**
~~~
class Renderer : BaseRenderer {
public:
    virtual void renderTo(hd44780* lcd) override;
    // ... snip ...
private:
const PROGMEM uint8_t decimalDigit[10][8] = {
        {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
        {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
        {0x07, 0x01, 0x07, 0x04, 0x07, 0x18, 0x18}, // .2
        {0x07, 0x01, 0x07, 0x01, 0x07, 0x18, 0x18}, // .3
        {0x5,  0x05, 0x07, 0x01, 0x01, 0x18, 0x18}, // .4
        {0x07, 0x04, 0x06, 0x01, 0x06, 0x00, 0x18, 0x18}, // .5
        {4,    4,    7,    5,    7,    0,    0x18, 0x18}, // .6
        {7,    1,    1,    1,    1,    0,    0x18, 0x18}, // .7
        {7,    5,    7,    5,    7,    0,    0x18, 0x18}, // .8
        {7,    5,    7,    1,    1,    0,    0x18, 0x18}, // .9
    };
}
~~~

**Renderer.cpp**
~~~
void Renderer::renderTo(hd44780lcd* lcd) {
    for (int x=0; x<8; x++)
       lcd->createChar((uint8_t)x, decimalDigit[x]);
    // ...snip...
}
~~~

... the custom characters end up with garbage data.

I **think** I might be breaking some esoteric rule that governs where you're allowed to put a `const PROGMEM uint8_t[]`, and causing the array declared in Renderer.h to end up in SRAM. But I'm not sure how to confirm it OR fix it.

---

note: the for/next loop to create the chars is just for the sake of illustration & to demonstrate that something that works in main.setup() fails in Renderer.renderTo(). In *real* life, the sequence of characters getting rendered to the LCD owns one of the 8 custom characters & redefines it as necessary to be the decimal point and tenths value.

body:
OK, I ended up blindly stumbling over the solution, even though at this moment I have no idea why it actually works.

I moved the `const PROGMEM uint8_t decimalDigit[10][8] = {...}` declaration **from** Renderer.h **to** the almost-top of Renderer.cpp, so it sits between `#include "Renderer.h"` and constructor:

~~~
#include "Renderer.h"

const PROGMEM uint8_t decimalDigit[10][8] = {
        {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
        {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
        {0x07, 0x01, 0x07, 0x04, 0x07, 0x18, 0x18}, // .2
        {0x07, 0x01, 0x07, 0x01, 0x07, 0x18, 0x18}, // .3
        {0x5,  0x05, 0x07, 0x01, 0x01, 0x18, 0x18}, // .4
        {0x07, 0x04, 0x06, 0x01, 0x06, 0x00, 0x18, 0x18}, // .5
        {4,    4,    7,    5,    7,    0,    0x18, 0x18}, // .6
        {7,    1,    1,    1,    1,    0,    0x18, 0x18}, // .7
        {7,    5,    7,    5,    7,    0,    0x18, 0x18}, // .8
        {7,    5,    7,    1,    1,    0,    0x18, 0x18}, // .9
};

Renderer::Renderer(int col, int row, int customCharNumber) : BaseRenderer(col, row) {
    assignCustomChar(customCharNumber);
}
~~~

For now, I just have to chalk it up as 'black magic', because some subsequent experiments have forced me to question and doubt everything I ever thought I understood about how #include directives work.


body:
The `PROGMEM` qualifier can only be applied to statically-allocated
constant data. When you move the `decimalDigit` array inside the class,
it becomes a data member, i.e. you have one copy of the array per
instance... in RAM. In this case, `PROGMEM` does not work. My compiler
says:

```text
warning: ‘__progmem__’ attribute ignored [-Wattributes]
```

If you want to keep the array inside the class, it must be given the
`static` qualifier. It then becomes statically-allocated class data (not
instance data):

```c++
// Renderer.h:
class Renderer : BaseRenderer {
public:
    virtual void renderTo(hd44780* lcd) override;
    // ... snip ...
private:
    static const PROGMEM uint8_t decimalDigit[10][8];
};

// Renderer.cpp:
const PROGMEM uint8_t Renderer::decimalDigit[10][8] = {
    {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
    {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
    // ... snip ...
};
```

Of course, putting the array within the class is not an obligation. If
it is going to be private anyway, the outside world (the files that
include Renderer.h) does not need to know about its existence.


message:
MD5 of File doesnot match data in flash Error with ESP32 S3

I am getting the ```fatal error MD5 of file not match data in flash```. Below is the output of upload.

    [1/5] cmd.exe /C "cd /D D:\Users\INOMETRICS\espressif\workspace\blink\build\esp-idf\esptool_py && python D:/Espressif/frameworks/esp-idf-v4.4/components/partition_table/check_sizes.py --offset 0x8000 partition --type app D:/Users/INOMETRICS/espressif/workspace/blink/build/partition_table/partition-table.bin D:/Users/INOMETRICS/espressif/workspace/blink/build/blink.bin"
    blink.bin binary size 0x31340 bytes. Smallest app partition is 0x100000 bytes. 0xcecc0 bytes (81%) free.
    [2/5] Performing build step for 'bootloader'
    [1/1] cmd.exe /C "cd /D D:\Users\INOMETRICS\espressif\workspace\blink\build\bootloader\esp-idf\esptool_py && python D:/Espressif/frameworks/esp-idf-v4.4/components/partition_table/check_sizes.py --offset 0x8000 bootloader 0x0 D:/Users/INOMETRICS/espressif/workspace/blink/build/bootloader/bootloader.bin"
    Bootloader binary size 0x5180 bytes. 0x2e80 bytes (36%) free.
    [2/3] cmd.exe /C "cd /D D:\Espressif\frameworks\esp-idf-v4.4\components\esptool_py && D:\Espressif\tools\cmake\3.20.3\bin\cmake.exe -D IDF_PATH="D:/Espressif/frameworks/esp-idf-v4.4" -D SERIAL_TOOL="python D:/Espressif/frameworks/esp-idf-v4.4/components/esptool_py/esptool/esptool.py --chip esp32s3" -D SERIAL_TOOL_ARGS="--before=default_reset --after=hard_reset write_flash @flash_args" -D WORKING_DIRECTORY="D:/Users/INOMETRICS/espressif/workspace/blink/build" -P D:/Espressif/frameworks/esp-idf-v4.4/components/esptool_py/run_serial_tool.cmake"
    esptool.py esp32s3 -p COM8 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 80m --flash_size 2MB 0x0 bootloader/bootloader.bin 0x10000 blink.bin 0x8000 partition_table/partition-table.bin
    esptool.py v3.2-dev
    Serial port COM8
    Connecting...
    Chip is ESP32-S3
    Features: WiFi, BLE
    Crystal is 40MHz
    MAC: 70:04:1d:be:ab:74
    Uploading stub...
    Running stub...
    Stub running...
    Changing baud rate to 460800
    Changed.
    Configuring flash size...
    Flash will be erased from 0x00000000 to 0x00005fff...
    Flash will be erased from 0x00010000 to 0x00041fff...
    Flash will be erased from 0x00008000 to 0x00008fff...
    Compressed 20864 bytes to 13002...
    Writing at 0x00000000... (100 %)
    Wrote 20864 bytes (13002 compressed) at 0x00000000 in 0.1 seconds (effective 1284.4 kbit/s)...
    File  md5: 1d4bc050825217f8434a2cfd167894cd
    Flash md5: 1b32e380d00eb036ce18a632dedbe04d
    MD5 of 0xFF is b145c0e952abec491d69c8c5f8ac47c4

    A fatal error occurred: MD5 of file does not match data in flash!
    CMake Error at run_serial_tool.cmake:56 (message):
      python
      D:/Espressif/frameworks/esp-idf-v4.4/components/esptool_py/esptool/esptool.py
      --chip esp32s3 failed

I am getting the same error while uploading with esp-idf and Arduino ide or platformio.

How could i solve the issue.

Regards

body:
Yes, I have managed to get it working now, the issue encountered was with the strapping pins. Specifically, Pin 45 of ESP32S3 is responsible for configuring VDD_SPI_FLASH. To ensure it operates at 3.3V, the pin should be connected to the ground. Otherwise, it will function at 1.8V, which might cause problems with the Flash functionality.

Fortunately, this can also be resolved by burning some EFUSES using the espefuse.py tool, which comes along with esptool.py. All you need to do is run the command: `espefuse.py set_flash_voltage <voltage>` (where voltage can be either 3.3V or 1.8V or OFF). For more details, you can visit: [link to the official documentation][1].

  [1]: https://docs.espressif.com/projects/esptool/en/latest/esp32s3/espefuse/set-flash-voltage-cmd.html


message:
ERROR: return reinterpret_cast<T>(pgm_read_ptr(p));

I need to update **DHT** sensor data to the webserver in ***JSON*** format using **ESP8266**. This is my code.

```c++
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#include <ArduinoJson.h>

const char* ssid = "YOUR_SSID";
const char* password = "YOUR PASSWORD";
const int dhtPin = D4;
DHT dht(dhtPin, DHT11);
ESP8266WebServer server(80);

void handleRoot() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  if (isnan(temperature) || isnan(humidity)) {
     server.send(500, "text/plain", "Failed to read from DHT sensor");
    return;
  }

  StaticJsonDocument<200> jsonDoc;
  jsonDoc["temperature"] = temperature;
  jsonDoc["humidity"] = humidity;

  String jsonString;
  serializeJson(jsonDoc, jsonString);

  server.send(200, "application/json", jsonString);
}

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

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  Serial.println("Connected to WiFi");
  dht.begin();
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Server started");
}

void loop() {
  server.handleClient();
}
```

But I got error like,

```
In file included from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Polyfills/static_array.hpp:11:0,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Numbers/FloatTraits.hpp:14,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Numbers/FloatParts.hpp:8,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Json/TextFormatter.hpp:11,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Json/JsonSerializer.hpp:7,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Variant/ConverterImpl.hpp:7,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.hpp:37,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.h:9,
                 from C:\Users\Kuralmozhi.R\Downloads\ID_2\ID_2.ino:5:
c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Polyfills/pgmspace_generic.hpp: In instantiation of 'typename ArduinoJson6193_F1::enable_if<ArduinoJson6193_F1::is_pointer<T>::value, T>::type ArduinoJson6193_F1::pgm_read(const void*) [with T = const __FlashStringHelper*; typename ArduinoJson6193_F1::enable_if<ArduinoJson6193_F1::is_pointer<T>::value, T>::type = const __FlashStringHelper*]':
c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Deserialization/DeserializationError.hpp:85:12:   required from here
c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Polyfills/pgmspace_generic.hpp:15:45: error: 'const void*' is not a pointer-to-object type
   return reinterpret_cast<T>(pgm_read_ptr(p));
                                             ^

exit status 1

Compilation error: exit status 1
```

I don't know how to solve this error. Please suggest me some ideas!

---

I tried to update ESP8266. But now it shows like this,

```
Variables and constants in RAM (global, static), used 28984 / 80192 bytes (36%)
║   SEGMENT  BYTES    DESCRIPTION
╠══ DATA     1504     initialized variables
╠══ RODATA   1376     constants
╚══ BSS      26104    zeroed variables
Instruction RAM (IRAM_ATTR, ICACHE_RAM_ATTR), used 60439 / 65536 bytes (92%)
║   SEGMENT  BYTES    DESCRIPTION
╠══ ICACHE   32768    reserved space for flash instruction cache
╚══ IRAM     27671    code in IRAM
Code in flash (default, ICACHE_FLASH_ATTR), used 273120 / 1048576 bytes (26%)
║   SEGMENT  BYTES    DESCRIPTION
╚══ IROM     273120   code in flash
```

body:
With the info from [the link Fahad provided in the comments][1], I can only offer a guess: Your ESP8266 board definitions are outdated and the old version of the ESP8266 board definitions contains a bug.

There is an outdated URL to the ESP8266 board definition JSON floating around on the web. I _guess_ you found that one. The URL still works, but is not updated anymore. Please check the version of your ESP8266 board definitions: Open the Board Manager (`Tools -> Board -> Board Manager`), search for ESP8266 and verify that the version is at least 3.1.2 (current version as of this writing; I don't know the lowest version where this bug is fixed).

If the Board Manager does not offer to update to version 3.1.2 (or later), you may need to provide the current URL to the board definitions in `File -> Preferences -> Tab "Settings" -> Additional Boards Manager URLs`. Remove the old ESP8266 URL, but don't remove URLs for _other_ boards. Then try to update using the Board Manager again:
```
https://arduino.esp8266.com/stable/package_esp8266com_index.json
```

  [1]: https://github.com/bblanchon/ArduinoJson/issues/1442


message:
Encoder giving value between steps

I'm trying to interface an encoder and a 1602 i2c display. My encoder seems to be giving an output between steps.

I have tried to make my code as simple as possible and am outputting whether the encoder rotated clockwise or counter clockwise to serial. When I rotate the knob one physical step clockwise, '++' (separated by a new line) outputs to the serial monitor when I am expecting just '+'.  The same occurs when rotating counter clockwise, except with '--' instead of '++'.

Parts:
 - ESP32 Dev Board
 - [Rotary Encoder](https://www.amazon.com/Cylewet-Encoder-Digital-Potentiometer-Arduino/dp/B07DM2YMT4/?_encoding=UTF8&pd_rd_w=dJykK&content-id=amzn1.sym.5f7e0a27-49c0-47d3-80b2-fd9271d863ca:amzn1.symc.e5c80209-769f-4ade-a325-2eaec14b8e0e&pf_rd_p=5f7e0a27-49c0-47d3-80b2-fd9271d863ca&pf_rd_r=8QJDDY22WMD2B9NRE7XB&pd_rd_wg=2tOn9&pd_rd_r=ea853507-cd5e-45d9-b373-d8c5139e071e&ref_=pd_gw_ci_mcx_mr_hp_atf_m)

Code:

    #define enc1 32
    #define enc2 33
    #define button 25
    #define led 2;

    int oldPos1;
    int newPos1;
    int newPos2;

    void setup() {
      pinMode(enc1, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(enc1),encRead,CHANGE);
      pinMode(enc2, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(enc2),encRead,CHANGE);
      Serial.begin(115200);

      oldPos1 = digitalRead(enc1);
    }

    void encRead(){
      newPos1 = digitalRead(enc1);
      newPos2 = digitalRead(enc2);
      if(oldPos1 != newPos1){
        if (newPos1 == newPos2){
          Serial.println("+");
        }
        else{
          Serial.println("-");
        }
      }
      oldPos1 = newPos1;
    }

    void loop() {
      delay(10);
    }

body:
Unfortunately you did not provide a link to the data sheet of the encoder.

One physical step at the knob can generate changes on both pins. And since you have assigned the interrupt service routine to both pins, it is called two times for each physical step.

Another possible reason is "[bouncing][1]" of the mechanical contacts in this encoder. That means, that multiple pulses are generated on the change between _open_ and _closed_. Therefore, change or edge interrupts are only a correct solution, if you take bouncing into account.

To investigate the issue, you can insert port pin toggles to your interrupt service routine. For example, set a pin on entry and reset it on exit. Then connect an oscilloscope or logic analyzer and compare the input signals and this output.

Oh, and it is never a good idea to put serial output in an interrupt service routine. Depending on the amount of sent data and the chosen baudrate, this output will block the routine for several milliseconds. During this time, the same interrupt is not serviced, and can be skipped in case of multiple triggers.

  [1]: https://en.wikipedia.org/wiki/Switch#Contact_bounce


body:
This is the kind of thing that can happen when you buy cheap parts that
come with no documentation whatsoever: you don't know how they are
supposed to work! Many rotary encoders have two detents per pulse: if
you rotate them by a single detent, you get a single transition on each
pin. If using such an encoder, you would indeed expect a single `+` or
`-` printed per detent. But what about the encoder you bought? You can't
tell, since there is no documentation!

Quite fortunately, a helpful individual left a useful review on the
product page you linked to. It can serve as an ersatz of datasheet:

> Each movement of the spindle from one detent to the next results in
> the encoder1 and encoder2 pins going through multiple transitions, not
> a single one (as you might expect).
>
> Assuming that you have tied the encoder pins to (say) 5V with a
> resistor, a rotation between detents, will produce a set of encoder
> transitions. For example: 11 10 00 01 11 (clockwise) or 11 01 00 10 11
> (anti-clockwise).

This explains the behavior you are experiencing.

Side note: as jsotola writes in a comment, you should
remove the `enc2` `attachInterrupt()`. As your interrupt handler
explicitly ignores transitions in `enc2` (it does nothing unless `enc1`
changed), there is no point in interrupting the processor for those
ignored transitions.