message:
Is there an Arduino library that uses ARP to get list of connected devices on network?

I have been looking for a library that can execute an ARP (Address Resolution Protocol) command to return a list of connected devices on the network. The idea is that it would send the request to the gateway and get a list of MAC addresses of currently connected devices as a sort of "who's home" request.

I have searched around Arduino's libraries and have not found any that specifically perform this type of functionality so I was hoping that maybe it was available in a function within a broader networking library.

The particular networking interface (wifi via ESP8266/ESP32 or Ethernet) does not matter as I have not chosen a specific board for the job yet. I'm interested in any library solution that would allow me to poll the gateway to see which devices are currently online without having to buy a special device like [FingBox][1].

Any recommendations for a library that includes this functionality or an approach that would allow me to send ARP commands over the network?

  [1]: https://www.fing.com/products/fingbox

body:
[ARP][1] isn't generally used the way you described. Per the spec, to resolve an IP address into a MAC address, you broadcast an ARP request for the IP address, and receive  a unicast response from the host whose address it is - not a router. It also only resolves a single IP address in one request; it doesn't return the contents of the entire ARP cache.

While you could potentially unicast ARP requests to a router, it's anybody's guess as to whether the router would respond - it's not required to. By spec only the computer who's IP address is being queried should respond - so a router should not unless you've sent it an ARP request for its IP address. You'd also have to send one request for each IP address in the range specified by the LAN's network mask.

You're better off using [SNMP][2], if the router supports it. SNMP can read the router's entire ARP cache with very little overhead (and very few packet exchanges).

The are SNMP implementations for the ESP32 and ESP8266, but they're likely to be difficult to use. Googling will find them for you.

  [1]: https://www.rfc-editor.org/rfc/rfc826
  [2]: https://www.rfc-editor.org/rfc/rfc1157


sender: user

sender: assistant

body:
I was searching for the same function but I think you don't need to query the gateway.

My idea is to loop through all the valid ip addresses, send a ping to each one (it does not matter if they don't answer the ping), and we should have the MAC for this ip. Then check if this MAC is in a list saved in some non volatile space (may be an sd card) and if it's not in the "known peers" list, add it and send a message warning about a new device added to the network.
Using the MAC address instead of the ip for identifying the devices should avoid problems with dynamic ips recognized as new.


message:
Recommended way to fork a library

I want to extend a library, available on github to add some features I need.
Of course I will made available the new source code as well.
Because it's the first time I do this, I'm not sure how to do.

My idea:

1. fork the original repository
2. create a new branch
3. make the changes
4. commit them locally
5. push the new branch on another (mine) repository (of course, to avoid messing up the original one)

Is it correct?
How to test the library while developing it? I mean, in which folder I have to clone the repo?

body:
Almost.

1. Fork the library to your account
2. Check out your fork
3. Edit as needed
4. Commit locally
5. Push back to your fork

Your fork is yours to do with as you wish. Github makes it easy, should you wish, to then pass those changes back up to the original repository (make a "pull request"). But you don't have to do that (and probably don't want to).

You *can* make a new branch if you like, but that's pointless - your fork is, in effect, a branch itself (well, it's an entire new tree really).


message:
Lolin NodeMCU V3 and 5V sensors

I am new to Arduino and electronics so please correct me if I made a mistake.

Many sensors and actuators require 5V. The Lolin NodeMCU V3 has outputs of 3.3V. I want to have them working together.

I have read that the VIN pin outputs the voltage of the USB power source, which is around 5V. I bet that many sensors and actuators can be connected to VIN.

I guess that the main difference with the VCC pin of other boards is the accuracy and stability of the potential.

**1)** What about the amperage? (I guess that the max amperage of the USB power supply is divided between the board and sensors/actuators connected). How does it compare with the VCC output of, let say, an Arduino UNO?

**2)** How important is in most practical cases not having exactly 5V? (clearly, I am not considering using the sensors for extremely accurate measurements). I am interested in things like movements/distance/light/accelerometers/humidity etc. sensors and LCD displays, relays, small motors, etc..

I have seen that many sensors have a not so narrow range of working voltages. That makes me think that small oscillations in the USB voltage may not be significant.

**3)** Is there a better yet simple way to connect 5V devices to this board?

Thank you in advance.

body:
> What about the amperage? (I guess that the max amperage of the USB power supply is divided between the board and sensors/actuators connected). How does it compare with the VCC output of, let say, an Arduino UNO?

The 5V pin is connected directly to the 5V of the USB. Whatever your USB port can provide the 5V can provide, minus the current used by the ESP8266.

> How important is in most practical cases not having exactly 5V? (clearly, I am not considering using the sensors for extremely accurate measurements). I am interested in things like movements/distance/light/accelerometers/humidity etc. sensors and LCD displays, relays, small motors, etc..

That all depends on the device. Read the datasheet. Look at the Electrical Characteristics. It will tell you the recommended (and the absolute maximum) voltage range.

> Is there a better yet simple way to connect 5V devices to this board?

Again, it all depends on the devices. Many many devices that are marketed as 5V are in fact "anything from 2.8V to 5.5V" or something like that. *Read the datasheets!*

The NodeMCU is a tricky board to use with 5V because there is no isolation between the USB power and the 5V pin's power. You can't power the board through the 5V pin and still be able to use the USB port or you risk destroying the USB port or computer that the NodeMCU is plugged into.  If possible you really want to be running as many 3.3V devices as you can, or to keep any external 5V supplies completely separate (except ground, of course) from the 5V of the NodeMCU.


body: nodemcu gives 3.3 V output voltage. This output voltage is not considered sufficient by many components. So my recommendation is logic converters. The most logical solution to convert 3.3V voltage to 5V. Thus, the elements used with 5V will work stably.


message:
When connecting, client.connect() returns 0

I'm using an arduino UNO with ethernet shield. When following a few guides online for a school project I came across this issue. First code sample:
```c

    #include <SPI.h>
    #include <Ethernet.h>

    EthernetClient client;

    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(192, 168, 1, 25);
    byte server[] = { 64, 233, 187, 99 }; // Google

    void setup() {
      Ethernet.begin(mac, ip);
      Serial.begin(9600);
      delay(1000);
      Serial.println(Ethernet.localIP());
    }

    void loop() {
      if (client.connect(server, 80)) {
        Serial.println("connected");
        client.println("GET /search?q=arduino HTTP/1.0");
        client.println();
      } else {
        Serial.println("connection failed");
        Serial.println(client.connect(server, 80));
      }
    }
```

This doesn't work, unfortunately. We successfully connect to our network, but `client.connect()` doesn't work and returns 0. Expected result:

>SUCCESS: 1\
TIMED_OUT: -1\
INVALID_SERVER: -2\
TRUNCATED: -3\
INVALID_RESPONSE: -4

According to the documentation it shouldn't be able to return this. Why wouldn't this work? Thanks in advance.

body:
The documentation is wrong. The `connect` function only returns 1 on success and 0 on fail. All examples have `if (client.connect(host, port)) {` (0 is false, 1 is true).

Try the WebClient example provided in the IDE Examples menu for the Ethernet library. It has better diagnostics of Ethernet link.

You can try the WebServer example. It doesn't need Internet connection.

You can try ping the IP address of the Ethernet shield.

The shield should be connected to a router or switch and the gateway IP address should point to a device routing the network traffic to Internet.


message:
Ethernet shield connected to local network, not to internet

Using the WebServer example file I have been able to confirm that my arduino is connected to my local network and I can open the page in my browser. However any attempt at contacting addresses outside my own network fails. For example this simple script:

```c

    #include <SPI.h>
    #include <Ethernet.h>

    EthernetClient client;

    byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    IPAddress ip(192, 168, 1, 25);
    IPAddress gateway(192, 168, 1, 1);
    IPAddress dns(8, 8, 8, 8);
    byte server[] = { 64, 233, 187, 99 }; // Google

    void setup() {
      Ethernet.begin(mac, ip, dns, gateway);
      Serial.begin(9600);
      delay(1000);
      Serial.println(Ethernet.localIP());
    }

    void loop() {
      if (client.connect(server, 80)) {
        Serial.println("connected");
        client.println("GET /search?q=arduino HTTP/1.0");
        client.println();
      } else {
        Serial.println("connection failed");
      }
    }
```

This consistently returns `connection failed`. The ethernet cable in the arduino has an active internet connection, albeit via a switch. My board is an arduino uno.

body:
Find a server that doesn't automatically switch modes to https as google does.  If you put 64.233.187.99/search?q=arduino HTTP/1.0   in your browser you'll see that it switches to https.

If make the same request via the wget terminal app it fails.
```$ wget '64.233.187.99/search?q=arduino HTTP/1.0'
--2020-01-17 11:42:26--  http://64.233.187.99/search?q=arduino HTTP/1.0
Connecting to 64.233.187.99:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://www.google.com/search?q=arduino HTTP/1.0 [following]
--2020-01-17 11:42:26--  http://www.google.com/search?q=arduino HTTP/1.0
Resolving www.google.com... 172.217.4.132, 2607:f8b0:4007:80c::2004
Connecting to www.google.com|172.217.4.132|:80... connected.
HTTP request sent, awaiting response... 403 Forbidden
2020-01-17 11:42:28 ERROR 403: Forbidden.
```

There should also be an error returned to the client object which you can print out for debugging the conection.

Change your code to print out the return value of the client.connect call like so
```
void loop() {
      int result = client.connect(server, 80);
      if (x) {
        Serial.println("connected");
        client.println("GET /search?q=arduino HTTP/1.0");
        client.println();
      } else {
        Serial.println("connection failed");
        Serial.println(x);  // print out the error
      }
    }
```
One last thing, you set your dns server to 8.8.8.8 which should generally be set to your gateway / router of 192.168.1.1.


message:
Powering an rc car motor with arduino

I have a weird problem. When I power an rc car motor through the 5v or the 3.3V arduino's outputs everything goes fine, while powering it through digitalPins does not work.
I'm testing digitalPins with a simple led Blink example. Leds work, the motor does not move. Shouldn't digitalWrite(pinNumber, HIGH) output 5volts? What is the difference between digitalWrite voltage and 5v board output voltage? It seems crazy to me that leds light up without problems but the motor remains motionless...

body:
Never ever power a motor or anything, that needs that much power, through a digital output pin. The maximum rating is 40mA, though you should not draw more than 20mA continuously from it. Also there is an overall limit of 100mA over all digital pins together. If you are drawing more from the pins, first the voltage will drop immediately, since the pin cannot provide what you ask for. Then you can easily destroy the pins output hardware or the whole Arduino. For an LED you normally use a current limiting resistor, so that it does not draw too much current from the pin.

For anything with more current demands, you need some kind of driver, which will take the big current load of the microcontroller. The easiest driver is a transistor or MOSFET (to switch the motor on and off or to have different speeds). If you want the motor to spin in both directions, you need an H-bridge driver (effectively 4 transistors/MOSFETs).

Note: I'm talking about simple DC motors here. Other types of motors need other types of drivers.


message:
Does RFID-RC522 supoort tk4100 chip protocol ISO18000-2C 10 digital ID card?

I have ordered a starter kit and received RFID reader is

> RFID-RC522

module with one card and tag now I need more RFID card for my project and I can't find the supported card type for my project please can any one tell me supported card types and if this card supports my device this is the card type

