text:
Why is dtostrf() not working for this one value?
I'm building a weather station using an ESP32 and BME280. I'm feeding the data via MQTT and Python into a database that is then used to make a nice dashboard for the data.
The MQTT message needs to be a char, and the sensor readings are floats, so I'm using dtostrf() to convert them. This works fine for the temperature and pressure readings, but for some reason not for the humidity reading.
I declare my variables:
float temp;
float hum;
float pres;

char mqttTemp[6];
char mqttHum[6];
char mqttPres[5];

Then I get my readings:
temp = mySensor.readTempC();
Serial.print("Temp: ");
Serial.print(temp);
hum = mySensor.readFloatHumidity();
Serial.print("Hum: ");
Serial.print(hum);
pres = mySensor.readFloatPressure();
Serial.print("Pres: ");
Serial.print(pres);

This returns:
Temp: 25.57 Hum: 40.15 Pres: 97684.39
Then I run the results through the function:
dtostrf(temp,4,2,mqttTemp);
dtostrf(hum,4,2,mqttHum);
dtostrf(pres,5,0,mqttPres);

Then I output these to Serial:
Serial.print("Temperature: ");
Serial.print(mqttTemp);
Serial.print("Humidity: ");
Serial.print(mqttHum);
Serial.print("Pressure: ");
Serial.print(mqttPres);

Which gives me:
Temperature: 25.57
------------------------------
Humidity:
------------------------------
Pressure: 97684

There is also no message sent via MQTT for humidity, but it works perfectly for the other two readings. What gives?

Using a esp32 and trying to squeeze an array to the very last byte and beyond? That makes no sense. Can you make the char arrays 16 bytes each (or 20 or 100 bytes). The size for dtostrf is the minimum size, plus perhaps a negative sign, plus zero terminator, plus some extra for safety, that makes a lot more than just 6 or 5. What if the sensor is disconnected and some error values are returned and those errors are converted to text?

two basic errors - 1) you haven't declared the variables with enough room for the data they need to contain, and 2) you're using dtostrf incorrectly (the width of temperature is at least 5, or 6 if you can get temperatures at -10.00 or less, and the width of humidity is at least 6, since 100.00 is 6 characters

What is happening is that the variables you declared for mqttTemp etc are stored in memory something like this
variable   memory address
mqttPres @ 1000-1004 (5 bytes)
mqttHum  @ 1005-1010 (6 bytes)
mqttTemp @ 1011-1015 (6 bytes)

For a start, you only have enough room (with the mandatory NUL byte string terminator) for 4, 5 and 5 characters
When you convert pressure, the NUL byte is being placed as the first byte in mqttHum, therefore, when printing mqttHum you get an empty string output (since the first byte is NUL)
To really see what's happening, here's some code that illustrates the issue
char mqttTemp[6] = "TTTTT";
char mqttHum[6] = "HHHHH";
char mqttPres[5] = "PPPP";
void setup() {
  float temp = 25.57;
  float hum = 40.15;
  float pres = 97684.39;

  Serial.begin(74880);
  // put your setup code here, to run once:
  delay(100);
  Serial.println("before");
  printThem();
  dtostrf(temp, 4, 2, mqttTemp);
  Serial.println("converted temp");
  printThem();
  dtostrf(hum, 4, 2, mqttHum);
  Serial.println("converted hum");
  printThem();
  dtostrf(pres, 5, 0, mqttPres);
  Serial.println("converted press");
  printThem();
}
void printThem()
{
  Serial.print("mqttPres ");
  Serial.print((unsigned long) &mqttPres, DEC);
  Serial.print(": ");
  for (int i = 0; i < 5; i++) {
    Serial.print((int) mqttPres[i], DEC);
    Serial.print(' ');
  }
  Serial.println();

  Serial.print("mqttHum  ");
  Serial.print((unsigned long) &mqttHum, DEC);
  Serial.print(": ");
  for (int i = 0; i < 6; i++) {
    Serial.print((int) mqttHum[i], DEC);
    Serial.print(' ');
  }
  Serial.println();

  Serial.print("mqttTemp ");
  Serial.print((unsigned long) &mqttTemp, DEC);
  Serial.print(": ");
  for (int i = 0; i < 6; i++) {
    Serial.print((int) mqttTemp[i], DEC);
    Serial.print(' ');
  }
  Serial.println();
}

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

}

The above outputs the following:
before
mqttPres 1073644748: 80 80 80 80 0
mqttHum  1073644753: 72 72 72 72 72 0
mqttTemp 1073644759: 84 84 84 84 84 0
converted temp
mqttPres 1073644748: 80 80 80 80 0
mqttHum  1073644753: 72 72 72 72 72 0
mqttTemp 1073644759: 50 53 46 53 55 0
converted hum
mqttPres 1073644748: 80 80 80 80 0
mqttHum  1073644753: 52 48 46 49 53 0
mqttTemp 1073644759: 50 53 46 53 55 0
converted press
mqttPres 1073644748: 57 55 54 56 52
mqttHum  1073644753: 0 48 46 49 53 0
                     ^ ======== note the leading 0
mqttTemp 1073644759: 50 53 46 53 55 0

The simplest fix, of course, is to declare your variables with the correct size
char mqttTemp[7]; // because -10.00 takes 6 characters + 1 for NULL
char mqttHum[7];  // because 100.00 takes 6 characters + 1 for NULL
char mqttPres[6]; // because 97684 takes 5 characters + 1 for NULL - if pressure can reach 100000 then use 7 here as well

and then use dtostrf correctly, i.e. the second argument is the total width, including . and a possible -
dtostrf(temp,6,2,mqttTemp);
dtostrf(hum,6,2,mqttHum);
dtostrf(pres,5,0,mqttPres);

Thanks for a very thorough answer! I suspected I was fundamentally misunderstanding something (not least because it's my default state of being). It now works perfectly.

It is the minimal width. Why not make the arrays 20 in size instead of waiting for the next problem when the text turns out to be longer than expected?

if the temperature is above 999 or below -99 - there's a lot more to worry about @Jot - agreed though, but with the minimal sizes in the code above there can't be any issue given the data

@JaromandaX I have to disagree. I even have to disagree very strong. A bug in software should not be the cause of an avalanche of errors throughout the code. Therefor when using dtostrf, the buffer should be large enough to hold every possible float value. Preferably a buffer on the stack. In case the float value is limited, that limit should be in the code with if-statements and with a comment section to explain why a smaller buffer is possible. Perhaps that is useful in a attiny, but certainly not in a ESP32.

@Jot - I understand what you're saying, but a BME280 will not give you any values outside its measuring range, and dtostrf will "write" at most 7, 7 and 6 bytes including the NUL termination in this code - there is no possibility, in this case of the avalanche you speak of


text:
Interconnected Arduinos via digital pins and magnets
Before i get too far into the design phase of a project i have in mind, is there a way to connect arduinos in a non-master/slave manner to pass a few different combinations of HIGH/LOW (say 5) or 'information' both ways using digital pins? Perhaps some library i don't know about?
Each of these modules should be identical and be able to connect on any face to any other module. I've included a crude image of what I would like to accomplish.

I've already determined that i can solder to these neodymium magnets without loss of magnetic properties by having the little magnets attached to a stronger magnet during the soldering process. Magnet to magnet connection shows only a very tiny resistance.
If it can't be accomplished, i will need to abandon the project and look for some other means to make my project. Thanks in advance!
~zen

would serial connections work for you?

As long as i was only communicating to one face of the module at a time, but my understanding of the Tx/Rx communications would push out the command to all modules. I only want to send/receive to one module, not all of them at the same time.

you have more than one serial interface - some arduinos have 4 hardware serial interfaces (if I recall) ... then there's SoftwareSerial - to make any pair of pins a "serial" interface

Hmmm... since the rest of the project is only LED lighting with not much programming, I was hoping to use a cheap, low-power (usually 1 serial interface) arduino like the lilypad or similar. I would be creating some 30-40 modules to interact and so the cost of each is thusly multiplied.

Does 'SoftwareSerial' allow multiple Tx/Rx pin sets? That does look promising!

so, your wiring shows each "arduino" using 3 pairs of wires to connect to an adjacent "arduino" - so, how did you envisage these wires would be used for "communication"

I would need them to transmit or receive a value such as 1 for green, 2 for red, 3 for blue or something similar. Decision-making by the arduino would determine if that value was passed to another face. (It's sounding weirder and weirder).

https://arduino.stackexchange.com/questions/43118/simple-multiple-rx-tx-softwareserial shows 4 software serial in use

by the way, I'd wire it differently ... if 1 is output and 2 is input, for example, then you'd need, for example 1 on top of 2 on the left of the board, and 2 on top of 1 on the right ... therefore, output connects to input and vice versa :p

Sweet! That looks like maybe the ticket. Thanks for the pointer!

don't use high speeds though ... but it looks like you won't need to - I believe 9600 would work

Well, dang. I would need each of the modules and their faces to be identical as far as wiring, meaning that any face to be magnetically attached to any face. You're right, i can't connect Tx to Tx if i expect to read anything...

Yes, 9600 would be quick enough...

Hmmm... so maybe i need to use 4 pins for each side to be able to communicate back and forth serially? My mind's boggling a little.

not sure why you'd need 4 - the key is rotational symmetry

Oh, wait. Yes. If i have the Tx pin on the left and the Rx on the right, the two match each other's Rx and Tx. Sorry, i got confused.
Thanks so much for your help and for having to suffer through my confusion!

upvote for a cool idea ..... i would give you another upvote, if i could, for including the information about soldering the magnets

@jsotola - I'll upvote for you :p

there is also an issue with magnet polarity ..... the Rx could me a magnet ... the Tx would be a plain metal contact .... the power pins would have to be pogo pins ... otherwise you would not get rotational symmetry

How would pogo pins help rotational symmetry @jsotola? There is a way to get rotational symmetry with the power though https://photos.google.com/share/AF1QipOuhzEuYNfLFVrEynOVZ015yysy5AGGHLprJbm-S2iH80RgSi98F5woS5yH6yDZmA?key=R01LaERCM3huNExpX1lWeEpmWV9MT3pkOURNRzVR

@JaromandaX, i was unclear in my statement .... i was referring to the vertical layout of the power pins with the data pins on either side

While idea looks cool, you need some kind of "locks" because not "any combination" can work.
Rotate second Arduino in bottom row on 180 degree and you will see that GND/5V reversed relatively to first arduino in second row.
You have to account magnet N-S polarities to allow good lock. Probably you can use magnet polarities to achieve proper orientation.

Non-master/Slave is absolutely the best for lots of applications.
Why bother with Arduinos? There are much better processors available at low cost.
Lots of the STM32 processors allow you to address the serial ports.
For instance, from the reference manual of the popular STM32F103 (Blue pill).Quote.
Address mark detection (WAKE=1)
In this mode, bytes are recognized as addresses if their MSB is a ‘1’ else they are
considered as data. In an address byte, the address of the targeted receiver is put on the 4
LSB. This 4-bit word is compared by the receiver with its own address which is programmed
in the ADD bits in the USART_CR2 register.
The USART enters mute mode when an address character is received which does not
match its programmed address. In this case, the RWU bit is set by hardware. The RXNE
flag is not set for this address byte and no interrupt nor DMA request is issued as the
USART would have entered mute mode. Unquote.
Then use the Embitz compiler, free, use C or C++ if you have to.
C++ cannot compete with C for embedded work, proven over and over comparing code size and operating speed. Why use a processor without decent debugger?
Embitz and STM32 will give you an unbeatable debugger.
The larger STM32 processors also have Canbus, which is the ultimate non-master/slave.
Canbus is not difficult to set up, and you will never look back.
Alternatively, use ESP32 and Canbus.
Regards
Johan Smit

source: Stack Exchange

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

sort: votes


text:
what is the right way to parse JSON to Arduino?
i am trying to Turn an LED from a hosted website, though Arduino using the CC3000 wifi shield. It is working as it should. but i have to questions about optimising my code :
1) the Part where i parse my JSON is kind of sloppy, what is the right way to Parse the code so i can turn the LED on and off when clicking on the website buttons ?
2) i need to keep the arduino connected to the website, so i can always control the LED. Do i need to close the connection at the end ? if so, how can i activate the connection only when clicking the button on the website to active the LED.
#include <ArduinoJson.h>