> tk4100 chip protocol ISO18000-2C 10 digital ID number

body:
The MFRC522 on your kit is designed to communicate with ISO/IEC 14443 A/MIFARE and NTAG cards.

Search for `Mifare Classic` or `Mifare Ultralight` or `NTAG213`, `NTAG216` ... cards.


message:
SSD1306 recognized in I2C scaner, can't get it to display

The gist of my issue is in the title. I have a cheap ebay SSD1306 128x64 display which I hooked up to my arduino, and checked the wiring at least 50 times and the address is correct, the display has the jumper set to 0x78 and the arduino (Nano with ATmega168) sees it on an i2c scanner as 0x3C which is expected.

Now I installed Adafruit's SSD1306 and GFX libraries and an OLED i2c library I found somewhere (can't find it, sorry. In the IDE it's called OLED_I2C) and ran both example codes (shortened Adafruit's to fit on a 168) and I can't get it to show anything. I've tried many things including trying the 128x32 code with no luck, not even missing every other line. I think the display works since it shows up in the scanner, does anyone have any idea what could be wrong? Thanks in advance

My shortened Adafruit code:

    #include <SPI.h>
    #include <Wire.h>
    #include <Adafruit_GFX.h>
    #include <Adafruit_SSD1306.h>

    #define SCREEN_WIDTH 128 // OLED display width, in pixels
    #define SCREEN_HEIGHT 64 // OLED display height, in pixels

    // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
    #define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
    Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

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

      // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
      if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
        Serial.println(F("SSD1306 allocation failed"));
        for(;;); // Don't proceed, loop forever
      }

      // Show initial display buffer contents on the screen --
      // the library initializes this with an Adafruit splash screen.
      display.display();
      delay(2000); // Pause for 2 seconds

      // Clear the buffer
      display.clearDisplay();

      // Draw a single pixel in white
      display.drawPixel(10, 10, SSD1306_WHITE);

      // Show the display buffer on the screen. You MUST call display() after
      // drawing commands to make them visible on screen!
      display.display();
      delay(2000);
      // display.display() is NOT necessary after every single drawing command,
      // unless that's what you want...rather, you can batch up a bunch of
      // drawing operations and then update the screen all at once by calling
      // display.display(). These examples demonstrate both approaches...

      testdrawline();      // Draw many lines

      testdrawrect();      // Draw rectangles (outlines)
    }

    void loop() {
    }

    void testdrawline() {
      int16_t i;

      display.clearDisplay(); // Clear display buffer

      for(i=0; i<display.width(); i+=4) {
        display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
        display.display(); // Update screen with each newly-drawn line
        delay(1);
      }
      for(i=0; i<display.height(); i+=4) {
        display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
        display.display();
        delay(1);
      }
      delay(250);

      display.clearDisplay();

      for(i=0; i<display.width(); i+=4) {
        display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
        display.display();
        delay(1);
      }
      for(i=display.height()-1; i>=0; i-=4) {
        display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
        display.display();
        delay(1);
      }
      delay(250);

      display.clearDisplay();

      for(i=display.width()-1; i>=0; i-=4) {
        display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
        display.display();
        delay(1);
      }
      for(i=display.height()-1; i>=0; i-=4) {
        display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
        display.display();
        delay(1);
      }
      delay(250);

      display.clearDisplay();

      for(i=0; i<display.height(); i+=4) {
        display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
        display.display();
        delay(1);
      }
      for(i=0; i<display.width(); i+=4) {
        display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
        display.display();
        delay(1);
      }

      delay(2000); // Pause for 2 seconds
    }

    void testdrawrect(void) {
      display.clearDisplay();

      for(int16_t i=0; i<display.height()/2; i+=2) {
        display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
        display.display(); // Update screen with each newly-drawn rectangle
        delay(1);
      }

      delay(2000);
    }

body:
I have some experience with the the screen you are using and I hope these tips can solve your problem.

 - Changing the Address in the code

The OLED display you are using uses what is called I2c or IIC protocol which is the abbreviation of "Inter Intergrated Circuit", here is it's Wikipedia page to read about [it][1].

The IIC communication has 7 bit address space, that means there is 127 distinctive address for example 0x3C,0x3D,0x38 etc....

Your display might have either the address 0x3C or 0x3D so you might try changing theses values until anything would show up.

 - Unhooking any other IIC device

Although you can hook many IIC devices but as was said in the comments it's better to unhook everything except it, to troubleshoot.

 - Correct voltage ?

You might know that some displays uses 3.3v or some uses 5v, but as it showed in the IIC scanner, I don't think  that is the problem in your case but you should consider it.

 - Try using other sketches

Well, I think that 99% of the problem lays in your code (sometimes happens to me), so I suggest using other library examples or completely other libraries, or if you would like to take the challenge open the datasheet for the ssd1306 and make your own library and codes.

I hope these tips will help you or any other viewer.

As a side note I am a student, so I completely will appreciate anybody editing the answer to make better or more clear.

  [1]: https://en.wikipedia.org/wiki/I²C?wprov=sfla1


body:
I copied your code and load to my display. It doesn't show anything. Here is the code that I had run successfully.

    #include <Adafruit_SSD1306.h>
    Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

    void setup() {

      // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
      display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32

      display.display();
      delay(2000);

      display.clearDisplay();      //this line to clear previous logo
      display.setTextColor(WHITE); //without this no display
      display.print("Hello World!");//your TEXT here
      display.display();            //to shows or update your TEXT
    }

    void loop() {

     }

Good Luck,
Aung Myo Oo


body:
I tried researching a while after asking this question. Turns out changing OLED_RESET to -1 fixed it.

[![Photo][1]][1]

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


body:
The confusion about I2C address really comes from whether it's treated as a byte or 7-bit (MSB).

For example, on the OLED PCB, it's stated address I2C =  0x78, which is 0b_0111_1000 (I2C address write).

In the Adafruit Arduino SSD1306 library, it uses 7-bit I2C address, that 0x78 becomes 011_1100 (taking the 7-bit MSB) = 0x3C


message:
How to control segments with SevSeg library

The [SevSeg][1] library by Dean Reading seems to have a keyword to control individual segments on SSD's. I am using four common cathode, single digit displays. Does anyone know how to program individual segments?

    #include "SevSeg.h";

    SevSeg sevseg;

    void setup() {
      // put your setup code here, to run once:

      byte numDigits = 4;
      byte digitPins[] = {2, 3, 4, 5};
      byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
      bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
      byte hardwareConfig = COMMON_CATHODE; // See README.md for options
      bool updateWithDelays = false; // Default 'false' is Recommended
      bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
      bool disableDecPoint = false; // Use 'true' if your decimal point doesn't exist or isn't connected. Then, you only need to specify 7 segmentPins[]

      sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins,
        resistorsOnSegments,
        updateWithDelays, leadingZeros, disableDecPoint);

    }

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

      sevseg.setSegments();
      //sevseg.setNumber(1234,0);
      //sevseg.setChars("");
      //sevseg.blank();
      sevseg.refreshDisplay();

    }

  [1]: https://github.com/DeanIsMe/SevSeg

body:
You can't with that library. The author has not provided any public methods that will do the job.

There are private methods (`segmentOn` and `segmentOff`) that might be usable, but you would have to modify the library to be able to access them.


message:
Is there an alternative to strtok_r in extracting words from char?

The task, in char, I get some data that I have to parse into parts.

In this case, I use strtok_r, which finds identifiers like

> "=", " ", "&"

**Code:**

    char payload[70] = "GET /wifi?ssid=MyWiFi&pass=123456789 HTTP 11";
    char *p;
    char *i;

    void setup() {
      Serial.begin(15200);
      Serial.println("Load");

      p = strtok_r(payload, "=", &i);
      // Get SSID
      p = strtok_r(NULL, "&", &i);
      Serial.println(p);

      p = strtok_r(NULL, "=", &i);
      // Get PASS
      p = strtok_r(NULL, " ", &i);
      Serial.println(p);
    }

    void loop() {}

**Result:**

> Load MyWiFi 123456789

This works, but as soon as I add the characters strtok_r works on to the ssid = or pass = value, it stops working, outputting the cropped data.

These characters can be in the name of any WiFi network or the generated password.

Tell me, are there strtok_r analogues, where instead of a single character I can insert a whole phrase?

For example, so that he finds the beginning of ssid by the tag "ssid=", and finishes before "pass=".

**Resolved.**

Thank you all for your help!

I studied both options from @Majenko and @user7761803. All of them came in handy in various parts of the code.

Perhaps someone will use the Regexp library to parse such data. Here is example:

        #include <Regexp.h>

        char payload[60] = "ssid=MyWifi&pass=ukLPm&I*uwlm HTTP";
        char ssid[25], pass[25];

        void setup() {
          ms.Target(payload);
          char match_result = ms.Match("ssid=(.*)&pass=(.*) H", 0);
          if(match_result == 1) {
           // Get SSID
           ssid = ms.GetCapture(regexp_var.buffer, 0);
           // Get PASS
           pass = ms.GetCapture(regexp_var.buffer, 1);
          }
        }

        void loop() {}

body:
The normal way of parsing such complex strings in any language is to use *Regular Expressions*.

Normally these are pretty heavy-weight to use, but thankfully Nick Gammon has written [an Arduino implementation of regexp](https://github.com/nickgammon/Regexp).


body:
The function you are looking for is [`strstr()`](https://linux.die.net/man/3/strstr), which takes two strings, and returns a pointer to where the second string appears in the first (or `NULL` if it doesn't appear).

You could use it something like this:

```
void setup() {

    Serial.begin(15200);
    Serial.println("Load");

    char *p = strstr(payload, "ssid=");
    char *q = strstr(payload, "pass=");
    char *r = strstr(payload, " HTTP");

    char *ssid = NULL;
    char *pass = NULL;

    if (p == NULL || q == NULL || r == NULL) {
        // One or other (or both) missing - what to do?
    } else {
        *r = '\0'; // Terminate the last string

        // If this really is an HTTP query string, we don't know
        // if ssid or pass will be first
        if (p < q) { // Terminate the first string
            *(q - 1) = '\0';
        } else {
            *(p - 1) = '\0';
        }

        ssid = p + 5;
        pass = q + 5;

        Serial.println(ssid);
        Serial.println(pass);
    }
}
```

Note, however, that your `payload` string looks like an [HTTP query string](https://en.wikipedia.org/wiki/Query_string).

These are *defined* so that they are split at the `&` characters, and if a `&` needs to appear in one of the values, it should be *percent encoded* (where the `&` would appear as `&`, and would need to be decoded afterwards).

However, that wasn't your question...


message:
Arduino Obstacle Avoiding Shield controlor motor L293D

I am a beginner with Arduino. I wanted to make an Arduino obstacle avoiding. So I ordered last week an L293D Shield Motor Driver and I don't know if what I receive is a good item. The first picture is how it looks on the site and the second picture is what I got.

[![][1]][1]

[![][2]][2]

I saw that if you search for this motor you get results for both motors, but they are not the same. And I saw in this tutorial, this person using a motor like mine https://www.youtube.com/watch?v=ydDvoknlJ9M and then he switched to the motor in the first picture.

Questions: Are these motors the same? Should I request a return? If they are the same, how can I add the pins (as shown in the third picture?

[![][3]][3]

  [1]: https://i.stack.imgur.com/UWW0O.jpg
  [2]: https://i.stack.imgur.com/XfQ38.jpg
  [3]: https://i.stack.imgur.com/yTMUw.jpg

Again, I am a beginner and I would appreciate if someone can help me.

body:
To complete @chrisl answer: Yes you need these pins to make the same robot as in the video. You can order them online and solder them (if you know how to solder and if you have the soldering material). Be careful with soldering ;)

For your information, the pins you circled in red are used to communicate with the Arduino pins A0 to A5, and provide +5V and GND. In the video, they are connected to the ultrasound sensor.

And please clarify what is your `motor`??? Do you mean the `Shield motor driver`? It is not the same. A `shield` is an eletronic board that you plug to your Arduino to do a specific task (control a motor, connect to wifi...). A `motor driver` is the electronic to control the motor. On your pictures, they are mainly the 3 components with 16 legs each.


message:
Why is this RISING interrupt repeatedly triggering?

I've set up an ISR to trigger on the `RISING` edge of pin #2, but I find that if pin 2 is held high, the ISR triggers repeatedly.

Here's a trace of the voltage measured right at the pin:

[![Scope trace of voltage at pin 2][1]][1]

I can see a little bit of noise, but it shouldn't be enough to trigger multiple pulses. I've tried both `INPUT` and `INPUT_PULLUP` modes for the pin; behavior is the same.

```c++
constexpr byte kClockPin = 2;
constexpr byte kReadWritePin = 3;
constexpr byte kLedPin = 13;
constexpr int kNumAddressPins = 16;
constexpr byte kAddressPins[] = {/* MSB */52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22};
constexpr int kNumDataPins = 8;
constexpr byte kDataPins[] = {/* MSB */45, 43, 41, 39, 37, 35, 33, 31};

volatile bool dirty = false;
volatile uint8_t data = 0;
volatile uint16_t address = 0;
volatile bool read = false;

void setup() {
  // put your setup code here, to run once:
  pinMode(kClockPin, INPUT_PULLUP);
  pinMode(kReadWritePin, INPUT);
  for (byte pin : kAddressPins) {
    pinMode(pin, INPUT);
  }
  for (byte pin : kDataPins) {
    pinMode(pin, INPUT);
  }
  pinMode(kLedPin, OUTPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(kClockPin), OnClock, RISING);
}

void loop() {
  // digitalWrite(kLedPin, digitalRead(kClockPin));
  if (!dirty) return;
  char output[15];
  sprintf(output, "x %c x", address, read ? 'r' : 'w', data);
  Serial.println(output);
  dirty = false;
  // digitalWrite(kLedPin, digitalRead(kClockPin));
}

void OnClock() {
  read = digitalRead(kReadWritePin);
  data = 0;
  for (byte pin : kDataPins) {
    data = (data << 1) + (digitalRead(pin) ? 1 : 0);
  }
  address = 0;
  for (byte pin : kAddressPins) {
    address = (address << 1) + (digitalRead(pin) ? 1 : 0);
  }
  dirty = true;
}

```

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

body:
Turns out the short answer is that I'm still not great at using an oscilloscope.

Longer version is that the noise was *very* visible at smaller time scales. A filter capacitor had come disconnected from the breadboard in a way that was hard to see, and that was causing a whole bunch of noise. Replacing it fixed the problem.


message:
How to get char array's length

I use a LCD display to display a not known size of text ( changes over time ). I wish to display it at the center of LCD ( 2X16 ).

I declare:
<!-- language-all: lang-cpp -->

      char t[16];
      char h[16];
      sprintf(t, "%.1f� %.0f%%", temperature,223, humidity);

Now, since I want to add additional data on a specific line and center it, I need to know it size. When using:

    sizeof(t)/(sizeof(t[0])

I get `16` which is the size determined and not its actual size.

How can I get the exact number of chars **used**?

body:
The function I think you are looking for is `strlen` - STRing LENgth.

It counts the number of characters in a string up until it finds the "NULL" end of string marker.

    Serial.println(strlen(t));


message:
Weather API Arduino

#include <SPI.h>
    #include <Ethernet.h>

    // Enter a MAC address for your controller below.
    // Newer Ethernet shields have a MAC address printed on a sticker on the shield
    byte mac[] = {my mac };
    char serverName[] = "api.weather.gov";

    // Initialize the Ethernet client library
    // with the IP address and port of the server
    // that you want to connect to (port 80 is default for HTTP):
    EthernetClient client;

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

      // start the Ethernet connection:
      if (Ethernet.begin(mac) == 0) {
        Serial.println("Failed to configure Ethernet using DHCP");
        // no point in carrying on, so do nothing forevermore:
        while(true);
      }
      // give the Ethernet shield a second to initialize:
      delay(1000);
      Serial.println("connecting...");

      // if you get a connection, report back via serial:
      int ret = client.connect(serverName,443);
      if (ret==1) {
        Serial.println("connected");
        // Make a HTTP request:
        client.println("GET /stations/KGSO/observations/latest");
        client.println("accept: application/geo+json,*/*");
        client.println("user-agent: arduino, mymail@asdf.com");
        client.println("host: api.weather.gov");
        client.println();
      }
      else {
        // kf you didn't get a connection to the server:
        Serial.println("connection failed");
        Serial.println(ret);
        Serial.println(client.status());
      }
    }

    void loop()
    {
      // if there are incoming bytes available
      // from the server, read them and print them:

      if (client.available()) {
        Serial.print("\ngotsome\n");
        char c = client.read();
        Serial.print(c);
      }

      // if the server's disconnected, stop the client:
      if (!client.connected()) {
        Serial.println();
        Serial.println("disconnecting.");
        client.stop();

        // do nothing forevermore:
        while(true);
      }
    }

When I run this I get:

connecting...
connected

disconnecting.

Why don't I get data? I thought it was about the header info. But I looked at https://www.weather.gov/documentation/services-web-api#/ and it doesn't say it needs much.

body:
The Ethernet library doesn't support secure connection (so called SSL, but TLS now). To connect to a secure HTTP transport HTTPS the secure connection is necessary. The AVR MCU don't have the computing power to compute the security keys. And for less popular 32bit MCU nobody created a 'SSL' implementation for Ethernet library yet.

esp8266, esp32, MKR1010, Uno WiFi, Nano 33 IoT can do HTTPS, but all only over WiFi as far as I know.


message:
Get image from Fingerprint module

I want to get the image from the fingerprint module (https://makeradvisor.com/tools/fingerprint-sensor-module/) as a result of scanning. It is enough to have a single frame image. it would be good if the computer can get image the output image from the serial port (as in linescan camera example: https://www.youtube.com/watch?v=welv4w8B88g   https://www.tindie.com/products/ap_tech/tsl1401cl-linescan-camera/)

I am open to your suggestions if it can be done in another module.

body:
Since all of these cheap fingerprint readers are similar you can find a compatible datasheet and just find the commands and descriptions there. However, I couldn't find a datasheet that would include a good description of the protocol. So the other option is to look at the protocot through the software SFGDemo which is apparently capable of getting an image of a fingerprint. Or to use [this][1] python package which apparently also can download the image.

  [1]: https://pypi.org/project/fpscanner/


message:
How many PIR Motion Sensors can I connect to my Arduino-Uno R3?

I am doing a school project where I intend to measure the cafeteria line with motion sensors and the send that information with a WiFi module to a server. This is my first time using Arduino and I am not sure how many motion sensors does it support.

body:
Most PIR sensors provide a simple relay output. That means they are nothing more than a switch as far as the Arduino is concerned.

You can connect hundreds of switches to an Arduino. With judicious use of diodes and a matrix arrangement you can hundreds with not many IO pins.  For example an 8x8 matrix of switches gives you 64 PIR sensors with just 16 IO pins.  For *n* pins you can have *(n/2)²* switches with a balanced (*n/2* by *n/2*) matrix.


message:
GSM+GPS modules

Say, I need to track a vehicle using Arduino and a (GPS+GSM) module.  Though GPS can be used to get Location of the Vehicle(and then sent using GSM), why would we even do it using GPS if we already have a GSM module. Can't GSM do both these tasks(getting location and sending it) . What's the use of using an extra module there?

I am new to network stuff, help me!

body: The GSM module can estimate it's location based on cell tower triangulation but if you want a more accurate location then you need to use a GPS.


message:
Multiple serial monitors with the same arduino mega

I’ve got mega 2560.
In my project serial port is used for communicating with PC.
However, I’d like to see debug info in serial monitor. Mega has a few hardware Serial ports. How to use one of them got extra serial monitor?

body:
You need to connect one (or more) to your PC. To do that you would use a USB to TTL UART adaptor, like an FT232 board.

That will give you a new COM port that you can open with your terminal program of choice, though opening the Arduino "serial monitor" multiple times might be somewhat difficult.


body:
Use an USB to TTL Serial adapter. Wire it to one of the RX/TX pin pairs and in code use the corresponding Serial object Serial1, Serial2 or Serial3. Don't forget to wire Ground.

You can use some terminal program or Serial Monitor in Arduino IDE to communicate over the adapter. You can open a second instance of the Arduino IDE by starting it with the Desktop or menu shortcut. In this instance you can select a different port then the sketch upload port.

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

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


message:
Extra `eecfbba=.@aa` file in sd card

I am doing a project, and I need an SD card. Everything worked well, but after a while when I read the SD card from my PC(Windows 10 64 bit, Intel Core), I found a file called `eecfbba=.@aa`. It's so big that it almost ate up one GB storage of my SD card. But when I tried to open it with notepad, notepad tells me that there is actually no such file, and asks me if I want to create it. I tried to delete it, but file explorer also told me there is no such file. What is it?

This is my code:
```c
#include <ArduinoJson.h>

// Version 0.20.1.19.3.7:
// 2020/01/19, 16:10, button record test, 7th version.

#include <SD.h>
#include <SPI.h>
#include <TMRpcm.h>
#include <Wire.h>
#include "RTClib.h"
//#include <string.h>

RTC_DS1307 rtc;
String strdoc;
char daysOfTheWeek[7][2] = {"su", "mo", "tu", "we", "th", "fr", "sa"};
#define SD_ChipSelectPin 10  // 如果使用 arduino nano 328 可使用Pin4

TMRpcm audio;
void setup() {
  audio.speakerPin = 8;
  Serial.begin(9600);
  pinMode(25, INPUT_PULLUP);
  pinMode(7, INPUT_PULLUP);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  else
  {
    Serial.println("rtc started");
  }

  if (!SD.begin(SD_ChipSelectPin)) {
    Serial.println("SD Fail");
    return;
  } else {
    Serial.println("SD OK");
  }

  audio.setVolume(6);
  audio.CSPin = SD_ChipSelectPin;

  StaticJsonDocument<200> doc;
  doc["sensor"] = "gps";
  doc["time"] = 1351824120;
  JsonArray data = doc.createNestedArray("data");
  data.add(48.756080);
  data.add(2.302038);
  serializeJson(doc, strdoc);
}
bool isrecording = false;
bool recordButtonPressed()
{
  return (digitalRead(25) == LOW);
}
bool playButtonPressed()
{
  return (digitalRead(7) == LOW);
}
void loop() {
  delay(200);
  // Below is the formatted datetime.
  DateTime now = rtc.now();
  // Below is the serialized datetime.
  String filename = (String)(now.unixtime() % 10000000) + ".j";
  //  Serial.println(filename);
  if (recordButtonPressed())
    if (!isrecording)
    {
      isrecording = true;
      audio.startRecording("test.wav", 16000, A0);
      Serial.println("stt");
    }
    else
    {
      isrecording = false;
      Serial.println("stp");
      audio.stopRecording("test.wav");
    }
  Serial.println("sdsad991===`=`");
  if (playButtonPressed())
  {
    audio.play("test.wav");
    Serial.println("ply");
  }
  String dataString = strdoc;
  if (!isrecording)
  {
    File dataFile = SD.open(filename, FILE_WRITE);

    if (!dataFile) {
      Serial.println(F("Failed to create file"));
    }
    else
    {
      dataFile.println(dataString);
      Serial.println("Wrote string.");
      dataFile.close();
      Serial.println("Closed file.");
    }
  }
  /* Please ignore this line */
  //  //    audio.play("test.wav"); break;audio.volume(1); break;audio.volume(0); break;audio.stopPlayback(); break;
}
```

P.S. I'm using Mega 2560, so MISO, MOSI, SCK and CS pins are different.(Which is 50,51,52,10).

Edit 2020/1/25, 14:15(Beijing Time) At 1/20 I have bigger problems. There are more and more big files. All of them are the same situation. For details, take a look at this photo(ignore selected files): [Imgur](https://i.stack.imgur.com/mAV1x.jpg) or 咱们中国人上不去imgur，用这个：[File-up（直接下载）](https://www.file-up.org/kbg7y8frdjtl)

body:
Thanks to @Juraj, I fixed the problem. Deleted those files by manually formatting the SD card.

_**This is not really the answer, you can see the answer in [this comment](https://arduino.stackexchange.com/questions/71901/extra-eecfbba-aa-file-in-sd-card#comment157026_71901) under the question.**_


message:
SPI command versus data?

I have bough an LCD screen display TFT Touch Screen Board For Arduino UNO R3.

Aand the following commands are given to me for the initialization:

```
write_SPI_commond(0xFF);
write_SPI_commond(0xFF);
delay_nms(5);
write_SPI_commond(0xFF);
write_SPI_commond(0xFF);
write_SPI_commond(0xFF);
write_SPI_commond(0xFF);
delay_nms(10);

write_SPI_commond(0xB0);
write_SPI_data(0x00);

write_SPI_commond(0xB3);
write_SPI_data(0x02);
write_SPI_data(0x00);
write_SPI_data(0x00);
write_SPI_data(0x10);

write_SPI_commond(0xB4);
write_SPI_data(0x11);//0X10

write_SPI_commond(0xC0);
write_SPI_data(0x13);
write_SPI_data(0x3B);//
write_SPI_data(0x00);
write_SPI_data(0x00);
write_SPI_data(0x00);
write_SPI_data(0x01);
write_SPI_data(0x00);//NW
write_SPI_data(0x43);

write_SPI_commond(0xC1);
write_SPI_data(0x08);
write_SPI_data(0x15);//CLOCK
write_SPI_data(0x08);
write_SPI_data(0x08);

write_SPI_commond(0xC4);
write_SPI_data(0x15);
write_SPI_data(0x03);
write_SPI_data(0x03);
write_SPI_data(0x01);

write_SPI_commond(0xC6);
write_SPI_data(0x02);

write_SPI_commond(0xC8);
write_SPI_data(0x0c);
write_SPI_data(0x05);
write_SPI_data(0x0A);//0X12
write_SPI_data(0x6B);//0x7D
write_SPI_data(0x04);
write_SPI_data(0x06);//0x08
write_SPI_data(0x15);//0x0A
write_SPI_data(0x10);
write_SPI_data(0x00);
write_SPI_data(0x31);//0x23

write_SPI_data(0x10);
write_SPI_data(0x15);//0x0A
write_SPI_data(0x06);//0x08
write_SPI_data(0x64);//0x74
write_SPI_data(0x0D);//0x0B
write_SPI_data(0x0A);//0x12
write_SPI_data(0x05);//0x08
write_SPI_data(0x0C);//0x06
write_SPI_data(0x31);//0x23
write_SPI_data(0x00);

write_SPI_commond(0x35);
write_SPI_data(0x00);

//write_SPI_commond(0x36);
//write_SPI_data(0x00);

write_SPI_commond(0x0C);
write_SPI_data(0x66);

write_SPI_commond(0x3A);
write_SPI_data(0x66);

write_SPI_commond(0x44);
write_SPI_data(0x00);
write_SPI_data(0x01);

write_SPI_commond(0xD0);
write_SPI_data(0x07);
write_SPI_data(0x07);//VCI1
write_SPI_data(0x14);//VRH 0x1D
write_SPI_data(0xA2);//BT 0x06

write_SPI_commond(0xD1);
write_SPI_data(0x03);
write_SPI_data(0x5A);//VCM  0x5A
write_SPI_data(0x10);//VDV

write_SPI_commond(0xD2);
write_SPI_data(0x03);
write_SPI_data(0x04);//0x24
write_SPI_data(0x04);

write_SPI_commond(0x11);
delay_nms(150);

write_SPI_commond(0x2A);
write_SPI_data(0x00);
write_SPI_data(0x00);
write_SPI_data(0x01);
write_SPI_data(0x3F);//320

write_SPI_commond(0x2B);
write_SPI_data(0x00);
write_SPI_data(0x00);
write_SPI_data(0x01);
write_SPI_data(0xDF);//480

//write_SPI_commond(0xB4);
//write_SPI_data(0x00);
delay_nms(100);

write_SPI_commond(0x29);
delay_nms(30);

write_SPI_commond(0x2C);
```

These commands do not look like Arduino commands to me. I have placed them like this

```
#include <Arduino.h>
#include <SPI.h>

void setup()
{
    Serial.begin(9600);
    Serial.println("Test!");

    SPI.begin();

    write_SPI_commond(0xFF);
    write_SPI_commond(0xFF);
    delay_nms(5);
    write_SPI_commond(0xFF);
    write_SPI_commond(0xFF);
    write_SPI_commond(0xFF);
    write_SPI_commond(0xFF);
    delay_nms(10);

    write_SPI_commond(0xB0);
    write_SPI_data(0x00);

    write_SPI_commond(0xB3);
    write_SPI_data(0x02);
    write_SPI_data(0x00);
    write_SPI_data(0x00);
    write_SPI_data(0x10);

    write_SPI_commond(0xB4);
    write_SPI_data(0x11);//0X10

    write_SPI_commond(0xC0);
    write_SPI_data(0x13);
    write_SPI_data(0x3B);//
    write_SPI_data(0x00);
    write_SPI_data(0x00);
    write_SPI_data(0x00);
    write_SPI_data(0x01);
    write_SPI_data(0x00);//NW
    write_SPI_data(0x43);

    write_SPI_commond(0xC1);
    write_SPI_data(0x08);
    write_SPI_data(0x15);//CLOCK
    write_SPI_data(0x08);
    write_SPI_data(0x08);

    write_SPI_commond(0xC4);
    write_SPI_data(0x15);
    write_SPI_data(0x03);
    write_SPI_data(0x03);
    write_SPI_data(0x01);

    write_SPI_commond(0xC6);
    write_SPI_data(0x02);

    write_SPI_commond(0xC8);
    write_SPI_data(0x0c);
    write_SPI_data(0x05);
    write_SPI_data(0x0A);//0X12
    write_SPI_data(0x6B);//0x7D
    write_SPI_data(0x04);
    write_SPI_data(0x06);//0x08
    write_SPI_data(0x15);//0x0A
    write_SPI_data(0x10);
    write_SPI_data(0x00);
    write_SPI_data(0x31);//0x23

    write_SPI_data(0x10);
    write_SPI_data(0x15);//0x0A
    write_SPI_data(0x06);//0x08
    write_SPI_data(0x64);//0x74
    write_SPI_data(0x0D);//0x0B
    write_SPI_data(0x0A);//0x12
    write_SPI_data(0x05);//0x08
    write_SPI_data(0x0C);//0x06
    write_SPI_data(0x31);//0x23
    write_SPI_data(0x00);

    write_SPI_commond(0x35);
    write_SPI_data(0x00);

    //write_SPI_commond(0x36);
    //write_SPI_data(0x00);

    write_SPI_commond(0x0C);
    write_SPI_data(0x66);

    write_SPI_commond(0x3A);
    write_SPI_data(0x66);

    write_SPI_commond(0x44);
    write_SPI_data(0x00);
    write_SPI_data(0x01);

    write_SPI_commond(0xD0);
    write_SPI_data(0x07);
    write_SPI_data(0x07);//VCI1
    write_SPI_data(0x14);//VRH 0x1D
    write_SPI_data(0xA2);//BT 0x06

    write_SPI_commond(0xD1);
    write_SPI_data(0x03);
    write_SPI_data(0x5A);//VCM  0x5A
    write_SPI_data(0x10);//VDV

    write_SPI_commond(0xD2);
    write_SPI_data(0x03);
    write_SPI_data(0x04);//0x24
    write_SPI_data(0x04);

    write_SPI_commond(0x11);
    delay_nms(150);

    write_SPI_commond(0x2A);
    write_SPI_data(0x00);
    write_SPI_data(0x00);
    write_SPI_data(0x01);
    write_SPI_data(0x3F);//320

    write_SPI_commond(0x2B);
    write_SPI_data(0x00);
    write_SPI_data(0x00);
    write_SPI_data(0x01);
    write_SPI_data(0xDF);//480

    //write_SPI_commond(0xB4);
    //write_SPI_data(0x00);
    delay_nms(100);

    write_SPI_commond(0x29);
    delay_nms(30);

    write_SPI_commond(0x2C);
}

void loop(void)
{
    delay(1000);
}
```

and I get many errors like

```
error: ‘write_SPI_commond’ was not declared in this scope
```

Even fixing the typo to `write_SPI_command` does not work. I have no problem with using the default `SPI.transfer` of the Arduino library. But, I am wondering how to translate `write_SPI_commond` and `write_SPI_data` into a proper `SPI.transfer`?

body:
The “commands” provided by the vendor are not code meant to be copied
as-is. They are [pseudocode][]. If you need to know the real difference
between “write command” and “write data”, you have to look at the
datasheet of the interface chip.

See for example the [ILI9481][]. On pages 28–29 you can see a data
transfer mode compatible with SPI (type C interface, option 3). Here you
have to wire one digital output of the Arduino to the D/CX pin on the
interface chip. This pin is used to tell whether you are writing a
command (pin LOW) or data (pin HIGH).

[pseudocode]: https://en.wikipedia.org/wiki/Pseudocode
[ILI9481]: https://www.crystalfontz.com/controllers/Ilitek/ILI9481/144/


body:
To answer the question in the title "**SPI command versus data?**":

TLDR
----
Some SPI drivers will separate the data sent on the [COPI/PICO][1] lines into subsections to make it easier on the programmer.

SPI command versus data?
-----
I am currently working with the ESP32 myself and have come accross the more generic question of "**What is the difference between command and data when using SPI?**". After some reading around, I have come to the conclusion that certain SPI drivers will allow users to separate the generic data sent in SPI protocal into subsections such as ADDRESS, COMMAND, and ADDITIONAL_DATA. This is simply to make it easier for the programmer to understand what they are sending.

Not all applications will require the an ADDRESS, COMMAND, and ADDITIONAL_DATA. For example, some chips will have pre-programmed commands such as this [Inclinometer (SCA61T)][2] which then may or may not require ADDRESS and ADDITIONAL_DATA. But others, such as the [MAX7219][3] (which I am using), only require an ADDRESS and ADDITIONAL_DATA, no COMMAND.

Example
-----
Using the ESP32 SPI driver, I played around with setting the length of the command bits and address bits from 0 to some nonzero number as seen in the code snippet below.
```
spi_device_interface_config_t devcfg={
                .command_bits=4,           ///< Default amount of bits in command phase (0-16), used when ``SPI_TRANS_VARIABLE_CMD`` is not used, otherwise ignored.
                .address_bits=4            ///< Default amount of bits in address phase (0-64), used when ``SPI_TRANS_VARIABLE_ADDR`` is not used, otherwise ignored.
}
```
Then I specified the data to be sent in the command and address bits (along with the data to be sent in the tx buffer) as seen in the code below.

```
     char data[1]= {0x97};

            spi_transaction_t spi_trans={
                .cmd={0x05},          ///< Command data, of which the length is set in the ``command_bits`` of spi_device_interface_config_t.
                .addr={0x00},         ///< Address data, of which the length is set in the ``address_bits`` of spi_device_interface_config_t.
                .length=8,            ///< Total data length, in bits
                .rxlength=0,          ///< Total data length received, should be not greater than ``length`` in full-duplex mode (0 defaults this to the value of ``length``).
                .rx_buffer=data,      ///< Pointer to receive buffer, or NULL for no MISO phase. Written by 4 bytes-unit if DMA is used.
                .tx_buffer=data,      ///< Pointer to transmit buffer, or NULL for no MOSI phase

            };

```
where `spi_trans.cmd = {0x05}` with 4 bits length corresponds to a binary `0101`, `spi_trans.addr = {0x00}` with 4 bits length corresponds to a binary `0000`, and `spi_trans.tx_buffer = {0x97}` with 8 bits length corresponds to a binary `10010111`.

When using an o-scope to measure the chosen COPI and clock pins, we see the following waveform.

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

We realize the ordering of the data sent over the COPI pin is command, then address, and lastly tx data. This ordering may differ depending on which driver is used (I am using the [ESP32 SPI Master driver][4]).

  [1]: https://www.sparkfun.com/spi_signal_names?_ga=2.24794995.891517377.1639774114-1543916381.1637822354
  [2]: https://www.mouser.com/pdfdocs/tn15_spi_interface_specification.PDF
  [3]: https://www.mouser.com/datasheet/2/256/MAX7219_MAX7221-1513157.pdf
  [4]: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/spi_master.html
  [5]: https://i.stack.imgur.com/s2ALa.png


message:
How can I set a timer?

I would like to set a stopwatch timer that will determine how long an input is in a certain state before changing. I want to set it so that, depending on the output my code executes one of 2 switch cases. But my trouble comes in on setting a timer. Is there a function I could use? Or a method that somebody knows? The time that the input will be for each case is not fixed so I cannot use a delay.

body:
Even though you are not running an actual (complex) Operating System, you should adhere to common practices.  For an Arduino, you should, in many cases, avoid directly controlling the hardware so as to be compatible with as many existing libraries for your particular Arduino platform as possible.

Setting the timer directly (if you are using an official Arduino Uno which contains an Atmel328P processor the processor's timers are covered in section 14 of the [Atmel328P Specifications][1]) may cause unexpected results should you use a library which expects the timer to run without being altered.

Instead, consider using the [millis() function][2] built into the Arduino IDE.  The function returns the current number of milliseconds since the Arduino was powered up.  Record this value in your code.  Then, if you want to know if One Second has elapsed, get the new value of millis and subtract this saved value from it and see if it is greater than 1000.  When that is true, One Second has elapsed.

  [1]: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf
  [2]: https://www.arduino.cc/reference/en/language/functions/time/millis/


body:
<!-- language-all: lang-arduino -->

Use `micros()` ([reference page][1]) to obtain a microsecond timestamp, and `millis()` ([reference page][2]) to obtain a millisecond timestamp.

Full Disclosure: I link to a library I maintain in my answer below, and I mention a few products (no links) I created with various techniques presented here in order to act as representative examples of when one approach might be preferred over another.

# Example 1: simple linear (synchronous) software timing measurement, including low-resolution (`micros()`) and high-resolution (`timer2.get_count()`)

In the simplest sense, **let's measure how long it takes to set an output pin HIGH and then LOW again:**

    void setup()
    {
        Serial.begin(115200);
        // I'll just leave pin 9 as an input; but uncomment the line below to make it an output
        // pinMode(9, OUTPUT);
    }

    void loop()
    {
        // Measure and print how many microseconds it takes just to set an output pin HIGH and then
        // LOW again.
        uint32_t time_start_us = micros();    // <=== START TIMESTAMP
        digitalWrite(9, HIGH);
        digitalWrite(9, LOW);
        uint32_t time_end_us = micros();      // <=== END TIMESTAMP
        uint32_t time_elapsed_us = time_end_us - time_start_us;
        Serial.print("time_elapsed_us = ");
        Serial.println(time_elapsed_us);
        delay(100);
    }

The really cool [ShowInfo][3] Arduino speed profiling sketch shows that Arduino's `digitalWrite()` function takes about 5us each, so expect the code above to print ~10us. Let's see if that's correct. I ran this on an Arduino Nano and got this output:

    time_elapsed_us = 8
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 8
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 8
    time_elapsed_us = 12
    time_elapsed_us = 8
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 12
    time_elapsed_us = 8

That's weird. Why only `8` or `12` us? Why not `10`? Or `9`? Or something else? Well, it turns out the Arduino `micros()` function only has a resolution of 4us, so it will actually print out either `8` or `12` us since those are multiples of 4 us. To get better resolution you'd have to modify the hardware timer registers, as I've done in my `eRCaGuy_Timer2_Counter` library, which has 0.5us-resolution. Full Disclosure: I wrote and maintain this library. It is free and open source, but I have it on my personal website, which has ads, and I solicit donations for downloads. A fully-functional snippet is also available in code at the bottom of that web-page without downloading anything.

Here is how to do the above code with my library:

    #include <eRCaGuy_Timer2_Counter.h>

    // Convert timer2 clock counts, which are 0.5us each, to us.
    float counts_to_us(uint32_t time_counts)
    {
        float time_us = (float)time_counts/2.0;
        return time_us;
    }

    void setup()
    {
        Serial.begin(115200);
        // I'll just leave pin 9 as an input; but uncomment the line below to make it an output
        // pinMode(9, OUTPUT);

        // Configure Timer2. This MUST be done before the other Timer2_Counter functions work.
        // Note: since this messes up PWM outputs on pins 3 & 11, as well as interferes with the tone()
        // library (http: arduino.cc/en/reference/tone), you can always revert Timer2 back to normal by
        // calling `timer2.unsetup()`
        timer2.setup();
    }

    void loop()
    {
        // Measure and print how many microseconds it takes just to set an output pin HIGH and then
        // LOW again.
        uint32_t time_start_counts = timer2.get_count();    // <=== START TIMESTAMP
        digitalWrite(9, HIGH);
        digitalWrite(9, LOW);
        uint32_t time_end_counts = timer2.get_count();      // <=== END TIMESTAMP
        uint32_t time_elapsed_counts = time_end_counts - time_start_counts;
        float time_elapsed_us = counts_to_us(time_elapsed_counts);
        Serial.print("time_elapsed_us = ");
        Serial.println(time_elapsed_us);
        delay(100);
    }

Now look at the output. Here's the more accurate and precise results with my `eRCaGuy_Timer2_Counter` library. Much better! But why those spurious 14.50us values I have marked with `<===`? Why are they off by 4us? I will explain below.

    time_elapsed_us = 10.00
    time_elapsed_us = 10.50
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 14.50  <===
    time_elapsed_us = 10.50
    time_elapsed_us = 10.50
    time_elapsed_us = 10.50
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 14.50  <===
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 10.50
    time_elapsed_us = 10.50
    time_elapsed_us = 10.50
    time_elapsed_us = 10.50
    time_elapsed_us = 10.00

The tradeoff of doing what Im doing is that you will get a 4us jitter introduced more often. Every time the 8-bit timer2 counter overflows, an ISR (Interrupt Service Routine) is called. This counts overflows to keep track of the 32-bit software timer from an 8-bit hardware counter. Entering this ISR takes about 4us, which means that if you try to grab a timestamp but then the ISR is called, you have to wait 4+us to get that timestamp, so it is off by that much. One of the several Arduino experts I really look up to, Nick Gammon, mentions this here in his [Interrupts](http://www.gammon.com.au/forum/?id=11488) article where he says, "There is a tweaking figure of 4 µS...". So, this 8-bit counter counts at 1 tick per 0.5us, which means it rolls over every 256 ticks * 0.5us/tick = 128us. So, every 128us you will have at least a 4us delay error introduced if you try to call the `timer2.get_count()` exactly when the ISR is called. If you get really unlucky you may even get this effect twice and be off by as much as 8us. When using the standard `micros()` function, since it rolls over only every 256 ticks * 4us/tick = 1024us, you get this 4us error effect 8x less frequently. That's the tradeoff of getting better resolution: you also get more-frequent 4+us jitter.

And just for kicks, here's a really bad one. Notice the `20.50`us value--off by 10.50us!

    time_elapsed_us = 15.00 <===
    time_elapsed_us = 10.50
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 15.00 <===
    time_elapsed_us = 10.50
    time_elapsed_us = 10.00
    time_elapsed_us = 20.50 <======
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 10.50
    time_elapsed_us = 10.00
    time_elapsed_us = 10.50
    time_elapsed_us = 10.50
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00
    time_elapsed_us = 10.00

Using mode filters, median filters, or other filters, these spurious results can be removed, at, of course, the cost of reduced frequency response to the thing being measured (all this means really is it takes multiple measurements to know the true value, just as we need to see with our eyes multiple measurements above to deduce 10.0us seems to be the right answer).

# Example 2: non-blocking (asynchronous) timing measurement of external event

**More-complicated Example: measure how long INPUT pin 9 is HIGH, and print out the HIGH time out each time it goes LOW again.**

In general, use this approach for any and all input events you need to measure at the 100us to ~200us resolution or larger level. You can use this on every single pin at once and get good results with resolutions around that level, depending really just on how long your main loop takes to run each iteration.

    constexpr uint8_t PIN = 9;

    void setup()
    {
        Serial.begin(115200);
        pinMode(PIN, INPUT);
    }

    void loop()
    {
        // This will measure how long `SOME_PIN` is HIGH, in microseconds.

        static uint32_t time_start_us = micros();
        bool time_just_acquired = false; // true if a new time value was just measured
        uint32_t time_elapsed_us = 0;

        bool pin_state = digitalRead(PIN);
        static bool pin_state_old = LOW;

        if (pin_state == HIGH && pin_state_old == LOW)
        {
            // The pin just barely went HIGH, so "start the timer" by obtaining a timestamp of the
            // start time
            time_start_us = micros();
            pin_state_old = pin_state; // update
        }
        else if (pin_state == LOW && pin_state_old == HIGH)
        {
            // The pin just barely went LOW, so "stop the timer" by obtaining a timestamp of the
            // end time
            uint32_t time_end_us = micros();
            pin_state_old = pin_state; // update
            time_elapsed_us = time_end_us - time_start_us;
            time_just_acquired = true;
        }

        // In some other place later down the code where you need this value,
        // you can use it like this. Here I just print the value.
        if (time_just_acquired)
        {
            time_just_acquired = false; // reset
            Serial.print("time_elapsed_us = ");
            Serial.println(time_elapsed_us);
        }
    }

_IMPORTANT: notice in all my examples above I use ONLY UNSIGNED INTEGER variables for timestamps. This is ESSENTIAL. Using **signed** integers for timestamps in the same way I've written them here would be a violation of the C standard because it will produce undefined behavior when you do subtraction which results in underflow, or when the integer has overflow. Using unsigned integers, however, is perfectly valid. Ex: `(uint8_t)0 - (uint8_t)1` = `255`, because it is an unsigned 8-bit integer which safely underflows from its lowest value back around to its highest value. Similarly, `(uint8_t)255 + (uint8_t)1` = `0` because it is an unsigned 8-bit integer which safely overflows from its highest value back around to its lowest value. This is how `time_elapsed_us = time_end_us - time_start_us` works in both of my examples as well. As the 32-bit microsecond counter overflows, which it will every 70 minutes or so, it wraps around back to 0. This means that sometimes `time_end_us` will be SMALLER than `time_start_us`, and you could end up with a measurement like this: `time_elapsed_us = 124 - 4294967295`, which equals `125`._

# Example 3: use external interrupts to detect changes on pins to measure external events

Use this approach when you need to measure external events at the 4~10us or larger resolution level on 2 pins maximum at a time.

This is a really good approach for measuring external events, but you get only 2 pins per Arduino Uno or Nano or similar that can do it. They are pins 2 or 3. See the table here: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/.

For a demo, see [Edgar Bonet's answer here](https://arduino.stackexchange.com/a/76992/7727).

# Example 4: use pin change interrupts to measure external events

Use this approach when you need to measure external events at the 4~10us or larger resolution level on > 2 pins maximum at a time.

These are like external interrupts except you have to manage up to 8 pins in a single interrupt service routine (ISR), instead of only 1 pin per ISR, so they aren't quite as good as "external interrupts". _Every single digital-capable pin on an Arduino Uno or Nano can do this._ I use this approach when reading many PWM signals from a radio control receiver, for instance, but it requires some sophistication and a ring buffer to do it right, as the time in the ISR *must* be minimized or else you get tons of jitter all over the place! That means you just grab the timestamp in the ISR, store it in a ring buffer, and exit. You do NOTHING ELSE! No subtraction, no math, no determining which pin fired, _nothing!_ You then process the ring buffer of timestamps and pin states in your main loop to determine which pin changed and do the math to obtain a new time reading on that pin. I used this for passing signals through a fire-shooting battlebots hexacopter that flew on ABC TV. It worked well. It made me happy to see the ISR do its job.

# Example 5: use input capture (on pin 8 *only*) to measure an external event

This is the "golden", or "best" approach. But, you get 1 pin per Arduino Uno or Nano that can do it. Use this approach when you need to measure external events at the 62.5 _nanosecond_ or larger resolution level **jitter-free**. There will be NO ISR TIMESTAMP DELAY WHATSOEVER with this approach, which is really cool.

Input Capture is only available on 16-bit timers on the 8-bit AVR microcontrollers such as the ATmega328. Since an Uno or Nano only has 1 16-bit timer, this means they get 1 single input capture pin. It is pin 8. Don't waste this pin for anything else if you need perfect time measurements of external events using input capture. Input capture is the "perfect" way to measure external events since it stores the time count in a hardware register at the moment the event happens, without CPU interaction through an ISR, which, as we know, would cause a delay and 4+us jitter.

I first did this on a commercial product I made which needed to read a single Radio Control receiver PWM pin. It made me happy to see it work right, as it has zero jitter. I'll come back and add a demo (code only, no more mention of the product) if I get a chance. This technique is also *perfect* for reading PPM (Pulse Position Modulation) signals, which are just a bunch of multiplexed Radio Control PWM signals.

  [1]: https://www.arduino.cc/reference/en/language/functions/time/micros/
  [2]: https://www.arduino.cc/reference/en/language/functions/time/millis/
  [3]: https://playground.arduino.cc/Main/ShowInfo/
  [4]: https://www.electricrcaircraftguy.com/2014/02/Timer2Counter-more-precise-Arduino-micros-function.html


body:
Your title is about “setting a timer”, but your actual question is about
measuring the length of a pulse. There are two functions provided by the
Arduino IDE for this purpose, `pulseIn()` and `pulseInLong()`:

* [`pulseIn()`][pulseIn] is based on a carefully timed delay loop. It
  has a resolution of the order of one microsecond, but will not count
  the time spent servicing interrupt requests. It works best for very
  short pulses timed with interrupts turned off.
* [`pulseInLong()`][pulseInLong] is based on `micros()`. It has a
  resolution of 4 µs and will _not_ work properly if interrupts are
  turned off. It works best for longer pulses where its limited
  resolution and interrupt latency are tolerable.

Both of these are _blocking_ functions: they completely block your
sketch while they perform the measurement. If you don't want your sketch
to be unresponsive during this time, you can write a non-blocking
version of `pulseInLong()` using a [finite-state machine][FSM] like
this:

```cpp
// Measure the length of a pulse in a non-blocking manner.
// Returns 0 if no measurement is available at the time of the call.
void get_pulse_length() {
    static enum {
        INITIAL_WAIT,    // wait for the first (partial) pulse to end
        BETWEEN_PULSES,  // wait for the pulse to start
        WITHIN_PULSE     // wait for the pulse to end
    } pulse_state = INITIAL_WAIT;
    static uint32_t pulse_start;  // when the current pulse started

    uint8_t pin_state = digitalRead(pulse_pin);
    uint32_t now = micros();
    switch (pulse_state) {
        case INITIAL_WAIT:
            if (pin_state == LOW)
                pulse_state = BETWEEN_PULSES;
            break;
        case BETWEEN_PULSES:
            if (pin_state == HIGH) {
                pulse_start = now;
                pulse_state = WITHIN_PULSE;
            }
            break;
        case WITHIN_PULSE:
            if (pin_state == LOW) {
                pulse_state = BETWEEN_PULSES;
                return now - pulse_start;
            }
            break;
    }
    return 0;
}
```

Note that this measures high pulses. You will have to swap `HIGH` and
`LOW` if you want to measure low pulses. You would use it like this:

```cpp
void loop() {
    uint32_t pulse_length = get_pulse_length();
    if (pulse_length) {
        // handle the pulse
    }
}
```

The resolution of the measurement is the execution time of `loop()`, so
you have to make sure there is nothing blocking there, and specially no
calls to `delay()`. If you need a better resolution from a non-blocking
method, you can use interrupts to trigger the measuring process:

```cpp
volatile uint32_t pulse_start, pulse_length;
volatile bool pulse_valid;

void on_rise() {
    pulse_start = micros();
    attachInterrupt(digitalPinToInterrupt(pin), on_fall, FALLING);
}

void on_fall() {
    pulse_length = micros() - pulse_start;
    pulse_valid = true;
    attachInterrupt(digitalPinToInterrupt(pin), on_rise, RISING);
}

uint32_t get_pulse_length()
{
    if (!pulse_valid) return 0;
    noInterrupts();
    uint32_t pulse_length_copy = pulse_length;
    pulse_valid = false;
    interrupts();
    return pulse_length_copy;
}

void setup() {
    attachInterrupt(digitalPinToInterrupt(pin), on_rise, RISING);
}
```

This should give you the resolution of `micros()`, i.e. 4 µs, but
occasionally you may get results that are slightly off if interrupts
happen to be disabled when the input transitions. If this is
unacceptable, the only other options I see is to use a hardware timer
with _input capture_ capability. You will have to look at the datasheet
of your microcontroller to see how it works, and maybe do a Web search
for “Arduino input capture”.

[pulseIn]: https://www.arduino.cc/reference/en/language/functions/advanced-io/pulsein/
[pulseInLong]: https://www.arduino.cc/reference/en/language/functions/advanced-io/pulseinlong/
[FSM]: https://majenko.co.uk/blog/finite-state-machine


message:
Can you make Arduino Uno send information through a WiFi module to a server?

A lot of tutorials are about how to control Arduino through WiFi, but I need my Arduino to send information about motion sensor activity to a server. Is that possible?

body:
> Can you make Arduino Uno send information through a WiFi module to a server?

Yes, I can.

The simplest way is through an HTTP "GET" request. Every time you request a web page (and there are plenty of examples of that) you are sending data to the server to tell it both what web page to get (`/foo/bar.php`) and what data to submit to that web page (`?baz=4`).

It's then up to you to craft that GET request, such as:

    GET /foo/bar.php?baz=4 HTTP/1.1
    Host: example.com
    Content-length: 0

and write the PHP web page (or whatever language you prefer to write web pages in) to do something meaningful with the "baz = 4" parameter.


message:
Latest news about alternative Arduino IDEs

I simply hate the default Arduino "IDE".
On Windows I use Visual Studio Code with the related plugin.

Now I have a Ubuntu machine and I'm looking for the definitive IDE.
Questions:

1. I'm not sure whether to use VSC I need to install the default IDE as well
2. is there something better?

By the way, I also have QtCreator, PHPStorm, MPLAB X, STM32Cube (Eclipse based).

body:
I use the Arduino IDE to 'build' everything.

However, in case of a bigger project, I use a 'decent' code editor (Visual Studio in my case) to edit, and the Arduino IDE to build.

Also, because I prefer testing all non-Arduino related code on the PC (not on the Arduino), the Visual Studio (C++) project uses some stub classes I created (specifically for my project), and I can run the application on my PC.

When some part is finished, I can build the same code in Arduino IDE, but without the stubs (because these are acquired from Arduino.h and related Arduino files).

What IDE is best to 'edit' code is very subjective I think. But in the above way I can see many classes/files at a glance on the left side (and not in the top like Arduino IDE where only like 5 tabs fit on a screen), and to test lots of code on the PC already before sending it to an Arduino.

The GitHub repository can be found here: https://github.com/michelkeijzers/Mestra

Project inside is DmxLightShow.


body:
Arduino creators toughed of you.
Personally I use Geany, but you can use eclipse, but I find the Arduino plugin rather hostile, especially when it comes to editing default libraries (to add printf) and pointlessly complex serial monitor settings default above the NANO's range.
Although its missing testing feature without upload

Although most other editors would be quite happy with arduinos file too, but  you have to always create new project with native IDE.
You will find use external editor feature in Arduino-ide's settings in which case every time file is saved it gets immediately updated in Arduino's IDE, so you can use it for your tasting as a sub-window.


message:
Setting Time Function With DS3232 Library

I am trying to set the time on my DS3231, then read that time on my arduino nano. This is for a digital clock project. I am using DS3232 library by JChristensen.

He has an example that can set the DS3231 time through the serial monitor, and it works great, but I don't understand how to implement it into my sketch.

I can confirm that once the external RTC is set using said example, I can then upload my code, and the clock holds time when unplugged. It's setting the time within my sketch that I can't figure out. I've been at it for about 8 hours today and read through the github resources.

Here's my code. Towards the top you can see my attempt to set the system time, then set it to the RTC.

     #include "SevSeg.h";
        #include <DS3232RTC.h>; //Jack Christensen
        https://github.com/JChristensen/DS3232RTC
        #include <Streaming.h>; //Mikal Hart https://github.com/janelia-
         arduino/Streaming
        //Also requires time library https://github.com/PaulStoffregen/Time

        SevSeg sevseg;

        void setup() {
        // put your setup code here, to run once:

        //Serial.begin(9600);

        setSyncProvider(RTC.get);// the function to get the time from the RTC
        setTime(8,0,0,20,1,2020);
        time_t t = now();
        RTC.set(now());

         byte numDigits = 4;
         byte digitPins[] = {2, 3, 4, 5};
         byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12};
         bool resistorsOnSegments = false; // 'false' means resistors are on digit
         pins
         byte hardwareConfig = COMMON_CATHODE; // See README.md for options
         bool updateWithDelays = false; // Default 'false' is Recommended
         bool leadingZeros = false; // Use 'true' if you'd like to keep the leading
         zeros
         bool disableDecPoint = true; // Use 'true' if your decimal point doesn't
         exist or isn't connected. Then, you only need to specify 7 segmentPins[]

         sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins,
          resistorsOnSegments,
           updateWithDelays, leadingZeros, disableDecPoint);

        }

         void loop() {

        sevseg.setChars("hola");
        sevseg.refreshDisplay();

         if(millis()>6000) {

        int adj = 0;
        int timenumber;
        int hr = hourFormat12();
        int Min = minute();

        timenumber = (hr*100) + Min; //converts time into a number for the seven
        segment display

       sevseg.setNumber(timenumber);
       sevseg.refreshDisplay();
        }

        }

  And JChristensen's Example Code:

    // Arduino DS3232RTC Library
    // https://github.com/JChristensen/DS3232RTC
    // Copyright (C) 2018 by Jack Christensen and licensed under
    // GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
    //
    // Example sketch to display the date and time from a DS3231
    // or DS3232 RTC every second. Display the temperature once per
    // minute. (The DS3231 does a temperature conversion once every
    // 64 seconds. This is also the default for the DS3232.)
    //
    // Set the date and time by entering the following on the Arduino
    // serial monitor:
    //  year,month,day,hour,minute,second,
    //
    // Where
    //  year can be two or four digits,
    //  month is 1-12,
    //  day is 1-31,
    //  hour is 0-23, and
    //  minute and second are 0-59.
    //
    // Entering the final comma delimiter (after "second") will avoid a
    // one-second timeout and will allow the RTC to be set more accurately.
    //
    // No validity checking is done, invalid values or incomplete syntax
    // in the input will result in an incorrect RTC setting.
    //
    // Jack Christensen 08Aug2013

    #include <DS3232RTC.h>      // https://github.com/JChristensen/DS3232RTC
    #include <Streaming.h>      // http://arduiniana.org/libraries/streaming/

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

        // setSyncProvider() causes the Time library to synchronize with the
        // external RTC by calling RTC.get() every five minutes by default.
        setSyncProvider(RTC.get);
        Serial << F("RTC Sync");
        if (timeStatus() != timeSet) Serial << F(" FAIL!");
        Serial << endl;
    }

    void loop()
    {
        static time_t tLast;
        time_t t;
        tmElements_t tm;

        // check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
        if (Serial.available() >= 12) {
            // note that the tmElements_t Year member is an offset from 1970,
            // but the RTC wants the last two digits of the calendar year.
            // use the convenience macros from the Time Library to do the conversions.
            int y = Serial.parseInt();
            if (y >= 100 && y < 1000)
                Serial << F("Error: Year must be two digits or four digits!") << endl;
            else {
                if (y >= 1000)
                    tm.Year = CalendarYrToTm(y);
                else    // (y < 100)
                    tm.Year = y2kYearToTm(y);
                tm.Month = Serial.parseInt();
                tm.Day = Serial.parseInt();
                tm.Hour = Serial.parseInt();
                tm.Minute = Serial.parseInt();
                tm.Second = Serial.parseInt();
                t = makeTime(tm);
                RTC.set(t);        // use the time_t value to ensure correct weekday is set
                setTime(t);
                Serial << F("RTC set to: ");
                printDateTime(t);
                Serial << endl;
                // dump any extraneous input
                while (Serial.available() > 0) Serial.read();
            }
        }

        t = now();
        if (t != tLast) {
            tLast = t;
            printDateTime(t);
            if (second(t) == 0) {
                float c = RTC.temperature() / 4.;
                float f = c * 9. / 5. + 32.;
                Serial << F("  ") << c << F(" C  ") << f << F(" F");
            }
            Serial << endl;
        }
    }

    // print date and time to Serial
    void printDateTime(time_t t)
    {
        printDate(t);
        Serial << ' ';
        printTime(t);
    }

    // print time to Serial
    void printTime(time_t t)
    {
        printI00(hour(t), ':');
        printI00(minute(t), ':');
        printI00(second(t), ' ');
    }

    // print date to Serial
    void printDate(time_t t)
    {
        printI00(day(t), 0);
        Serial << monthShortStr(month(t)) << _DEC(year(t));
    }

    // Print an integer in "00" format (with leading zero),
    // followed by a delimiter character to Serial.
    // Input value assumed to be between 0 and 99.
    void printI00(int val, char delim)
    {
        if (val < 10) Serial << '0';
        Serial << _DEC(val);
        if (delim > 0) Serial << delim;
        return;
    }

body:
I figured it out. You must first set the built in arduino RTC using the time library, then set the DS3232 from there. It did not work for my code before because it has to be called *outside* of the setup function.

For instance, I made a function that adjusts the hour:

    void adjHr() { //hour adjustment function

    if(millis() >= time_now + period){
            time_now += period;
            time_now = millis();
            setTime(hour()+1,minute(),second(),day(),month(),year());
            RTC.set(now());
        }

My setup function also includes:

    setSyncProvider(RTC.get);

Allows the code to get time from the DS3232.


message:
How to add another condition in the loop?

I am using mpu6050 for counting the twitch movement. The algorithm is counting the peak/twitch whenever it goes above the threshold value. Now, I want to add that the algorithm count twitch only when it goes above threshold value and all the twitch within 90s are counted as one twitch movement. Kindly help me with this. Also try to integrate this in my code.

**Here is the code:**

    #include "I2Cdev.h"
    #include "MPU6050.h"

    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        #include "Wire.h"
    #endif

    MPU6050 accelgyro;

    int16_t ax, ay, az;
    float threshhold=5000.0;
    float conmove=4;
    const int sampletime=90000;

    float xval[100]={0};
    float yval[100]={0};
    float zval[100]={0};
    float xavg;
    float yavg;
    float zavg;

    int twitch,flag=0;
    MPU6050 mpu6050;

    int16_t tr;          // raw temperature data register value
    char buffer[7];      // temporary string buffer; used with dtostrf() function
    #define OUTPUT_READABLE_ACCELGYRO

    #define LED_PIN 13
    bool blinkState = false;

    void setup() {

        // join I2C bus (I2Cdev library doesn't do this automatically)
        #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
            Wire.begin();
        #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
            Fastwire::setup(400, true);
        #endif

        Serial.begin(115200);

        // initialize device
        Serial.println("Initializing I2C devices...");
        accelgyro.initialize();
        mpu6050.initialize();  // initialize MPU6050 sensor module

        // verify connection
        Serial.println("Testing device connections...");
        Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");

        pinMode(LED_PIN, OUTPUT);
        calibrate();
        delay(5000);
    }

    void loop() {

        accelgyro.getAcceleration(&ax, &ay, &az);
        tr = mpu6050.getTemperature();

        #ifdef OUTPUT_READABLE_ACCELGYRO
        +
            // display tab-separated accel/gyro x/y/z values
            Serial.print("a/g:\t");
            Serial.print(ax); Serial.print("\t");
            Serial.print(ay); Serial.print("\t");
            Serial.print(az);
        #endif

        #ifdef OUTPUT_BINARY_ACCELGYRO
            Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
            Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
            Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
        #endif

        // blink LED to indicate activity
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
        int acc=0;
        float totvect[100]={0};
        float totave[100]={0};
        float xaccl[100]={0};
        float yaccl[100]={0};
        float zaccl[100]={0};

        for (int i=0;i<100;i++)
        {
            xaccl[i]=float(ax);
            delay(1);
            yaccl[i]=float(ay);
            delay(1);

            zaccl[i]=float(az);
            delay(1);

            totvect[i] = sqrt(((xaccl[i]-xavg)* (xaccl[i]-xavg))+ ((yaccl[i] - yavg)*(yaccl[i] - yavg)) + ((zval[i] - zavg)*(zval[i] - zavg)));
            totave[i] = (totvect[i] + totvect[i-1]) / 2 ;
            //acc=acc+totave[i];
            Serial.println(totave[i]);
            Serial.print("T = ");  Serial.print(dtostrf(tr/340.0+36.53, 5, 1, buffer));  Serial.println(" °C");

            // delay(200);

            //cal twitch
            if (totave[i]>threshhold && flag==0)
            {
                twitch=twitch+1;
                flag=1;
            }
            else if (totave[i] > threshhold && flag==1 )
            {
                //do nothing
            }
            if (totave[i] <threshhold  && flag==1 )
            {flag=0;}

            Serial.println('\n');
            Serial.print("twitch=");
            Serial.println(twitch);
        }

        //float tim=acc/100;
        //Serial.println(tim);
        delay(1000);
        // stepcal(totave);
    }

    void calibrate()
    {
        digitalWrite(13,HIGH);
        accelgyro.getAcceleration(&ax, &ay, &az);

        float sum=0;
        float sum1=0;
        float sum2=0;

        for (int i=0;i<100;i++)
        {
            xval[i]=float(ax);

            sum=xval[i]+sum;
        }
        delay(100);
        xavg=sum/100.0;

        Serial.println(xavg);

        for (int j=0;j<100;j++)
        {
            yval[j]=float(ay);

            sum1=yval[j]+sum1;
        }
        yavg=sum1/100.0;

        Serial.println(yavg);
        delay(100);
        for (int i=0;i<100;i++)
        {
            zval[i]=float(az);

            sum2=zval[i]+sum2;
        }
        zavg=sum2/100.0;
        delay(100);
        Serial.println(zavg);

        digitalWrite(13,LOW);
    }

body:
You can do this with the `millis()` function. It returns the number of milliseconds since startup and can be used as a simple clock. Take the if statement, where you increment `twitch`:

    if (totave[i]>threshhold && flag==0)
    {
      if(millis()-last_twitch_timestamp > 90000){
        twitch=twitch+1;
        flag=1;
        last_twitch_timestamp = millis();
      }
    }

This will check, if at least 90 seconds (90000ms) have passed since the last registered twitch (time difference between the current time and the timestamp of the last twitch). If yes, it will register another twitch and reset the timestamp to the current time (return value of `millis()`). This deactivates twitch registering for 90s after each twitch.

For this to work, you need to define the `last_twitch_timestamp` variable at global scope:

    unsigned long last_twitch_timestamp = 90000;

I initialize the timestamp to 90000, so that the very first twitch can be registered. If you initialize it to zero, you would need to wait 90s, until the first twitch can be registered.

---

Btw: The following delays don't make any sense. You can remove them:

    xaccl[i]=float(ax);
    delay(1);
    yaccl[i]=float(ay);
    delay(1);

    zaccl[i]=float(az);
    delay(1);

And you should really really keep all lines indented correctly. The Arduino IDE has an autoformat feature to make it simpler for you.


message:
Set slide potentiometer values

I am using the Grove - Slide Potentiometer (http://wiki.seeedstudio.com/Grove-Slide_Potentiometer). How can I set the potValue so that at maximum it will 128?

    int potPin= A0;
    int readValue;
    int potValue;

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

    void loop() {
     readValue = analogRead(potPin);
     potValue = (255./500.) * readValue;
     Serial.print("You are writing a value of ");
     Serial.println(potValue);
    }

body:
You can use the `map` function, see https://www.arduino.cc/reference/en/language/functions/math/map/.

Example: If your pot meter gives values from 100 to 1000 and you want to map that range to a range of 0 to 128 you can easily write:

    potValue = map(readValue, 100, 1000, 0, 128);

High likely, in your case and if the potentiometer is 'perfect' it returns values from 0 to 1023 and you can write:

    potValue = map(readValue, 0, 1023, 0, 128);


body:
analogRead() returns 0x0000 to 0x03ff

If the max data 0x03ff is shifted to the right by 3 bits (or divide by 8),
then 0x03ff becomes 0x007f, or 127.

I think this will do it:

    desiredMax = analogRead(A0) >> 3; // divide 1023 max by 8, becomes 127 max


message:
Daisy chaining of multiple blocs of 4x(8x8) MAX7219 matrix

Thanks for your presentation https://arduino.stackexchange.com/tags/max7219/info.
You say that multiple MAX7219 8x8 blocs can easily be daisy-chained and you show an example of at least 12 blocs displaying "Testing12345".
Trying several programs I found for Arduino, I never succeeded to chain more than 8 blocs with 8x8 matrix (either 8 individual blocs or 2 groups of 4 as on your image).
So I'ld be very happy if you send me examples of programs managing more than 8 blocs for fixed or scrolling displays.
Many thanks in advance.

body: Try using @Majenko 's MAX libary https://github.com/MajicDesigns/MD_MAX72XX .  It allows you to specify how many modules are to be addressed.


body:
All is OK changing the proposed statement
# define HARDWARE_TYPE MD_MAX72XX::PAROLA_HW
to
# define HARDWARE_TYPE MD_MAX72XX::FC16_HW


message:
Need my code to do multiple commands when inputs are pressed

Hello all I am back again with another issue concerning a code for my job. The code I have been working on is meant to connect to a IP server where some options are listed and I can control the servo motor through there. The options listed are FORWARD, BACKWARD, STEP, and STOP. Each command makes the servo motor move a certain way but the problem I need help with is I need the edited the code to work with three input switches which when pressed in real time they allow the motor to make turns without the need of pressing any button on the server and so far the code is not working. They work with some LED lights which when the input switches are pressed also light up each input is paired with an output (LED) respectively and I tried to create a marker that when the input is pressed also says on the server that "LED1 is on" for example. Each input corresponds to an INPUT switch and each output corresponds to an LED light. The Pin variable corresponds to the motor. Here is the code in question:

```
#include <ESP8266WiFi.h>
#include <Servo.h>

const char* ssid = "RETProject";
const char* password = "mporfiri";

WiFiServer server(80);

int Pin = 16; // GPIO13
int var = 0;
int D1 = 5;
int D2 = 4;
int D4 = 2;
int D5 = 14;
int D6 = 12;
int D7 = 13;
int temp1 = 0;
int temp2 = 0;
int temp3 = 0;

Servo servoMotor;

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

  pinMode(D1, INPUT);
  pinMode(D2, OUTPUT);
  pinMode(D4, INPUT);
  pinMode(D5, OUTPUT);
  pinMode(D6, INPUT);
  pinMode(D7, OUTPUT);
  pinMode(Pin,INPUT);
  //pinMode(LED_BUILTIN, OUTPUT);
  //digitalWrite(LED_BUILTIN, LOW);

  // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

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

  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");

  //servoMotor.attach(Pin);

}

void loop() {
  // Check if a client has connected
  WiFiClient client = server.available();
  temp1 = digitalRead(D1);
  temp2 = digitalRead(D4);
  temp3 = digitalRead(D6);
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  // Match the request
  if(temp1 == HIGH) {
    digitalWrite(D2,HIGH);
    servoMotor.attach(Pin);
    servoMotor.write(90);
  }
  else{
    digitalWrite(D2,LOW);
  }

  if(temp2 == HIGH) {
    digitalWrite(D5,HIGH);
    servoMotor.attach(Pin);
    servoMotor.write(-90);
}
  else {
    digitalWrite(D5,LOW);
}

  if(temp3 == HIGH) {
    digitalWrite(D7,HIGH);
}
  else{
    digitalWrite(D7,LOW);
}

  int value = LOW;
  while (value = LOW); {
  if (request.indexOf("/LED=ON") != -1)  {
    //digitalWrite(LED_BUILTIN, HIGH);
    value = HIGH;
    servoMotor.attach(Pin);
    servoMotor.write(0);
    delay(1000);

  }
  if (request.indexOf("/LED=OFF") != -1)  {
    //digitalWrite(LED_BUILTIN, LOW);
    value = LOW;
    servoMotor.attach(Pin);
    servoMotor.write(180);
    delay(1000);

  }
  if (request.indexOf("/LED=STP") != -1){
      var = 1;
      while(var < 10){
    //digitalWrite(LED_BUILTIN, LOW);
    value = LOW;
    servoMotor.attach(Pin);
    servoMotor.write(90);
    delay(200);
    servoMotor.write(-90);
    delay(200);
    var=var+1;
    }
  }
  if (request.indexOf("/LED=STOP") != -1)  {
    //digitalWrite(LED_BUILTIN, LOW);
    value = LOW;
    servoMotor.detach();
    delay(1000);
  }

// Set ledPin according to the request
//digitalWrite(ledPin, value);

  // Return the response
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println(""); //  do not forget this one
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");

  client.print("Robot is now: ");

  if(value == HIGH) {
    client.print("Moving Forward");
  } else if(value == LOW) {
    client.print("Moving Backward");
  } else if(request.indexOf("/LED=STP") != -1) {
    client.print("Moving in Step");
  }else {
    client.print("Stopped");
  }

  if(temp1 == HIGH) {
    client.print("Led_1 is on");
  }else if (temp1 == LOW);{
    client.print("Led_1 is off");
  }

  if(temp2 == HIGH) {
    client.print("Led_2 is on");
  }else if (temp2 == LOW);{
    client.print("Led_2 is off");
  }

  if(temp3 == HIGH) {
    client.print("Led_3 is on");
  }else if (temp3 == LOW);{
    client.print("Led_3 is off");
  }

  client.println("<br><br>");
  client.println("<a href=\"/LED=ON\"\"><button>Move Forward </button></a>");
  client.println("<a href=\"/LED=STP\"\"><button>Step </button></a>");
  client.println("<a href=\"/LED=OFF\"\"><button>Move Backward </button></a><br />");
  client.println("<a href=\"/LED=STOP\"\"><button>STOP </button></a><br />");
  client.println("<a href=\"/Temp1=HIGH\"\"><Input>LED_1 ON </Input></a><br />");
  client.println("<a href=\"/Temp2=HIGH\"\"><Input>LED_2 ON </Input></a><br />");
  client.println("<a href=\"/Temp3=HIGH\"\"><Input>LED_3 ON </Input></a><br />");
  client.println("</html>");

  delay(1);
  Serial.println("Client disonnected");
  Serial.println("");
  }
}
```

P.S. I just edited the code to do the turns when the input is pressed for the third input it is supposed to make a random turn (either left or right the machine needs to decide on its own) and I am not sure how to write that in the code.

body:
Your code will only do anything if a client has connected to it because of this line
```
if (!client) {
    return;
  }
```

Your physical button will never do anything on their own unless a client has connected and has sent some data.

For the random direction you use a line like the following to randomly pick a direction
```
int direction = random(0,2) ? 1 : 0 ;
```
your direction variable will be with either 1 or 0 randomly


message:
Voltage divider and NodeMCU inputs

Some sensors give as output a voltage between 0 and 5V. The analog inputs of the NodeMCU require voltages between 0 and 3.3V. I plan to make a voltage divider with two resistors like in this [link][1] for compatibility.

To provide the desired voltage the quotient of the values of the resistances is fixed (approx. 1/2 for this case). However, the absolute values of the resistances are not.

**Q:** How to choose those absolute values? Which are the criteria and why?

I have a good background in electromagnetism but I know very few about electronic Engineering.

I think that low values must work, e.g. 1Ω and 2Ω (and surely greater values). But I am unsure of VERY high resistance values because I suspect that there should be some current intensity requirements.

Thank you.

  [1]: https://learn.sparkfun.com/tutorials/voltage-dividers/all

body:
The low end of the values is limited by how much current your sensor can provide. If you use 1Ω and 2Ω resistors in series then your sensor will need to provide 1.67A to create 5V across the divider. I doubt that your sensor can do that. For most sensors, you would want to use resistors in the kilohm or tens of kilohm range.

The high end is limited by the input impedance of the analog input pin. If your resistor values are large compared to this input impedance then the input impedance of the analog pin will affect how the voltage divider works. If the analog input is multiplexed and the ADC has a sample-and-hold at the input, then very large resistances in the divider will not allow the sampling capacitor to charge fast enough. For most ADC inputs, you would want to use resistors in the tens or hundreds of kilohms.


body:
As @Majenko commented, the A0 input has a fixed voltage divider (see [NodeMCU Schematics)][1] that connects the A0 input to a 220kOhm resistor, then to the ADC pin of the ESP8266, then to ground via a 100kOhm resistor.

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

This effectively fixes the resistor values that can be used to scale the input of the NodeMCU. For a 0-5.0V input range (with sufficiently low impedance) you need to scale the ADC pin from 0-1.0V by adding a ~180kOhm resistor between the 5V output and the A0 input of the NodeMCU, creating a 400kOhm-> ADC -> 100kOhm divider like this:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/3rS2N.png)

<!-- End schematic -->

  [1]: https://github.com/nodemcu/nodemcu-devkit-v1.0/blob/master/NODEMCU_DEVKIT_V1.0.PDF
  [2]: https://i.stack.imgur.com/QGkPV.jpg


body:
To better understand voltage divider, one can look at this online calculator https://ohmslawcalculator.com/voltage-divider-calculator to see the actual formula and try the calculator to compute the unknown wanted.

It is not well publish the existing voltage divider on the NodeMCU, of course you need to browse the schematic to figure it out.

It goes the same with existing pullup resistor for some GPIO.

@Majenko your explanation is excellent!