// Include Libraries
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>

// Define Pins
#define ADAFRUIT_CC3000_IRQ   3
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10

// Define Variables
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT, SPI_CLOCK_DIVIDER);

#define WLAN_SSID       "MyWeb"
#define WLAN_PASS       ""
#define WLAN_SECURITY   WLAN_SEC_UNSEC // Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2

uint8_t dhcpTimeout;

#define host "mygarden.comli.com" // Your domain
uint32_t ip;
String path   = "/light.json";
int port = 80;

int pin = 9;

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

  pinMode(pin, OUTPUT);
  pinMode(pin, HIGH);

  // Connect to Wifi
  cc3000.begin();
  Serial.println(F("Initialising the CC3000"));
  if (!cc3000.begin())
  {
    Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
    while(1);
  }

  /* Delete any old connection data on the module */
  Serial.println(F("Deleting old connection profiles"));
  if (!cc3000.deleteProfiles()) {
    Serial.println(F("Failed!"));
    while(1);
  }

  // Connect to Network
  beginning:
  Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
  cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
  Serial.println(F("Connected"));

  //Wait for DHCP to complete
  Serial.println(F("Requesting DHCP"));
  while (!cc3000.checkDHCP()) {
    delay(500);
    Serial.print(F("."));
    dhcpTimeout ++;
    if (dhcpTimeout == 60) {
      Serial.println(F(""));
      Serial.println("DHCP Timeout! Attempting to reconnect.");
      dhcpTimeout = 0;
      goto beginning;
    }
  }
  Serial.println(F(""));
  Serial.println(F("DHCP complete"));

  //get website IP
  ip = 0;
  Serial.print(host); Serial.print(F(" -> "));
  while (ip == 0) {
    if (! cc3000.getHostByName(host, &ip)) {
      Serial.println(F("Couldn't resolve!"));
    }
    delay(500);
  }
  cc3000.printIPdotsRev(ip);
  Serial.println("");
}

void loop(void) {

  Adafruit_CC3000_Client client = cc3000.connectTCP(ip, 80);

  client.print(String("GET ") + path + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: keep-alive\r\n\r\n");
  delay(500); // wait for server to respond

  Serial.println(F("----------"));
   while (client.connected()) {
    String response = "";
    bool begin = false;
      while (client.available() || !begin) {
      char c = client.read();
      if (c == '{') {
        begin = true;
      }
      if (begin) response += (c);
      if (c == '"}') {
        break;
      }
      delay(1);

      }
      int start = response.indexOf("light\":\"") + 12;
      int end = start + 3;
      String LED_Control = response.substring(start, end);

      if (LED_Control == "onn") {
        digitalWrite(pin, HIGH);
        Serial.println("LED ON");
      }
      else if (LED_Control == "off"){
        digitalWrite(pin, LOW);
        Serial.println("led OFF");
      }

   }

  delay(1000);
  Serial.println(F("\n\nClosing the connection"));
  client.close();
  cc3000.disconnect();

}

And this is my JSON output
{"light": "off"}

Did you try the "ArduinoJson library on Github" ?

I did, but i had difficulty implementing it in my exemple.

Is response equal to your json {"light": "off"} ?

@mounim Thanks buddy for asking this question. I have the same problem and finally solved it by reading this.

Assuming that String response will contain the json {"light": "off"} and your program is ready to use the ArduinoJson library (#include <ArduinoJson.h> on top), a simple solution could be:
Step1 - declare and initialize StaticJsonBuffer object.
StaticJsonBuffer<80> jsonBuffer;

Step2 - deserialize the json from response.
JsonObject& root = jsonBuffer.parseObject(response);

Step3 - if the deserialization doesn't succeed, warn and break,
if (!root.success())
{
  Serial.print("parseObject(");
  Serial.print(response);
  Serial.println(") failed");
  break;
}

Step4 - otherwise, use json object to get the LED_Control.

Is the json will really contain {"light": "onn"} or is a typo ?

String LED_Control = root["light"];

if (LED_Control == "onn") {  // 'on' or 'onn' ??
    digitalWrite(pin, HIGH);
    Serial.println("LED ON");
}
else if (LED_Control == "off"){
    digitalWrite(pin, LOW);
    Serial.println("led OFF");
}

That made alot of sens, thanks .... it ment to be "on" :)

Thank you so much for this answer. Finally, I'm able to parse my JSON data successfully.

If the response from the web server is just a boolean value, the 'right' way would IMHO be to return e.g. just a 0 and 1 instead of JSON encoded data. That saves you from parsing JSON on the Arduino completely. Instead you can simply read one character of the response and check for '0' or '1'.
HTTP is a request-response based protocol and not suitable for staying connected to the server. If you need immediate reaction from the Arduino to server-side changes and your web server supports WebSockets, you could use any of the WebSocket libraries for the Arduino. Otherwise, you can use HTTP and poll the web server at a set interval to get the current value of the switch. And if you don't implement HTTP keep-alive, you will have to close the TCP connection and make a new connection for each HTTP request.

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


text:
LED bar graph script not working
I have LED bar graph on pins 2-11. Eventually I want to use a voltage divider to figure out the amount of voltage left in a power supply. Currently, this script should set the number of LEDs on the bar graph based on round((v_actual/v_reference)*10), I am just using some placeholder numbers in the mean time to test this portion of the script e.g. v_actual of 5 and v_reference of 10. However, the convert variable keeps printing 0. I've checked that the other variables were passing and they are. What is the issue here?
#include <Wire.h>

int ledBarNum = 10;    // # of leds
int vref = 10;     // max voltage of power supply

void setup(){
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop() {

  ledBarSetup(5);
}

void ledBarSetup(int v) {

  // logic vref=8; vactual or v = 4; (4/8)*10 = 2
  // e.g. number of leds we need to light up to represent the total amt left

  Serial.println(v);
  Serial.println(vref);

  int convert = round((v/vref)*10);

  Serial.println(convert);

  ledBar(convert);

}

void ledBar(int n) {

  int startingPin = 2;

  for (int thisPin = 2; thisPin < ledBarNum; thisPin++) {

    if (thisPin <= n) {

      digitalWrite(thisPin, HIGH);

    } else {

      digitalWrite(thisPin, LOW);

    }

  }

}

In integer math, 5/10 is equal to 0.

Both v and vref are integers, which means that integer division will be performed. if v is ever less than vref then the result will be 0. Multiply first, then divide.

ah yes I suppose I should have looked up the diff between int and float in arduino. Was completely unaware of this. Doing the multiply then divide method! (v*10/vref)

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


text:
Disable interrupts when doing critical things?
I've got a few functions like this that log, or do more critical things like get/save configuration variables.
/**
   Write weather data to csv
   commit: datetime,minHumidity,maxHumidity,minTemperature,maxTemperature,rainfall,irrigationRan
*/
void writeWeatherData() {
  noInterrupts();
  DBG_OUTPUT.println(F("[WEATHER DATA] Attempting to save weather data..."));
  bool writeHeader = SPIFFS.exists("/weather_data.csv") ? false : true;
  File file = SPIFFS.open("/weather_data.csv", "a");
  if (!file) {
    addPrintError("[WEATHER DATA] There was an error opening weather_data.csv for writing.");
    interrupts();
    return;
  }
  String data = "";
  if (writeHeader) {
    data += "datetime,minHumidity,maxHumidity,minTemperature,maxTemperature,rainfall,irrigationRan\r\n";
  }
  DateTime now = rtc.now();
  char buf[] = "MM/DD/YY hh:mm:ss";
  String t = now.toString(buf);
  float rainfall = getRainfall();
  data += t + "," + minHumidity + "," + maxHumidity + "," + minTemperature + "," + maxTemperature + "," + rainfall + "," + irrigationRan + "\r\n";
  if (file.print(data)) {
    DBG_OUTPUT.println(F("[WEATHER DATA] File was written."));
  } else {
    addPrintError("[WEATHER DATA] File write failed.");
  }
  file.close();
  DBG_OUTPUT.println(F("[WEATHER DATA] Task completed."));
  interrupts();
}

I surround  code with noInterrupts and interrupts however I am not sure if it is required. Assume that an interrupt is triggered at the exact moment when the above function is saving something, what exactly happens if I didn't have noInterrupts .etc.?

It depends upon the priority. whenever the interrupts comes mcu put the current processing task address in stack and goes to service the interrupt, after servicing the interrupt it goes back to the address where it left. If you don't want that task to be suspended or on hold for some moment, you can disable the interrupts during task started and enable when task ended.

if it is needed, then the library would take care

in the core of the SPIFFS implementation is the closed source ESP SDK call spi_flash_write and according to the reference it disables interrupts while writing to flash.

Interrupts happen all the time and code works just fine without locking them out. It doesn't matter if it's at the exact moment that a function is saving something - a properly written interrupt handler will save any necessary state so that whatever was interrupted can continue without problems. If it doesn't, the software will crash hard.
You should lock out interrupts as little as possible. Interrupts are used for critical timing functions and for network and other communications. Locking them out will cause these functions to be unreliable and may disrupt network connections.
The only time you should disable interrupts is when a data structure that an interrupt handler needs to use is in an inconsistent state. If an interrupt handler needs to use a shared data structure, disable interrupts before beginning to modify it outside of the interrupt handler, and re-enable them when you're done. Make sure it's as brief as possible.
Interrupt handlers should do as little as possible. They definitely should not call SPIFFS, should not call the real time clock, should not allocate or instantiate objects and should not do i/o operations. And you should not be disabling interrupts around calls to SPIFFS in hopes of making it safe for your interrupt handler to also call SPIFFS.
Take this as an example: suppose you want to use SPIFFS in both an interrupt handler and outside the interrupt handler. So you think you'll be clever and disable interrupts before you call SPIFFS outside the interrupt handler. Do you know exactly how SPIFFS works? Do you know whether SPIFFS uses any other functions that you might need to disable interrupts for in other parts of your code so that the interrupt handler won't disrupt them? Do you know for certain that SPIFFS doesn't allocate memory temporarily? Imagine that it does - now you also need to find every place in your code that might allocate memory and lock out interrupts around it, too. And maybe SPIFFS doesn't allocate memory - but do you know that SPIFFS in the future will never allocate memory?
You can't make assumptions about exactly how modules that you call are implemented, or how they'll be implemented in the future.
Unless you seriously know what you're doing, on microcontrollers like Arduinos, the ESP8266 and the ESP32, the best thing an interrupt handler can do is just set a flag to indicate that the interrupt occurred, and let code in the loop() check for the flag. The flag should most likely just be a simple Boolean variable declared as volatile so that the C compiler is aware that its value may suddenly change:
volatile boolean interrupt_flag = false;

It's safe to set that interrupt_flag to true inside the interrupt handler and it's safe to check the value in loop(), reset it to false and do whatever work was needed. Don't do more than this unless you know what you're doing.

to be clear: i am not using spiffs in the interrupt handler. the interrupt handler merely increments a counter in my case (on rainfall). i was just concerned if data would be corrupted or cause a crash if an interrupt triggered during some housekeeping operations I do with spiffs. you are saying i should be fine leaving out the noInterrupts .etc.?

"just set a flag to indicate that the interrupt occurred, and let code in the loop() check for the flag." - Though then you don't need the ISR at all, since the MCU already has an interrupt flag build into it's register. You could also poll that flag.

Excellent answer. Just a comment on “a properly written interrupt handler will save any necessary state”: unless written in assembly, the code for saving and restoring the state is written by the compiler, and you can pretty much trust it to do it right.

@Alex Yes, you should not disable interrupts while you're doing housekeeping operations. It's important not to disable interrupts. If this were a problem, almost none of the Arduino code out there would work right.

@chrisl true! Although I think most people who know that are safe to do more in an interrupt handler than set a flag :)

@EdgarBonet good point, with the hardware doing some of the work too,

John Romkey provided you an excellent answer. I am adding this just to
provide another perspective, hopefully complementary.
Interrupts are meant to handle the most time-critical tasks. Those tasks
that cannot wait for the next loop() iteration, such as counting a
pulse from an encoder, or getting a byte out of the UART receive buffer.
If you delay them too much, they may miss their deadline, resulting in
unreliable operation of the whole program (counter missing pulses, UART
missing bytes...).
Sometimes you have a piece of code that cannot afford being interrupted.
Maybe it is extremely time-critical, like the generation in software of
a pulse that is exactly 0.5 µs wide. More commonly it will be
reading data from memory that is being modified by an interrupt handler,
and you don't want that data to be modified in the middle of the read
operation. Such pieces of code are called critical sections, and you
keep them safe in between noInterrupts() and interrupts(). If an
interrupt request fires while the program is running a critical section,
the request is put on hold and serviced only when the critical section
is done. This adds some latency to the interrupt which, if
excessive, can lead to the interrupt missing its deadline. This is the
reason critical sections should be kept as short as possible.
You have been told that interrupt handlers should be kept as short as
possible, but I am not sure you know why it is so. The fundamental
reason is that interrupt handlers are themselves critical sections.
While a handler is running, other interrupts are blocked. On some
architectures (notably not AVR, I don't know about the ESP), only
interrupts of lower priority are blocked, but it is still an issue. The
rationale for keeping those handlers short applies equally to any
critical section.
Now, just to provide an example of the sort of bad things that can
happen if you block interrupts unnecessarily, consider this piece of
code:
noInterrupts();
Serial.println("Inside critical section.");
interrupts();

What this does is put the string "Inside critical section." in a
software buffer. Not a huge task you may say. Actually pushing the bytes
out to the UART is the job of an interrupt handler, triggered by the
UART when it is ready to accept a new byte. But then what happens if
there is not enough free space in the buffer for the string? In this
case, Serial.println() waits in a busy loop. It waits for the
interrupt to move bytes out of the buffer and make space for the new
string. But wait, we have just disabled interrupts... See the problem?
This is the reason it is generally advised to never Serial.print()
inside an interrupt handler. The same applies to any critical section.
Edit: As Juraj points out in a comment, the HardwareSerial code
now implements a workaround against this problem: if it
detects it has to wait with interrupts disabled, it takes care of
calling the interrupt handler itself. This is a (relatively) late
addition to the HardwareSerial code. Their authors presumably
witnessed too many beginners doing debug prints from interrupt handlers
and being bitten by this issue. Note that it is a workaround, not a
solution: it will often make the critical section last for an
unreasonably long time.
I wouldn't rely on similar APIs, or even on other cores, systematically
implementing this kind of safeguards though: some library authors just
trust the user to not do silly things.

the write() of hardware Serial checks if interrupts are enabled and if not, it calls the sending function directly

@Juraj: You are right. I edited the answer.

These are all great points, thank you for posting them... I wish I'd included them in my post :)

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


text:
default parameter class method
I have this function (which works fine):
String Esper::rtcTimeString() {
  DateTime now = rtc.now();
  char buf[] = "MM/DD/YY hh:mm:ss";
  return now.toString(buf);
}

I'd like to have a default value of "MM/DD/YY hh:mm:ss" but also pass an argument to a parameter such as "MM/DD/YYYY" if I want to override this default behavior.
Typically, in the definitions .h file I would do something like:
String rtcTimeString(char ts[] = "MM/DD/YY hh:mm:ss");

and subsequently in the .cpp:
String Esper::rtcTimeString(char ts[]) {
  DateTime now = rtc.now();
  return now.toString(ts);
}

However that results in the same returned time string every time.
e.g.
1/6/2020 12:01:12
1/6/2020 12:01:12
1/6/2020 12:01:12

How can I implement a parameter such that the functionality is the same as in the first code block?

I would expected char ts[] to be passed as reference (you could change the argument into char* but I doubt it will improve ... What I suggest is to use a PC compiler (e.g. free Visual Studio 2019 C++) and use the internal debugger to see what actually is passed and exactly where it goes wrong. Than move the corrected code back to Arduino.

You cannot pass an array of characters as an argument (implicit or not)
to a function. When you write
String rtcTimeString(char ts[] = "MM/DD/YY hh:mm:ss");

The array notation is implicitly converted to a pointer. The line above
is then equivalent to:
String rtcTimeString(char *ts = "MM/DD/YY hh:mm:ss");

And this is incorrect: you are initializing a pointer to modifiable
characters using the address of an array of constant characters. The
compiler should have warned you about this... if you enabled compiler
warnings. The correct prototype should be
string rtcTimeString(const char* ts = "MM/DD/YY hh:mm:ss");

But then you cannot pass this pointer to DateTime::toString(), as this
method expects the template string to live in a buffer it can overwrite:
that's where it will write the formatted string.
I suggest this solution:
string rtcTimeString(const char* ts = "MM/DD/YY hh:mm:ss") {
    DateTime now = rtc.now();
    char buf[strlen(ts)+1];  // allocate a fresh buffer
    strcpy(buf, ts);         // copy the template there
    return now.toString(buf);
}

Well explained. Thank you!

This basic C++ (and GIYF).
What about
String Esper::rtcTimeString(std::string dateTimeForamt = "MM/DD/YY hh:mm:ss")
{
  DateTime now = rtc.now();

  return now.toString(dateTimeForamt );
}

See, for instance, this question. Hope this helps :-)


text:
Can I set arbitrary SPI clock speeds?
I would like to interface an ADC (in particular this one: http://www.linear.com/product/LTC1400) with an Arduino Nano via SPI. The specified max clock speed for the ADC is 6.4 MHz. The Nano can do up to 8 MHz clock speed, but I'm not able to set 6.4 MHz. If I try this
SPI.beginTransaction(SPISettings(6400000, MSBFIRST, SPI_MODE0));

I get 4 MHz at the clock pin, which means the achievable acquisition rate of the ADC is reduced. Is there a way to get the 6.4 MHz going for maximum acquisition rate with the ADC? Or is there a different approach to get fast data transfer with the ADC (e.g. external clock)?

You are limited to what your microcontroller supports. You could use a 12MHz oscillator to clock your Arduino and set the SCK divider to fOSC/2 = 6MHz (even if it was possible, I wouldn't go higher. Having some margin just to be on the safe side is generally a good advice).
Drawback of this solution is that you lose CPU performance. Please consider also that just collecting ADC data is not enough. You also have to do something with it. Therefore the question should rather be:
"What minimum ADC acquisition rate do I need for my application?"

No, you cannot set 6.4MHz on SPI with a default hardware arrangement.
On the ATMega series of chips the SPI clock is generated by dividing the system clock (8 or 16MHz depending on if you have a 3.3 or 5V board) by one of: 2, 4, 8, 16, 32, 64 or 128.
Looking at the datasheet (section 25) it may be possible to configure the USART to run in SPI mode which allows a flexible clock speed, though this is not supported by the Arduino API.

Just to be complete, the ATMegas can be clocked up to 20MHz

Yes, but the Ardiuno boards never are (or not that I have seen).

Yeah, thats right


text:
Alternative for Particle Photon's Timer
I am converting a program made for particle photon to a Mega, everything is working except for the interrupt timer. The code that is of concern is (it's a .cpp file being included in the main .ino)
MyClass::MyClassConstructor(){
    messageTimer = new Timer(20, &MyClass::send, *this);
}

The documentation for this method is here.
Does anyone know a way to convert this to Arduino? There is the Timer library, but I can't really use the update method as the timer is in an instance of a class.

why do you need to convert code? ... why don't you instead describe how you want the code to function

The code, that you show us, only instantiates the timer with an interval and it's callback function. This also can be done for example with the Timer1 library. Please describe further where exactly you have a problem with that

try TimerOne library


text:
Arduino 5v output dead?
i've got a bit of a problem with my Arduino UNO.
So coming back to my (pretty basic) build after a bathroom break, I go to un-assemble my circuit (on the breadboard) and grabbing the LED causes a static shock.
Since then I haven't been able to get any power to come out of the Arduino to the breadboard circuitry.
I have tried:

Different Breadboards
All new parts, LED's/cabling/buttons/resistors.
Different power and ground cables (from Arduino to breadboard)
Giving the Board more time to 'cool down' (I heard there was a
temperature based reset device?)
using the 3.5v output (I'm not sure if by doing this i should remove
the resistor? i'm VERY new to electronics
using the alternate ground input

Looking around here for 'shorts' or 'damaged Arduinos' returns mostly results about non communication to the board. the difference here is I can absolutely still upload programs to my Arduino and then run them (I've only tried the pre-existing blink, but i don't think there is any difference). And my computer's USB ports are also fine. So if there is a duplicate question i apologize, but i haven't been able to find anything related.
Any help would be much appreciated!

What does  “get power to come out of the Arduino to the breadboard circuitry” mean?  Which output pin isn't working?  Have you tried some other pins?

But you can still upload and run the blink sketch on this 'damaged' Uno ? WIre a led (it's polarity sensitive) with a series resistor say 330R between the GND pin and +5V pins on the Uno to show if you have power there, then check the connections between the Uno and the breadboard.

If you got zapped touching an LED and the circuit doesn't work any more, and since you're sure the Arduino uploads programs OK, then either the LED (or something else on your breadboard) or the pin driver within the Arduino is probably damaged.

Try changing the LED.
If that doesn't work, try changing the pin(s) the sketch uses to talk to your breadboard, rewire your breadboard to use those pins, and test again. If it works this time, the pin driver was probably damaged.
If there are any other components (e.g., not wires or resistors) on the breadboard whose failure might cause the LED not to light, replace those and test again.
If replacing the external components doesn't fix it, and if your Arduino's MCU is a 28-pin chip in a socket, a new one with the bootloader already loaded into it typically costs $5-$6 in the US.

Update:

...i have listed all these things as already tried.

Right - I read right past it. :( So you've done the right things (except no mention of testing other pins) so I'm not sure what your question is. The title asks about the board's 5v supply but that must be up b/c your board uploads and runs Blink. That really leaves only the the pin driver(s) you were using when you zapped it.
You can salvage the board by testing all the pins in their input, output, analog, and other functions, and make a note of what capabilities have been lost. Clearly not all of them - pin 13 still works, for instance, because Blink worked. You can't repair damage internal to the chip without replacing it, and I would always consider it suspect, but it will be fine for many hobby uses if you just avoid the damaged functions.

In my OP i have listed all these things as already tried.
Looks like i'll just have to pick up a new Arduino then :(
Thanks!


text:
Can a Windows 10 computer use Arduino IDE 1.8.10 sometimes AND use Arduino IDE 2.0.0 the rest of the time?
Can Windows 10 computer use  Arduino IDE 1.8.10 sometimes, AND use Arduino IDE 2.0.0 the rest of the time?

why are you asking? ... have you tried to use both versions?

If it collides, you can add subdirectory "portable" in 1.8.10 and everything will be stored there (boards, sketches, libraries...)

https://forum.arduino.cc/t/is-the-arduino-2-ide-installation-alongside-the-classic-ide-or-a-replacement/698588/2

I see no reason why not. I have several versions on my Linux machine however each is in its own directory, I would assume you need to do the same with windows.

i do it the other way around.


text:
Use digital pins as analog - Arduino Micro
I have an Arduino Micro and I want to use pin 6 and 8 as an analog pin, according to the manual this is possible:

The Micro has a total of 12 analog inputs, pins from A0 to A5 are
  labelled directly on the pins and the other ones that you can access
  in code using the constants from A6 trough A11 are shared respectively
  on digital pins 4, 6, 8, 9, 10, and 12.

What exactly do they mean by constants? I am aware what a constant is in the scope of programming, however I'm not sure what I should use to assign pins 6 and 8 as an analog pin? I assume I cannot just do an analogRead(6)?

Constants are variables that cannot change. They are constant.
In this case they are variables that have been set up in the board definition files (in pins_arduino.h in case you're interested) and are named just as they have said - A6 through A11.  This complements the existing A0 through A5 that are normally there anyway.
So you just use those names and it chooses the right pin for you:
int val = analogRead(A8);

The definitions of the pins are:
static const uint8_t A0 = 18;
static const uint8_t A1 = 19;
static const uint8_t A2 = 20;
static const uint8_t A3 = 21;
static const uint8_t A4 = 22;
static const uint8_t A5 = 23;
static const uint8_t A6 = 24;   // D4
static const uint8_t A7 = 25;   // D6
static const uint8_t A8 = 26;   // D8
static const uint8_t A9 = 27;   // D9
static const uint8_t A10 = 28;  // D10
static const uint8_t A11 = 29;  // D12

So no you cannot just use the number 8, you have to use A8 which points to pin number 26. The Arduino core then interprets that number as an analog pin (as opposed to the digital pin, which is 8) and performs an analog read on it.

so conversely (and for my own understanding), to use these pins as a digital pin (which they are also capable of) I can also do a digitalRead(8)? Furthermore, is the 'A' required? I've read that it automatically assigns A if its an analogRead.

When referring to the pin in a digital context you can use either label.

If A8 equals 8 then they are interchangeable. If not, then not.

I guess I just found it strange that one pin could be used both as analog and as a digital!

I just looked the file up - you cannot use 8, you have to use A8 or 26.

Good to know. I'll have to look at the pins_arduino file for future ref!

What are those pin numbers followed by ; ?

Yes, they are followed by ;


text:
ADS1115, ACS712 and ESP8266
I have an ACS712 (5v sensor), an ADS1115 (5 or 3.3v) and an ESP8266 board (3.3v).
I know I can't directly use the ACS with the ESP without a voltage divider on the analog pin. So I figured I could run the ADS and the ACS off 5 volts as the ADS communicates over I2C. Does this cause any issues with the SDA/SCL lines on the ESP?
What is the correct way in going about this?

The I2C lines of of ADS1115 will use 3.3 V if you power it with 3.3 V, but then the maximum analog input voltage would be 3.6 V (VDD + 0.3 V).

i am aware, but that wasn't my question

The SDA line of of ADS1115 will use 3.3 V if you power it with 3.3 V, but then the maximum analog input voltage would be 3.6 V (VDD + 0.3 V).
The ACS712 has the middle value at 2,5 V so to read it you need the 5 V range and must power the ADS1115 from 5 V. Then the SDA line of esp8266 will be connected to 5 V logic level, but the esp8266 pins can handle 5 V TTL communication currents.
The SCL line is driven from master (esp8266) at 3.3 V and the ADS1115 is good with it.


text:
while(1) inside if conditional
if (!MDNS.begin("esp8266")) {
    Serial.println("Error setting up MDNS responder!");
    while (1) {
      delay(1000);
    }
  }

I know this will result in an infinite loop if the if conditional is never satisfied, however I was wondering if this code would still result in an infinite loop if say, after 3 iterations the if conditional is satisfied?
Or if something like:
while(!MDNS.begin("esp8266")) {
   delay(1000);
}

is different?
Code from: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino (line 58)

why do you feel that the if condition could be satisfied more than once?

i don't. im saying, say in the first iteration it isn't. while loop enters. then what happens? is there any scenario in which we leave this loop? are if(condition) { while(1) } the same as while(conditional) { }

If it isn't then the while loop isn't entered.  The first time the if statement is true then you get to the while loop and the code is dead there forever.  It's very different from the second thing you wrote.  In that while loop it is checking to see if that begin function returns true, not checking that 1!=0

i guess the reason i was asking is because i don't see why the original author wrote it that way unless there was some trickery that i wasn't aware of. basically, they are just halting everything indefinitely which seems odd to me rather than triggering a device restart.

you are somehow missing the fact that the code is just example code that shows how to code a web server ... recovery code would add irrelevant routines

This is likely a case where the original code needs to be inspected to understand the purpose of the infinite loop.  In the original code we see this:
  if (!MDNS.begin("esp8266")) {
    Serial.println("Error setting up MDNS responder!");
    while (1) {
      delay(1000);
    }
  }
  Serial.println("mDNS responder started");

Here, it can be inferred the infinite loop is used to preserve the error message on the serial monitor.  By doing so prevents subsequent messages from announcing the Domain Name Server has started.  Which may confuse the user.
As mentioned in other answers, infinite loops are often used to purposely reset a processor.  However, this approach depend on an actively running watch dog feature.  A feature that is not normally active or even supported in the Arduino development environment.  Perhaps because the watch dog feature is considered an intermediate to advanced topic.

In the first case, the first time, that the outer if statement becomes true, the code will go into the while(1) loop and will be stuck there forever.
The second code is different, since the while loop will check at each start of it's iteration, if the condition is still met. If not, it will exit, so not necessarily an infinite loop.

Going into an infinite loop, if something fails to initialize is often done in the microcontroller world, especially when initializing external hardware. A reset loop (restarting until it works) is mostly not fitting there, because often it is not just waiting for a resource to become free. Often this is used for serious problems, for example external hardware not being there or functioning. Imagine trying to use an external GPS chip, but the chip is not there. It should be there, since the device is build this way. Why should a reset loop be better here? The problem won't get away with time. Or imagine, that the initialization fails, because the GPS chip is broken. Trying to interface such a broken chip repeatedly might break even more things. Either way, someone has to look at this, to fix the problem. It will not go away by itself.
I would say, that the failed initialization in the library above is such a situation.


text:
Strange adding behaviour
I have an Arduino Nano and was adding up some values 2^i from 0..7:
void setup() {
  Serial.begin(9600);
  int i,k;
  k = 0;
  for (i=0;i<8;i++){
     k += pow(2, i);
     Serial.println(k);
  }
}

Those numbers should sum up to 255, but that's the output:
1
3
6
13
28
59
122
249

Is my Arduino not working or what can be the reason for this behaviour?

As a tip for the future, printing the intermediate results would have given you a clue.  For example, adding Serial.print(pow(2, i), 7); gave me:  1.0000000, 2.0000000, 3.9999995, 7.9999980, 15.9999961, 31.9999885, 63.9999771, 127.9999542. The default output of Serial.print rounds so doing Serial.print(pow(2, i)); masks the problem: 1.00, 2.00, 4.00, 8.00, 16.00, 32.00, 64.00, 128.00,

No, there is nothing "wrong" there. In fact it's the expected results.
The problem here is that pow() returns a float, and some numbers just can't be represented with floating point. When that floating point value is converted to an integer it truncates the decimal portion leaving you with the wrong integer value.
void setup() {
    Serial.begin(115200);

    int t = 0;
    for (int i = 0; i < 8; i++) {
        float f = pow(2, i);
        int d = f;
        t += f;
        Serial.print("2^");
        Serial.print(i);
        Serial.print(": float = ");
        Serial.print(f, 10);
        Serial.print(" int = ");
        Serial.print(d);
        Serial.print(" total = ");
        Serial.println(t);
    }
}

void loop() {
}

2^0: float = 1.0000000000 int = 1 total = 1
2^1: float = 2.0000000000 int = 2 total = 3
2^2: float = 3.9999995231 int = 3 total = 6
2^3: float = 7.9999980926 int = 7 total = 13
2^4: float = 15.9999961853 int = 15 total = 28
2^5: float = 31.9999885559 int = 31 total = 59
2^6: float = 63.9999771118 int = 63 total = 122
2^7: float = 127.9999542236 int = 127 total = 249

Instead you should use bit-shifting to perform the same operation on an integer:
void setup() {
    Serial.begin(115200);

    int t = 0;
    for (int i = 0; i < 8; i++) {
        int d = 1 << i;
        t += d;
        Serial.print("1<<");
        Serial.print(i);
        Serial.print(": int = ");
        Serial.print(d);
        Serial.print(" total = ");
        Serial.println(t);
    }
}

void loop() {
}

1<<0: int = 1 total = 1
1<<1: int = 2 total = 3
1<<2: int = 4 total = 7
1<<3: int = 8 total = 15
1<<4: int = 16 total = 31
1<<5: int = 32 total = 63
1<<6: int = 64 total = 127
1<<7: int = 128 total = 255

Actually the values in question most definitely can be precisely represented as floats - all small integers can be, and these are even powers of two on a binary system.  The issue is rather imprecision within the implementation of the pow() function, possibly having to do with intermediate values.  And yes, it is not the way to do this - even apart from the inaccurate results, it is far more computationally intensive.

@ChrisStratton Float is still crap either way. Q15 etc are the way forward.

Granted that integer arithmetic is a computationally better approach to this problem; if your intent was to learn to use floating point and float to int conversions, then you need to round up the floating result before the conversion truncates it. As you saw in @Majenko's example, the floating results are close but not quite exact. In your own example, you'd change
k += pow(2, i);

to
p = pow(2, i); k += (p < 0. ? -0.5 : 0.5);

to so the float would truncate to the nearest int instead to the next lower int.

Note: that trick only works for positive numbers. For negative ones you should subtract 0.5. Or use the round() function.

Yup, shot from the hip. Edited to show the non-round() version.


text:
Connect my Arduinos to central server, despite different IP adresses
Community,
A team of friends just built, with an Arduino UNO, a system where one can open a door lock from the internet.
The Arduino UNO has an Ethernet Module (ENC28J60). When the command prompts, the Arduino will let a solenoid receive 5v, which will open it and, therefore, open the door.
The novel thing is, this door-opening-arduino connects via the Internet to a central server, a webpage that 'centralizes' the door-opening process. So, in a certain URL, we'll get a screen which goes:

All these doors are in remote locations, connected to very different routers. Some of these routers will go 192.168.1.1, whereas others will go with the 0.1 ending.
So far, my friend has hard-coded the internal IP address 192.168.1.143 for identifying the Arduino, so, he's given up on DHCP.
Afterwards, he's chosen port 6560 to be the open port and connect the door to the Internet. (VPN is not a option).
So the public IP address and port 6560 are our way in into the door. This info is shared with his webpage, where commands can be given: 'open it'.
But with these hard-coding of the 1.143 IP and the router's different default addresses, we've had trouble. You know what I mean: sometimes, the whole code must be changed for our Arduino to connect to the router. Not even close to 'plug-n-play'.
My questions seems natural: how can we ensure the Arduino connects each time to the router, without any problems?
Most devices just connect: an IP camera in these routers will connect, and will never care which IP address the router has given it. If the router resets, things will be fine, and connection will restart.
So, why not DHCP? As far as my understanding goes, a problem my friend mentioned that would happen if he chose to use DHCP would be the communication between his Arduino and his online server: 'how can I know which IP I should speak with in order to open the door? By choosing the .143, I know which would should be'.
Another problem comes in with port forwarding. Apparently, by choosing the .143 and then using port 6560, we ensure that we can access via the Internet, because there's a standarized procedure: 'please open port 6560 for this IP'.
This is a bit cumbersome. Most devices just don't work this way. We want to be able to just plug it in, let our Arduino and the router get any IP, and by just opening port 6560, we're in. Pretty simple.
How can we ensure that:

Our Arduino just connects to the router, and
that communication between our Arduino and the centralized server
just flows?

Another friend suggested configuring each router so that a device with a certain MAC address (our Arduino) gets this IP* and this port forwarding. But what if the default address is 192.168.0.1 (instead of 1.1), for example? wouldn't we be facing a problem?
We're seeking a kind of plug-n-play thing, like most access control systems work. Hardware's ok, it's connection the thing that bugs us.
Any suggestions, advice, or plain responses are really welcome. I think we're just a step away from our commit, which is creating a reliable connection for these doors. It may be just a line of code, or a config trick. Thank you for your time.
(you'll soon notice we're not that savvy on routing and switching, so If we got our premises completely wrong, don't hesitate to correct us)

I'd forgo the port forwarding and ip-fixing, and just have the Arduino poll the central server, to see if there's any action that needs to take place. Alternatively use something like pagekite.

Your problem is two-fold, and neither are easy for an Arduino to overcome.
First you have the problem that the router's internet-facing IP address is (unless you have a special arrangement with your ISP) liable to change at any time. You need to keep your sever up to date at all times with what that IP address is, and the only real way of doing that is for the router, or something behind the router, to connect with your server so it can update its IP address.
Secondly you have the port forwarding. The router has to know where to forward the port to. That means that either the IP address of the Arduino has to be static, or the Arduino has to somehow tell the router to do the port forwarding.  The simplest method is just to allocate a static IP address as you have done. The alternative is to use UPnP to instruct the router "I need you to forward this port through to me" - assuming the router understands UPnP. The hardest part of that though is getting the Arduino to speak UPnP. I am not aware of any UPnP libraries for the Arduino.
So keep the static IP address for the Arduino, it is simplest. One thing to note with manually allocating an IP address though is that it is vitally important you allocate it outside the IP address range of the DHCP server. Otherwise it is possible that the DHCP server could then allocate the IP address to someone else, and you'd then get a conflict. Most routers allow you to choose the range of IP addresses so you may want to go in and check that the DHCP server isn't able to clobber the IP address you have chosen.
To help solve the first problem some routers provide a "DDNS" (Dynamic DNS) facility, whereby they will periodically connect to a DDNS service to update a DNS record with the public IP address of the router. Not all provide it and those that do usually only provide access to a couple of DDNS services, so check your router to see if it does support it and if there is a suitable one for your needs there. If there is you can configure that and then, instead of connecting to the IP address of your router for issuing commands you instead connect to the DDNS domain name allocated to your router.
However, there is one much simpler option that solves all the problems in one go: reverse the communications.
Instead of the server connecting to the router to forward the port through to the Arduino to issue a command, it is far simpler (though I will admit not as responsive) for the Arduino, from whatever IP address it happens to be on, to just connect to the server itself and ask it for any pending commands.
If you have the ability to run your own software on the server you could even create your own small TCP server which the Arduino connects permanently to. The server can then send commands down that TCP connection just as if you were working with an Arduino directly connected by serial.
In both those situations it doesn't matter what IP address your router is on. You don't need to do any port forwarding. The Arduino can be on any IP address on your network.
And further more you have more security - no one could connect to your Arduino through the internet and cause havoc.

thank you! just shared this with my programmer friend and he thinks it's a great idea. He´s suggested using Heroku as a server, although we should pay a monthly fee for it, as Heroku "falls asleep" if it isn't used for 30 minutes, and we can't risk that.
Do you have any further advice? such as a platform to use (i.e, it could be Heroku), or a free alternative, or just any other suggestion in programming and deployment? We'll be expectant.

I would use socket.io for this. Here is a goos presentation on this:
http://www.robojay.us/wp-content/uploads/2016/08/NRB-socket-io.pdf


text:
Using ERASE button as PIO on Due
I'm working on a demo program for which I want to use minimal resources: all I need is one LED and one pushbutton.
I'd very much like to use on-board resources. The user LED (PB27) is fine (I'd have liked one more, but there it is).
I read in the datasheet that the ERASE button can be used as an input (PC0) provided that I clear the SYSIO12 bit in the System I/O Configuration Register CCFG_SYSIO.
I find that if I do this I can push the ERASE button without erasing flash (!), but PC0 always reads as 0 (even if I enable pullup; ought to be already enabled, you'd think).
I should say that PC1 works just fine.
Has anyone else got ERASE => PC0 to work? is there documentation I've missed? (in ASF, some of the other boards in sam/applications/getting_started/ disable the ERASE button, but not this one).


text:
How can I update a sketch to a NodeMCU “over the air” with the Arduino IDE?
I’m trying to use a sketch from this repository which uses MQTT to send a notification to Home-Assistant that acts a “presence sensor”.  When the NodeMCU comes into range of the specified SSID, the controller connects to WiFi and sends a MQTT message to home-assistant which can then perform some home automation commands.  This code does exactly that.  The MQTT messages are sent and received.
What is not working is that I can’t update the sketch over the air (OTA) via the included ArduinoOTA library. After uploading this sketch to the NodeMCU, it connects to WiFi and I am getting a message from the console output that the device is ready for OTA updates.  From everything that I’ve read I beleive there is supposed to be an option in the Arduino menus where I can specify that I want to update OTA instead of a com port.  How can I enable this in the IDE?  Also, is there a way to “connect” to the serial monitor so that I can also see the output OTA?
I’m attaching the sketch for your convenience:
////////////////////////////////////////////////////////////////////////////////////////////////////
// Modify these values for your environment
const char* wifiSSID = "wifissid";  // Your WiFi network name
const char* wifiPassword = "wifipassword";  // Your WiFi network password
const char* otaPassword = "myotapassword";  // OTA update password
const char* mqttServer = "192.168.1.2";  // Your MQTT server IP address
const char* mqttUser = ""; // mqtt username, set to "" for no user
const char* mqttPassword = ""; // mqtt password, set to "" for no password
const String mqttNode = "CarPresence"; // Your unique hostname for this device
const String mqttDiscoveryPrefix = "homeassistant"; // Home Assistant MQTT Discovery, see https://home-assistant.io/docs/mqtt/discovery/
////////////////////////////////////////////////////////////////////////////////////////////////////

// Home Assistant MQTT Discovery, see https://home-assistant.io/docs/mqtt/discovery/
// We'll create one binary_sensor device to track MQTT connectivity
const String mqttDiscoBinaryStateTopic = mqttDiscoveryPrefix + "/binary_sensor/" + mqttNode + "/state";
const String mqttDiscoBinaryConfigTopic = mqttDiscoveryPrefix + "/binary_sensor/" + mqttNode + "/config";
// And a sensor for WiFi signal strength
const String mqttDiscoSignalStateTopic = mqttDiscoveryPrefix + "/sensor/" + mqttNode + "-signal/state";
const String mqttDiscoSignalConfigTopic = mqttDiscoveryPrefix + "/sensor/" + mqttNode + "-signal/config";
// And a sensor for device uptime
const String mqttDiscoUptimeStateTopic = mqttDiscoveryPrefix + "/sensor/" + mqttNode + "-uptime/state";
const String mqttDiscoUptimeConfigTopic = mqttDiscoveryPrefix + "/sensor/" + mqttNode + "-uptime/config";

// The strings below will spill over the PubSubClient_MAX_PACKET_SIZE 128
// You'll need to manually set MQTT_MAX_PACKET_SIZE in PubSubClient.h to 512
const String mqttDiscoBinaryConfigPayload = "{\"name\": \"" + mqttNode + "\", \"device_class\": \"connectivity\", \"state_topic\": \"" + mqttDiscoBinaryStateTopic + "\"}";
const String mqttDiscoSignalConfigPayload = "{\"name\": \"" + mqttNode + "-signal\", \"state_topic\": \"" + mqttDiscoSignalStateTopic + "\", \"unit_of_measurement\": \"dBm\", \"value_template\": \"{{ value }}\"}";
const String mqttDiscoUptimeConfigPayload = "{\"name\": \"" + mqttNode + "-uptime\", \"state_topic\": \"" + mqttDiscoUptimeStateTopic + "\", \"unit_of_measurement\": \"msec\", \"value_template\": \"{{ value }}\"}";

// Set the signal strength and uptime reporting interval in milliseconds
const unsigned long reportInterval = 5000;
unsigned long reportTimer = millis();

// Set LED "twinkle" time for maximum daylight visibility
const unsigned long twinkleInterval = 50;
unsigned long twinkleTimer = millis();

#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <PubSubClient.h>

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

////////////////////////////////////////////////////////////////////////////////////////////////////
// System setup
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(115200);

  Serial.println("\nHardware initialized, starting program load");

  // Start up networking
  setupWifi();

  // Create server and assign callbacks for MQTT
  mqttClient.setServer(mqttServer, 1883);
  mqttClient.setCallback(mqtt_callback);

  // Start up OTA
  if (otaPassword[0]) {
    setupOTA();
  }

  Serial.println("Initialization complete\n");
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Main execution loop
void loop() {
  // check WiFi connection
  if (WiFi.status() != WL_CONNECTED) {
    setupWifi();
  }

  // check MQTT connection
  if (!mqttClient.connected()) {
    mqttConnect();
  }

  // MQTT client loop
  if (mqttClient.connected()) {
    mqttClient.loop();
  }

  // LED twinkle
  if (mqttClient.connected() && ((millis() - twinkleTimer) >= twinkleInterval)) {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    twinkleTimer = millis();
  }

  // Report signal strength and uptime
  if (mqttClient.connected() && ((millis() - reportTimer) >= reportInterval)) {
    String signalStrength = String(WiFi.RSSI());
    String uptimeTimer = String(millis());
    mqttClient.publish(mqttDiscoSignalStateTopic.c_str(), signalStrength.c_str());
    mqttClient.publish(mqttDiscoUptimeStateTopic.c_str(), uptimeTimer.c_str());
    reportTimer = millis();
  }

  // OTA loop
  if (otaPassword[0]) {
    ArduinoOTA.handle();
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Functions

////////////////////////////////////////////////////////////////////////////////////////////////////
// Handle incoming commands from MQTT
void mqtt_callback(char* topic, byte* payload, unsigned int payloadLength) {
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Connect to WiFi
void setupWifi() {
  Serial.print("Connecting to WiFi network: " + String(wifiSSID));
  WiFi.hostname(mqttNode.c_str());
  WiFi.mode(WIFI_STA);
  WiFi.begin(wifiSSID, wifiPassword);

  while (WiFi.status() != WL_CONNECTED) {
    // Wait 500msec seconds before retrying
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nWiFi connected successfully and assigned IP: " + WiFi.localIP().toString());
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// MQTT connection and subscriptions
void mqttConnect() {
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.println("Attempting MQTT connection to broker: " + String(mqttServer));
  // Attempt to connect to broker, setting last will and testament
  if (mqttClient.connect(mqttNode.c_str(), mqttUser, mqttPassword, mqttDiscoBinaryStateTopic.c_str(), 1, 1, "OFF")) {
    // when connected, record signal strength and reset reporting timer
    String signalStrength = String(WiFi.RSSI());
    reportTimer = millis();
    String uptimeTimer = String(millis());
    // publish MQTT discovery topics and device state
    Serial.println("MQTT discovery connectivity config: [" + mqttDiscoBinaryConfigTopic + "] : [" + mqttDiscoBinaryConfigPayload + "]");
    Serial.println("MQTT discovery connectivity state: [" + mqttDiscoBinaryStateTopic + "] : [ON]");
    Serial.println("MQTT discovery signal config: [" + mqttDiscoSignalConfigTopic + "] : [" + mqttDiscoSignalConfigPayload + "]");
    Serial.println("MQTT discovery signal state: [" + mqttDiscoSignalStateTopic + "] : " + WiFi.RSSI());
    Serial.println("MQTT discovery uptime config: [" + mqttDiscoUptimeConfigTopic + "] : [" + mqttDiscoUptimeConfigPayload + "]");
    Serial.println("MQTT discovery uptime state: [" + mqttDiscoUptimeStateTopic + "] : " + uptimeTimer);
    mqttClient.publish(mqttDiscoUptimeConfigTopic.c_str(), mqttDiscoUptimeConfigPayload.c_str(), true);
    mqttClient.publish(mqttDiscoUptimeStateTopic.c_str(), uptimeTimer.c_str());
    mqttClient.publish(mqttDiscoBinaryConfigTopic.c_str(), mqttDiscoBinaryConfigPayload.c_str(), true);
    mqttClient.publish(mqttDiscoBinaryStateTopic.c_str(), "ON");
    mqttClient.publish(mqttDiscoSignalConfigTopic.c_str(), mqttDiscoSignalConfigPayload.c_str(), true);
    mqttClient.publish(mqttDiscoSignalStateTopic.c_str(), signalStrength.c_str());
    Serial.println("MQTT connected");
    digitalWrite(LED_BUILTIN, LOW);
  }
  else {
    Serial.println("MQTT connection failed, rc=" + String(mqttClient.state()));
  }
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// (mostly) boilerplate OTA setup from library examples
void setupOTA() {
  // Start up OTA
  // ArduinoOTA.setPort(8266); // Port defaults to 8266
  ArduinoOTA.setHostname(mqttNode.c_str());
  ArduinoOTA.setPassword(otaPassword);

  ArduinoOTA.onStart([]() {
    Serial.println("ESP OTA:  update start");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("ESP OTA:  update complete");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    //Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.println("ESP OTA:  ERROR code " + String(error));
    if (error == OTA_AUTH_ERROR) Serial.println("ESP OTA:  ERROR - Auth Failed");
    else if (error == OTA_BEGIN_ERROR) Serial.println("ESP OTA:  ERROR - Begin Failed");
    else if (error == OTA_CONNECT_ERROR) Serial.println("ESP OTA:  ERROR - Connect Failed");
    else if (error == OTA_RECEIVE_ERROR) Serial.println("ESP OTA:  ERROR - Receive Failed");
    else if (error == OTA_END_ERROR) Serial.println("ESP OTA:  ERROR - End Failed");
  });
  ArduinoOTA.begin();
  Serial.println("ESP OTA:  Over the Air firmware update ready");
}

Follow the instruction here https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#application-example
First load the OTA example specified. Do not waste your time implementing it in your code until you have the supplied example working.
If you are running Windows then it helps to have an application called Bonjour Browser. The OTA method makes use of mDNS. I use Bonjour Browser to confirm that the ESP is being seen. Then I go to ports in the IDE and there is an entry for the newly added OTA device.
Select the entry instead of the com ports. Then compile and upload.
If you get an error then do a power cycle on the ESP board. You should only need to do this once after the serial upload.
I use this method but sometimes the device does not appear below the com listed. I have had to close and restart the IDE to refresh the device listing. (I think this is a Windows issue) Because of this I prefer the webupdater method.
https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html#web-browser

good answer Rudy. In Sloeber (Arduino Eclipse plugin) I can enter the IP address and must not relay on mDNS

of the available OTA methods, this one is the simplest imho.

Done this form a Linux laptop's command line.
For uploading to Arduino boards, I have been using (via the usual USB port connection) the command line methods as detailed at: https://github.com/arduino/Arduino/blob/master/build/shared/manpage.adoc
For the OTA method of uploading to the ESP, I just chanced to discover the following method.
As the argument to "--port", I just used the ip of the wifi connected ESP board.
Let us say I want to upload a sketch "myexample1.ino" to my ESP8266 board "ESP-01 (1MB)" having OTA firmware on it. Am using Arduino 1.8.8 and ESP8266 community version 2.4.2. As already stated, the ESP-01 has the example sketch "BasicOTA.ino" uploaded to it via the usual USB port. Now, the ESP-01 is not connected via USB. It is connected to my wifi router at an ip (say, 192.168.22.221). The following command successfully uploaded the code:
~/Arduino/myexample1 $ arduino --upload myexample1.ino --port 192.168.22.221
Just felt like sharing a nice experience not found reported elsewhere on the internet.


text:
See compiled assembly output (Visual Micro)
I'm curious about what some of my code is being compiled into, is there a way to have the compiler save the intermediate assembly files, ideally somewhere in the project folder?  I read some forum posts about holding down shift when compiling from the Arduino IDE, but even that seems pretty hackish.

Also see answer to a compiled code size question,  and see Does the compiler generate intermediate assembler?,

Thanks, that's helpful.  I think my question is more of how though?  I can see in the Visual Micro project properties how to pass flags to the compiler, but it doesn't seem to recognize the --save-temps=obj flag.  Its probably another question but I don't know how to pass flags from the Arduino IDE either.

The 2nd post in Assemler results, where? at forum.arduino.cc mentions the  -S switch and gives a batch file for Windows.  Note, probably won't apply to Visual Micro, but to set Arduino IDE to save temp files, click 'Save when Verifying or Uploading' on preferences page -- you could try both ways and see what flags get used

Turn on Verbose Compiling in the Arduino IDE and you will see all the intermediate file names (they are done in a temporary folder).
For example:
/home/nick/Development/arduino-1.6.7/arduino-builder -dump-prefs -logger=machine -hardware "/home/nick/Development/arduino-1.6.7/hardware" -hardware "/home/nick/.arduino15/packages" -hardware "/home/nick/Arduino/hardware" -tools "/home/nick/Development/arduino-1.6.7/tools-builder" -tools "/home/nick/Development/arduino-1.6.7/hardware/tools/avr" -tools "/home/nick/.arduino15/packages" -built-in-libraries "/home/nick/Development/arduino-1.6.7/libraries" -libraries "/home/nick/Arduino/libraries" -fqbn=arduino:avr:uno -ide-version=10607 -build-path "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp" -warnings=default -prefs=build.warn_data_percentage=75 -verbose "/tmp/arduino_1cdca0d02fcf3112936d1438c170697d/sketch_mar03b.ino"
/home/nick/Development/arduino-1.6.7/arduino-builder -compile -logger=machine -hardware "/home/nick/Development/arduino-1.6.7/hardware" -hardware "/home/nick/.arduino15/packages" -hardware "/home/nick/Arduino/hardware" -tools "/home/nick/Development/arduino-1.6.7/tools-builder" -tools "/home/nick/Development/arduino-1.6.7/hardware/tools/avr" -tools "/home/nick/.arduino15/packages" -built-in-libraries "/home/nick/Development/arduino-1.6.7/libraries" -libraries "/home/nick/Arduino/libraries" -fqbn=arduino:avr:uno -ide-version=10607 -build-path "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp" -warnings=default -prefs=build.warn_data_percentage=75 -verbose "/tmp/arduino_1cdca0d02fcf3112936d1438c170697d/sketch_mar03b.ino"
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/cores/arduino" "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/variants/standard" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch/sketch_mar03b.ino.cpp" -o "/dev/null"
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/cores/arduino" "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/variants/standard" "-I/home/nick/Arduino/libraries/PID_v1" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch/sketch_mar03b.ino.cpp" -o "/dev/null"
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/cores/arduino" "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/variants/standard" "-I/home/nick/Arduino/libraries/PID_v1" "/home/nick/Arduino/libraries/PID_v1/PID_v1.cpp" -o "/dev/null"
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/cores/arduino" "-I/home/nick/Development/arduino-1.6.7/hardware/arduino/avr/variants/standard" "-I/home/nick/Arduino/libraries/PID_v1" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch/sketch_mar03b.ino.cpp" -o "/dev/null"
...
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-ar" rcs  "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/core/core.a" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/core/main.cpp.o"
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-ar" rcs  "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/core/core.a" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/core/new.cpp.o"
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-gcc"  -Os -Wl,--gc-sections -mmcu=atmega328p  -o "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch_mar03b.ino.elf" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch/sketch_mar03b.ino.cpp.o" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/libraries/PID_v1/PID_v1.cpp.o" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/core/core.a" "-L/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp" -lm
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0  "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch_mar03b.ino.elf" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch_mar03b.ino.eep"
"/home/nick/Development/arduino-1.6.7/hardware/tools/avr/bin/avr-objcopy" -O ihex -R .eeprom  "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch_mar03b.ino.elf" "/tmp/build1cdca0d02fcf3112936d1438c170697d.tmp/sketch_mar03b.ino.hex"
Using library PID_v1 in folder: /home/nick/Arduino/libraries/PID_v1 (legacy)

Sketch uses 6,484 bytes (20%) of program storage space. Maximum is 32,256 bytes.
Global variables use 285 bytes (13%) of dynamic memory, leaving 1,763 bytes for local variables. Maximum is 2,048 bytes.

Of interest are the last couple - the xxx.elf file and the xxx.hex file (where xxx is your sketch name).
The xxx.hex file is what is uploaded to your Arduino (well, it is decoded by Avrdude).
The xxx.elf file can be used to get assembly output, like this:
avr-objdump -Sz xxx.elf

That outputs to the screen. I usually output to a file:
avr-objdump -Sz xxx.elf > /tmp/avr_dump.txt

Example output:
void setup() {
      ec:   0f 93           push    r16
      ee:   1f 93           push    r17
  Setpoint = 100;
      f0:   80 e0           ldi r24, 0x00   ; 0
      f2:   90 e0           ldi r25, 0x00   ; 0
      f4:   a8 ec           ldi r26, 0xC8   ; 200
      f6:   b2 e4           ldi r27, 0x42   ; 66
      f8:   80 93 73 01     sts 0x0173, r24
      fc:   90 93 74 01     sts 0x0174, r25
     100:   a0 93 75 01     sts 0x0175, r26
     104:   b0 93 76 01     sts 0x0176, r27
  //turn the PID on
  myPID.SetMode(AUTOMATIC);
     108:   61 e0           ldi r22, 0x01   ; 1
     10a:   70 e0           ldi r23, 0x00   ; 0
     10c:   82 e3           ldi r24, 0x32   ; 50
     10e:   91 e0           ldi r25, 0x01   ; 1
     110:   0e 94 04 04     call    0x808   ; 0x808 <_ZN3PID7SetModeEi>

In this particular  case Setpoint was a double so it took 8 instructions to load a literal into it.


text:
Visual Micro without .ino files
I am using the visual micro extension for Visual Studio 2015.  I would like to not use any .ino files since I'm trying to setup cppcheck which doesn't recogonize .cpp files, and its just what I'm used to.  However when I change my project.ino file to project.cpp the compile option is no longer available (I assume its looking for a .ino file).  Is there a project setting I can change to fix this?

Make a new tab in the IDE (top RH corner) with a xxx.cpp file name. Put your code in that. Leave the .ino file blank. Then it will compile. You need to add:
#include <Arduino.h>

... to the start of the .cpp file.
More information: How to avoid the quirks of the IDE sketch file pre-preprocessing

To clarify the question about libraries ...
You do need to put into the .ino file an include for any libraries used in the project. For example:
#include <Wire.h>
#include <SPI.h>
#include <EEPROM.h>

This effectively triggers the Arduino build process to link those libraries into the final executable file.
Related, my reply in this thread: Classes and objects: how many and which file types do I actually need to use them?

Thanks, that seems to be working in the Arduino IDE, but where I really need it to work is using the Visual Micro visual studio addin.  When I compile the project there I get #fatal error: SPI.h: No such file or directory so it doesn't seem to be handling the library paths correctly.

Nvm, the link you posted addresses this.

As you have found, Visual Micro will not consider the project to be an Arduino project if you do not have a "project_name.ino" included in the project
A cheat is to create a "project_name.cpp" and include it in the project. This will cause the .ino to be ignored during compilation.
EDIT: The project_name.cpp takes priority during compile, therefore the .ino just becomes a dummy. However the .ino will still be used for intellisense. The cpp should be #included in the .ino along with any libraries you want discovered by intellisense.
The Visual Micro release yesterday includes automatic "library in library" discovery which means you would no longer need to put all lib #include's in the project_name.ino. (tip: you can switch the "deep search" feature off for each project via the Visual Micro menu. It slows the compile down with large libraries)

Just to clarify, if "deep search" is off would the #includes still need to be in the .ino files?

Yes. With "Deep Search Off" all possible library includes need to be in the master .ino file. Then deep search is pointless :)


text:
Reading sensor data over MUX
I will start by saying I am very new to using Arduino.  The project I am planning is to create several arrays of sensors (each array will consist of 4 DS18B20 sensors and one temperature/humidity sensor) and using a MUX connected to Arduino I want to read the data from each [ten] array.  I have found sketches I can modify to do this task in a continuous cycle but I need to be able to display data from an array for an extended time period of several minutes.  My Arduino will output to a 3.2" LCD so there is only enough screen space to show data for one array at a time.

Push the "edit" button and add more info or at least ask a question.

DS18B20 sensors don't need a mux. You can have 40 DS18B20's on a single line. As to the "question". You could add some buttons below the LCD to select which array data to show.

You have posted a statement, not a question. You could post your code, perhaps? Also state what happens, and what you expect to happen.

The DS18B20 is a 1-Wire device and doesn't require a multiplexer, each device has its own address on the bus and you can connect a lot of them with a single wire. Depending on the humidity sensor you pick you may be able to use the same bus for it as well.
It is harder to find 1-Wire humidity sensors, but you could use a DS2438 Smart Battery Monitor which also includes an ADC to give you values from an analog humidity sensor.
The challenge of designing your project will be setting up an easy to understand display and controlling how/when it changes.


text:
connection between Arduino Uno with nRF24L01 and notebook with wireless card
My project intend to command an Arduino UNO by my notebook without cable. I thought to use a RF Nordic nRF24L01 cabled on an Arduino UNO, and to use the wireless card of my notebook to send command to it. Is it possible? Any solution?
Is this hardware solution possible?
I need to send to Arduino four analog signals to setup the light of four led.

Absolutely no. Can you connect your bluetooth headset to the wireless router? No because even if they share the same band they "speak" different protocols. So why could you do that with the nRF24L01?
If you want to communicate with your PC you have three options:

Choose nRF24L01. In this case, since the PC does not have that device, you will need to make an adapter (the easiest one could be an USB adapter). You can connect a microcontroller to a USB to serial converter and to the nRF24L01 and use it as a bridge.
Choose Wifi. Then you'll need a new transceiver for the arduino UNO you are using (maybe the ESP8266, which is around 2$) but can be a bit more complicated for just sharing data (I never used it, though, so I can be wrong).
Choose bluetooth. Usually this is my preferred way to communicate with a board. Cheap (the HC-06 module is about 2-3 $) and easy to use (the interface is a plain serial).

Good luck ;)

Might be worth trying the ESP8266 versions with USB interface. Programming them can be as easy as it is with any Arduino if you are using the Arduino IDE. I personally tend to stay away from bluetooth. Turning on bluetooth on my phone / laptop is too much effort:) WiFi is always on anyway.

@frarugi87, could you suggest a nRF24L01 module with USB adapter for my notebook? And which one for Arduino UNO?

@larzz11 But you have to implement a more complicated protocol (search for the device in the net, for instance) and I don't know if the ESP supports a direct TCP connection. The BT is much more easy to use (on the PC or phone you have a new serial interface, on the arduino... too ;) ). Anyway what you pointed out about the "turn on/off" is right :P Just one thing: why should you use the ESP USB version? It's easier to connect the arduino to it throigh the serial interface.. The PC is already connected to the wifi :P

@SPS just go on ebay and search for "nRF24L01 usb". I never used them, though, and I don't know what a "serial adapter" can do because the nRF has an SPI interface. If you want to try you can buy one and see if it works. Personally I'd design my own one using any microcontroller and writing my code...

@frarugi87 the cheapest solution? to buy another micro-controller (another Arduino??) and nRF24L01 or nRF24L01+USB? Could you provide some examples? Thanks

@SPS Some examples? go to ebay, write "nRF24L01 USB" to get these results. I think it's pretty easy..... As for the cheapest solution, probably those module work. You can give them a try... If, on the other hand, you want to spend some time on it, you can buy a board like the arduino nano, or the arduino micro + usb to serial adapter, or just any microcontroller (even an attiny where you can put the USB tiny code to get a HID device)... By the way usually when an answer is "satisfactory" you should accept it...

You could emulate BTLE with NRF24L01+ if your PC also supports it. Some amount of communication is possible I think but you would have to be quite creative.

@Avamander never knew you could "fake" BLE with a nRF24L01. Thank you! Anyway you can't receive data on the nRF, just broadcast (so you can only send data FROM arduino TO PC/mobile, and everybody with BT on will see the message). Anyway... Thank you!

@frarugi87 Is this a complete one (1 module USB for notebook + 1 module on arduino ), good for me? Or do I need another one? I'm a bit confused :-(

It looks like a good one. But again I never used them, so I don't know how they work. If you can get it to work then share your experience by just saying "Hey, it works" or "Nope, doesn't"


text:
Arduino Uno, HM-10 Bluetooth Module, Not Discoverable
In short, I've hooked up an HM-10 to digital pins 10 and 11 on my Uno (required because TX/RX (0/1) can't be used whilst a serial connection is present). The Bluetooth module is a Sunfounder HM-10 which comes with a data sheet. I'm successfully communicating with the HM-10 and I've written a modified version of serial comms tutorial code provided so it stores the reads up in a buffer before outputting them which works fine, I can set all properties on the HM-10 using this method.
The delays were necessary as it seems the clock cycle can't 'keep up' - bytes go missing when reading/writing, so if I attempt to write by just using Serial.read() in loop() alone then not all of it is read/written.
Here's the code.
#include <SoftwareSerial.h>

SoftwareSerial mySerial(10, 11); // RX, TX

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(57600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.println("Goodnight moon!");

  delay(500);

  // set the data rate for the SoftwareSerial port
  mySerial.begin(9600);
  mySerial.print("Wake up wake up wake up wake up wake up! Wake up wake up wake up wake up wake up!");
}

void loop() // run over and over
{
  if (mySerial.available()) {
    String s = "";
    char c;
    while((c = mySerial.read()) != -1) {
      s += c;
      delay(10);
    }

    Serial.println("Received: " + s);
  }

  if (Serial.available()) {
    String s = "";
    char c;
    while((c = Serial.read()) != -1) {
      s += c;
      delay(10);
    }

    delay(10);

    Serial.println("Sent: " + s);

    mySerial.print(s);
  }
}

This allows me to show input and output as follows:
Sent: AT+ADDR?
Received: OK+ADDR:F4B85EB42D64
Sent: AT+ADVI?
Received: OK+Get:0
Sent: AT+ALLO?
Received: OK+Get:0
Sent: AT+BATT?
Received: OK+Get:077

So good so far. Here's what I can't figure out from the data sheet. How do I make the bluetooth module discoverable on, say, my Mac or from my iPhone? I've tested setting AT+ROLE0 or AT+ROLE1 followed by AT+RESET and also set AT+NAME so I know what to expect, yet I can't discover the module.
Also to note, the status LED is flashing as per the specification as an unconnected status (500ms high, 500ms low) which indicates AT+PIO10 is setup. AT+ADTY? is set to 0 which allows it to be advertising, responds to scanning and connectable.
I'm likely missing something quite obvious. Any ideas?

I'm voting to close this question as off-topic because it is about BLE and phones, not about Arduino.  The original migration to this site was improper; it should have remained where it was asked, or simply been closed.

Ah, I jumped the gun. Just found out Mac/iPhone can't scan for BLE devices, so I downloaded a BLE scanning app and once I set AT+ROLE0 and AT+RESET it appeared.
So, the answer is you need a BLE scanning application.

Thanks for your answer! In another thread, I found a free iOS bluetooth scanning app called LightBlue Explorer (https://itunes.apple.com/au/app/lightblue-explorer-bluetooth/id557428110?mt=8) which also lets you read/write to the device. Super handy. Adding that here for the next person who encounters this thread and wants a rec for a scanning app.


text:
How to change Windows 10 Device Manager so Arduino NANO COM3 can operate on COM4
The Arduino ATmega328 NANO uses COM3 on my WINDOWS 10 computer,
but COM3 is NOT available.
QUESTION:
Please explain in detail how I can change this Arduino NANO
to operate on COM4

What do you mean com3 is not available...?

if COM3 is not available, then the Nano is not using COM3 or it is not plugged in or it has failed in some way

In device manager, right click on the device and select "Properties". Then go to the tab "Connection properties" and click on "Advanced". There you can change the COM port number assignment for a particular device.

In general, Windows assigns COM ports to USB devices when they are plugged in the first time.  If you have multiple USB sockets, the same physical device will be assigned a different COM port when plugged into different sockets.  Is it possible that you have changed your setup and are now using a different USB socket?  Try the others to see if that works.


text:
Possible error in CAN-Bus shield schematic?
This is a part of SeeedStudio CAN-Bus shield schematic. The vertical green line on the left seems suspicious to me. Am I missing something?

No, it's not a mistake. It's related to this statement on their Wiki:

When you use more than two CAN Bus Shield in one net, you should take the impedance into consideration. You should either cut P1 in the PCB with a knife, or just remove R3 on the PCB.

If you look closely at the pads of P1 you will see a small trace joining them together. That is the "rogue" green line you found. By cutting that trace you disconnect the termination resistor. You can then re-connect the termination resistor by soldering the pads together again.

Yes, that very remark is what drew my attention to the pad jumper. I assumed "P1" is what I will be cutting. Also on the PCB the part is labelled as "P1". Now you are telling me the part I will be cutting has no special symbol in the schematic and is merely described by a boring green line. :) That is... unexpected.


text:
timer interrupts on an esp8266
Folks.
I'm working on an ESP8266 and keen to switch to using:

an object approach -> sorted;
physical interrupts on the hardware pins -> sorted;
timer interrupts -> driving me crazy!

My problems are that:

There are so many timer libraries
I can't find one that works on my set-up; either they don't compile, or they have unfulfilled dependencies
Some look promising, but then it turns out something needs to be polled to see if the timer has triggered

Can anyone help me out here please?  I just want a straight-forward approach to setting a simple timer on the 8266 that will trigger an ISR where I can switch off an output now and then tidy up later.
Regards, David (Southampton)

Have you looked at the Ticker class (the one included in ESP8266 platform?)

Brilliant - it's simple yet flexible, it compiles - and it does the job.  Thank you!


text:
Power Arduino Mega ESP85266
Is it possible to Power a Arduino Mega 2560 and a NodeMCU V2 ESP8266 ESP-12E from a single 9V Block?
What would be the best solution?

Can i power the ESP8266 directly via the Arduino Mega 5V output? (3.3V Output seems to weak)
Is a Power Converter like this for the ESP8266 necessary?
Should i use another external Power source for the ESP8266?

Thanks for any Help :)

Is it possible to Power a Arduino Mega 2560 and a NodeMCU V2 ESP8266 ESP-12E from a single 9V Block?

Yes. Assuming the "block" can provide enough current.

Can i power the ESP8266 directly via the Arduino Mega 5V output? (3.3V Output seems to weak)

No.

Is a Power Converter like this for the ESP8266 necessary?

Yes if you are powering it from more than 3.3V.

Should I use another external Power source for the ESP8266?

Not necessary if the 9V one can provide enough current as I mentioned above.

*Can i power the ESP8266 directly via the Arduino Mega 5V output? (3.3V Output seems to weak)
No* - why not? I'm not questioning your answer, just wanted a reason why the Mega 5v can't be used to power a nodemcu via the nodemcu's Vin

The mega can only provide Max 800mA. That has to include what the mega uses, which leaves only just enough for the esp8266. You really need 1A for the nodemcu to work reliably.

fair enough, I thought the Mega could provide 1A - but that seems to be the spec for an Uno

It varies from model to model. The actual limit actually is dependant on the incoming voltage and how much heat that generates in the regulator. In practice you can't get more than a few hundred milliamps before it gets hot if you have 9v or more on the input.

The "1A" is the rating of the regulator. That is only achievable with good heat sinking and minimal difference between input and output voltages. With anything over about 9V half your power (or more) is being converted to heat - and there isn't good heatsinking. So it gets too hot and shuts down. On an Arduino I wouldn't want to draw more than maybe 400mA with >9V on the input.


text:
Is NVS storage reset during an OTA update? (ESP32)
I plan to save some settings in the NVS repository of my ESP32, which will also be implemented OTA update.
The question arose, will the data in the NVS storage be reset when the OTA update is launched?

no. why would it?


text:
Sizes of the original ESP32-DevKitC-32U Wifi board
I know that this topic does not apply to Arduino, but for me it is important to find a solution to the problem. I know the consequences.
I'm creating a pcb board into which the original ESP32-DevKitC-32U module will be inserted. I can not find the original dimensions of the board, in particular the distance between the contact rails. The site espressif has a small description.

27.9mm is indicated here. It is not clear to me, is this the full width of the board or the distance between the contacts?
What I want to do:

It is very important for me to find out the correct dimensions of the original board. Maybe someone has such a board and can measure this size?

The distance of the headers is breadboard and perfboard compatible for 0.1" (2.54 mm) pin standard. 25.4 mm is 10 rows.

I am taking a class and the instructor used a DEVKITC V4, which on a standard breadboard, plugged into columns b and i.  The DEVKITC that I ordered from Mouser plugs into columns b and j.  So one is a pin-to pin width of 25.4 mm and the other is 27.9 mm.  It seems that the newer DEVKITC V4 is 27.9 and is very difficult to work with on standard breadboard.  PITA!


text:
Neopixel LED control without library
I plan to use a single address LED (SK6812 or WS2812) to indicate controller status.
The goal is to include colors: Green / Blue / Red.
There are libraries like Neopixel, Fastled, and others, but I don’t have much space to include them in the program.
How difficult is it to implement color inclusion without the use of libraries and interrupts?

You could try the code from this article. It does not use any library for controlling any number of Neopixels. Only code that controls the timing

Why not use a regular RGB-led? Connect the led to 3 output pins (with resistors), and use digitalWrite to turn the colors on and off.

not difficult ... check the datasheet for required data signal timing

Again, to develop a solution we need to know more.  The tricky part of controlling the WS2812 is developing a signal that the WS2812 expects.  If you are just changing colors, say, no faster than once a second & you can wait and do nothing else with the processor during the fraction of a second it takes to talk to the WS2812, then, as @jsotola said, read the WS2812 data sheet and develop the correct serial signal.  You could further simplify it by only requiring the WS2812 to light up Red, Green, Blue or Off.  Then you would only need to send out 1 of 4 fixed patterns.