text:
ESP-01 not waking correctly up after deep sleep
I have an ESP-01 that I want to measure pool temperature with. It will send the data over MQTT to the broker.
I have connected RST to GPIO16 so I can use the deep sleep functionality. Currently I am testing sending a "hello world" to the MQTT broker, and everything works fine when booting up the first time, but it seems like the ESP never wakes up correctly after the first deep sleep.
My script looks like this:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Set ADC mode
ADC_MODE(ADC_VCC);

// WiFi settings
const char* ssid = "Network";
const char* password = "Password";
IPAddress ip(192, 168, 0, 100);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);

// MQTT settings
const char* mqtt_server = "192.168.0.110";
const int mqtt_port = 1883;
const char* mqtt_user = "User";
const char* mqtt_pass = "Password";
const char* mqtt_client_name = "poolsensor";
const char* mqtt_topic = "pool";

// Data wire plugged into D1 on the ESP8266 ESP-01 - GPIO 5
#define ONE_WIRE_BUS 5

// Setup OneWire instance to communicate with any device
OneWire oneWire(ONE_WIRE_BUS);

// Pass our OneWire reference to Dallas Temperature
DallasTemperature DS18B20(&oneWire);

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {
  delay(10);

  // Annuonce connection
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  // Setup WiFi config and connect
  WiFi.mode(WIFI_STA);
  WiFi.config(ip, gateway, subnet);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Connected, IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // Loop until we're connected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");

    // Attempt to connect
    if (client.connect(mqtt_client_name, mqtt_user, mqtt_pass)) {
      // Success
      Serial.println("connected");
    } else {
      // Fail
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

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

  // Start WiFi setup
  setup_wifi();

  // Set MQTT server
  client.setServer(mqtt_server, mqtt_port);

  // Set resolution to 0.25
  DS18B20.setResolution(10);

  // Start sensor
  DS18B20.begin();
}

void loop() {
  if (!client.connected()) {
    reconnect();
  } else {
    // Get temperature
    /*
    DS18B20.requestTemperatures();
    float temp = DS18B20.getTempCByIndex(0);

    if ((temp > -20) && (temp < 60)) {
      client.publish("pool/temperature", String(temp).c_str(), true);
    }
    */

    client.publish("pool/temperature", "hello world");
    Serial.println("published temperature");

    delay(1000);

    // Sleep
    ESP.deepSleep(60 * 1000000);

    delay(3000);
  }
}

Everything looks good in the serial monitor when compiling and uploading code, as the code runs the first time:
Connecting to Network
......
Connected, IP address: 192.168.0.100
Attempting MQTT connection...connected
published temperature

And I can see in my MQTT debugger that it receives hello world. After around 60 seconds, the following is shown in the serial monitor (lots of gibberish):
{l�l��|��d�|�d�b<����s�c$�#��ng�lgn���cxp��${$sd�s��'�c�ncp��

This is the last message I ever receive from the ESP, so I assume it never deep sleeps again and runs over the code again.
Anyone experienced the same, or see a bug in my code?

you have io 0 LOW?

How did you connect anything to GPIO16 on an ESP01? Other than very carefully of course - and D1??? that's wemos/nodemcu garbage (plus the  ESP01 doesn't break out gpio 5 either

if you set your serial monitor to 74880 baud, then you may be able to read the gibberish

@JaromandaX Actually the temp. sensor is not connected yet, so I commented out the code. I ran a thin copper wire from RST to the correct pin on the chip. Baud 74880 worked, and it reads the following: ets Jan  8 2013,rst cause:5, boot mode:(1,6) ets_main.c but only once, and never more.  @Juraj no, should I use pinMode(0, LOW); ?

boot mode:(1,6) look that up , I think you're in "Download code from UART" mode - should I use pinMode(0, LOW); no, or yes, doesn't make a difference

boot mode:(1,6) definitely "Download code from UART" mode - you need to make sure GPIO0 (and GPIO2 - but that doesn't seem so flakey on an ESP01) are HIGH on boot - use a pullup resistor from GPIO0 to VCC

@dandavis, he answered that " I ran a thin copper wire from RST to the correct pin on the chip"

@JaromandaX I have a similar issue - receive a lot of gibberish after coming back. Changing Baud to 74880 revealed boot mode:(3,7). Does this mean that GPIO0 and GPIO2 are high as they should, but something else is wrong? DFRobot show in their diagram that XPD is connected, which is shortcurcuited to RESET.

@JensMunk boot mode:(3,?) does indeed mean the 0 and 2 are high and 15 (MTDO) is low, as it should be for "normal" boot - so that's not your problem

Pretty sure you will need gpio 16 connected to reset in order for this to ever work, it’s tricky but not impossible. Have a read here:
https://randomnerdtutorials.com/esp8266-deep-sleep-with-arduino-ide/

I did that. Small copper wire from RST to GPIO16 on the chip.

Sorry, missed that one. From your code above it should be waking as expected. As others have said pulling GPIO 0 high is required for normal boot, GPIO 2 is not required but it is good practice to ensure stability. What you are most likely seeing and what I have seen in the past, if you have GPIO 0 grounded, i.e. to program with the arduino IDE, immediately after programming is complete, the chip will reboot normally and run with GPIO 0 grounded, but only once. If you leave GPIO 0 grounded and reboot again (or the chip wakes from sleep) it will not boot. Take GPIO 0 high and it should  work.

You left io 0 floating. With io 0 not HIGH at boot, the esp8266 goes into flashing mode.
The wake-up from deep-sleep is boot startup. So your code doesn't start if io 0 is not pulled high. Add a pull-up for io 0.
If you set Serial Monitor to 74880 baud, you will see the boot-log readable. It will print 1 as first value in "boot mode". This value is set from state of io 15, 2 and 0. 15 should be LOW and io 2 and io 0 HIGH for normal boot. 1 indicates that only 2 is HIGH.

Thanks for your reply. I'm not quite sure if I understand. No guides I've read says I have to pull 0 high. I use a programmer for programming, but I still have the same initial issue when I disconnect the programmer and just connect VCC and GND to a power source.

every good esp-01 tutorial connects EN and io 0 to VCC. I would use a pull-up resistor

do you understand that io 0 state at boot determines if the board boots to application or to bootloader?

Of course, but previously I never have to do this. I've used ESP-01 in several projects, but never with deep sleep, so this is new to me.

after upload it start without reboot

fwiw, i've found you need to wire EN to VCC on the ESP-01. but not on the ESP-01S, if that clarifies things.

yes, 01S has pull-ups on board, but then to flash it io 0 most be connected to ground

Ok, maybe I actually have an 01 and not 01S. I will do some research on this.

@Ronny-AndréBendiksen, what is the result? did the answer help?

I had the same problem and i found out, my CH_PD pin and RST pin were shorted together, when i was connecting wire from RST to GPIO_16. On the chip, the CH_PD pin is next to GPIO_16, so when you short them, the RST pin is always high, so esp cannot reboot anymore without external grounding. I fixed it and now deep sleep is working again!


text:
timer library on Arduino DUE
I'm trying to call an interrupt routine (let's call it handler() ) every second on my arduino DUE.
I thought the simplest way to do this was to use this library
but it seems that i don't know how to use it...

I guess you mean start(1000000).

yep............... this is embarassing ahahah
Do you have a guess on why wasn't it working with start(1000) ? is Serial.print too long to execute ?

Serial print in an ISR is not recommended. Set a flag in the ISR and poll in the loop() instead.

You are trying to print 6 characters ("test\r\n"), i.e. 60 bits
including the start and stop bits, 1000 times per second. This requires
a baud rate of at least 60 kbit/s, yet the serial port has been
configured for only 9.6 kbit/s. Something has to give...
As Mikael Patel wrote in a comment, it is generally inadvisable to
Serial.print() from within an ISR. It is supposed to work, though, as
long as you don't fill the Serial output buffer. The problem is that
your code does fill the buffer, as it is writing to it faster than the
UART can empty it. Once the buffer is full, the program will
malfunction.

thank you ! I will definitly use a flag now

source: Stack Exchange

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

sort: votes


text:
Negative currentmA and Shuntvoltage
Why is my INA219 current sensor gives a negative currentmA and Shunt voltage?  My sensor is connected in a glucose test strip connector. The current is from a glucose biosensor? Is it possible that my INA219 is damaged?

Did you connect it the wrong way around? Does the glucose strip maybe produce a voltage?

I connect it according to the schematic. The glucose test strip produce current

Could you show us the schematic? You haven't given us a lot of information to go on.

make sure the ground path is low-impedance between the MCU, the INA, and the sensor.

The "sign" of the INA219 shows the direction of flow of the current. Current isn't either "positive" or "negative", it has a direction. The sign is just used to represent that direction.
It's like a car. It has a speed. That speed could be in the forward direction, or the reverse direction.  It could be going 5 miles per hour forwards, or 5 miles per hour backwards. Either way, it's 5 miles per hour. However the backwards direction could be represented as "minus 5 miles per hour". It doesn't mean that you're doing a negative speed (there is no such thing), but that your speed is in a "negative direction".
This "speed" and "direction" are combined together to create "velocity", which is "speed relative to some arbitrarily chosen 'normal' direction and speed".
At this point the "velocity" can be represented as a 2D vector, with forward velocity in the + direction, and reverse velocity in the - direction.
But that's all a bit of a digression. All it means is that the "-" is meaningless if you don't care about the direction of current flow. If all you care about is the quantity of current you can discard the "-" completely.  The simplest way is:
current = abs(current);

Last month I measure the led with a 9 volts battery and the output is the same as I expected but when I tried it this week it gives negative values

Were the values (about) the same, but negative?

No.  It changed values and become negative

Did you calibrate it correctly?

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


text:
nRF24L01 with antenna transmitter and receiver

I am trying to use nRF24L01 with antenna  in my project, but when I do test with getting start from rf24 master is showing a serial monitor like in the picture abov e. What is the problem here?

Does your serial monitor Baud-Rate match the one of the sketch?

Thank you very much you find it i checked now and look ok!

Search in the code for the line Serial.begin(###) where ### is a number representing the serial speed, also known as baud rate.
This number must match with the baud rate of your serial monitor, otherwise all you get is garbage.
BTW, this has nothing to do with nRF24, this is plain Arduino serial connection.


text:
Serial communication problem NodeMCU
this is my first post here. Before I ask you my problem, I'm sorry if I'm wrong to write but my English is bad.
So, my problem is this: I'm developing a "client-server" system with serial communication between my computer and the NodeMCU. The PC will send a message (an integer) to the Node which makes certain things based on the number. At the end of the work the Node will send an ACK to the server (an integer).
I programmed the NodeMCU using the Arduino tool and in the first preliminary tests everything worked: the Node received and answered correctly. Then I wrote a script in Python to automate the thing and that's where the problems start. Communication takes place correctly but the messages that the Node sends to the PC are dirty. At the beginning of the buffer there are some illegible bits while at the end of the buffer there is the correct message. I did the same test with the Arduino Uno and this works perfectly.
Can you give me a reason for this problem and in case a solution?
Thanks in advance!

NodeMCU:
void setup( )
    {
        Serial.begin( 9600 );
        while ( !Serial );
    }

void loop( )
    {
        if( Serial )
            {
                Serial.write( (int)12 );
            }
    }

Python:
#!/usr/bin/python
import serial

port = '/dev/cu.wchusbserial1420'

ard = serial.Serial(port,9600,timeout=5)

x = ard.read(1)
x = int( x )

print x

(I am attaching some screenshots)

post your code as text, not pictures.

Try ard.flushInput() instead of ard.flush()

what about a number >255? hows that work?

Opening the serial port might cause a reset of the NodeMCU through the DTR/RTS pins. You might want to wait a second after opening, then read and flush all the input on the COM port and then start reading.

Use x = ord(x) instead of x = int( x ). ord() converts character to it's DEC value. 'int() ` converts only number characters to number.

try Serial.println(String(x)); to format it for consumption by your python parser. It has more overhead than raw multi-byte binary values, but will work on any int.


text:
12 V relay using Arduino
I want to control a 12 V relay using an Arduino 5 V signal, but due to some unknown reason the relay does not work. I am using a BC548 transistor as a switch for relay.
Please suggest where I go wrong.

issue aside, you need a flyback diode to save your NPN. Does the relay trigger if you feed the NPN +5v instead of a GPIO output?

I have added flyback diode in actual circuit forget to add in diagram.

yes the relay works when I give 12v to base

what about 5v, like the AVR would provide?

i didn't tried it but It only works when i give higher than 5v

It could be a lot of things then. I would swap the NPN for an NCHAN mosfet, preferably logic-level. I use the IRLZ44N in a lot of 3.3v projects, makes a great low-side switch.

Have you connected the grounds?

@Majenko yes i did.

If it's working with 12v on the input but not 5v, it sounds like the base resistor value
 (which is missing from the diagram) might be too high. A value of around 1k should ensure the transistor is fully switched on.


text:
Can't you easily use "quadrature" incremental rotary encoders at 2X or 4X their number of "stops"?
I bought a 12-step "quadrature" incremental rotary encoder as an input device for a project I'm working on.
When I wrote the code to track "ticks" of rotation, I made it respond to any change in the "A" pin. As a result, I got 24 steps, not 12. They appear to be evenly spaced, and still correctly indicate clockwise or counter-clockwise rotation.
It occurs to me that if I track changes of state in both the "A" and "B" pins, as long as I reverse the logic for identifying clockwize vs. counterclockwise rotation, I could get a 48 step count from the same encoder.
Thus isn't it straightforward to get 2X or 4X the steps from a quadrature  rotary encoder simply by interpreting the signals differently?

would that still work correctly when starting and stopping? it would seem the direction could be ambiguous if only one pin changed...

No, with quadrature encoding you can tell the direction based on one pin state change and the state of the other pin.

please clarify what this means got 24 steps

Yes, you are correct. You can track 48 different positions per rotation.

@Gerben, can you submit an answer (with a little more detail) so I can accept it? my naive code using digitalRead of the 2 pins is missing positions unless I rotate the encoder slowly. I found some code online this morning that uses pin interrupts. I gather that's the way to go?

My "answer" is the same as Jose's, just more to the point. Avoid using digitalRead, as it's pretty slow. Using interrupts would be the way to go. Depending on the amount of contact bounce, you might need to add some debouncing hardware (RC filter), so your software doesn't get flooded with interrupts, and miss some change.

Ok, I'll rewrite my code using interrupts and port registers. It's been several years since I dealt with pin reading using port registers, so I'll have to go do some digging. I've also never done interrupt handlers on Arduino before. I take it the ISR has to be a global function? (in the rest of my project I'm using C++ objects for things like sensor handles, so would prefer it to be an instance method, but I'm guessing nope.)

Maybe the encoder you got is being incorrectly described?  I have a handful of the little thru-hole rotary encoders popular in Arduino module kits and they have 12 detents for one rotation, but they are actually 48-position-per-rotation encoders. When I use them, I have to divide the tick count by 4 to have one physical "click" count as one tick in my code.
For some of these, it's fairly straightforward to open them up and remove the detent, and thus get a higher-resolution, smooth spinning encoder. Unfortunately, others, such as the ones I have, are difficult to open without destroying them, and since they physically snap to the detents, aren't usable at the proper resolution.
The method you note, where you track the high/low change in either direction of both outputs is the normal way to read quadrature encoders.

The one I bought is a 12-step encoder, but doesn't have detents. From what I've read the norm is to only track rising edge changes on one of the channels, which would give me 12 steps.  Thus your answer confuses me.

Mine is a Bourns PEC11-4020K-S0012 (Jameco part 2277703) encoder with switch.

Reading the datasheet shows it's described as "12 pulses per 360deg rotation". Clearly they mean 12 pulses (up, then down, then back up; or down, then up, then back down) on one channel, and not 12 level changes. I suppose what's "normal" depends on a lot of things. Many Arduino scripts use a less useful process of looking for a rising edge on one channel and then checking the other channel to determine the "direction" of rotation. But that wastes so much information!

"12 pulses" means 12 rising pulses on a single channel in this case. My point is that depending on how you write your code, you can  treat that as 12, 24, or 48 steps plus direction information, and without having to divide the tick count by anything.

The answer to my question is yes.
Normally you only count the falling edge of one of the outputs of an incremental encoder as a pulse. That gives you the specified number of ticks for that kind of encoder - 12 ticks per turn in the case of my encoder.
If you instead write your code to respond to either rising or falling edge changes on one of the pins, you get 24 ticks per revolution.
If you instead write your code to respond to rising or falling edge changes on either pin, you get 48 ticks per revolution.
The code I came up with looks like this:
void setup() {
  //Use this setup code for 12 ticks/revolution
  attachInterrupt(digitalPinToInterrupt(rotaryPinA), encode, FALLING);

/*
  Use this setup code for 24 ticks/revolution
  (trigger interrupt on rising and falling edge)
  attachInterrupt(digitalPinToInterrupt(rotaryPinA), encode, CHANGE);
*/

/*
  Use this setup code for 48 ticks/revolution
  (trigger interrupts on rising and falling edge of either pin)
  attachInterrupt(digitalPinToInterrupt(rotaryPinA), encode, CHANGE);
  attachInterrupt(digitalPinToInterrupt(rotaryPinB), encodePinB, CHANGE);
*/

//The rest of your setup code...
}

And the interrupt service routines (ISRs):
void encode() {
  rotaryValueChanged = true;
  //Read the PinA & PinB (Digital Pins 2 & 3) using port register PINE, 4th and 5th bit
  //Fast equivalent to pinAState = digitalRead(rotaryPinA) == LOW
  bool pinAState = (PINE & (1 << 4)) == 0;
  bool pinBState = (PINE & (1 << 5)) == 0;
  rotaryValue +=  (pinAState == pinBState) ? -1 : 1;
}

void encodePinB() {
  rotaryValueChanged = true;
  //Read the PinA & PinB (Digital Pins 2 & 3) using port register PINE, 4th and 5th bit
  bool pinAState = (PINE & (1 << 4)) == 0;
  bool pinBState = (PINE & (1 << 5)) == 0;
  rotaryValue +=  (pinAState != pinBState) ? -1 : 1;
}

If you only set up one interrupt on rotaryPinA, the 2nd interrupt method never gets called.
The code above is specific to the Arduino Mega 2560 and other boards that have the same pin to register mappings. It uses interrupts so it doesn't miss state changes in the pins, and reads the pin states using port registers for speed.
Note that if you're only adding a falling edge interrupt you can skip the read of pin A (since when the pin state falls it will, by definition be at a logic 0 whenever the ISR gets called.)
To get this to work well I had to build the RC filter circuit described in the spec sheet for my encoder:
https://www.bourns.com/docs/Product-Datasheets/PEC12R.pdf
The diagram looks like this:

And I had to add Schmitt triggers between the filter outputs shown above and the input lines to the Arduino.
Without the Schmitt triggers it gets jitter when the voltage from the filter doesn't switch between HIGH and LOW values fast enough. The Schmitt triggers exclude spurious readings from those "dead zone" voltages.
With those changes the readings from the encoder are quite good, although it still measure ± 1 tick or so per revolution for some reason.
I wish now I had bought the version of the encoder that has detents so it rotates in discrete clicks.

I find it somewhat surprising that you had to add Schmitt triggers, as the Arduino already has built-in Schmitt triggers on all its digital inputs.


text:
Where does the Arduino core include the name of the sketch?
I'm trying to look through the Arduino core to find where "mySketch.ino" is included or implemented. In 'Arduino.h', the prototypes void setup(void) and void loop(void) are defined, in 'main.cpp', setup(void) and loop(void) are called, but I'm not sure where 'main.cpp' or any other related files makes a reference to the sketch.
Where does this occur?

The files don't reference the sketch. They don't need to. That's not how C compiling works. Look up "Linking (Compiling)" in Google to understand more.

Here is the "main()" source file for the Arduino core. https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/main.cpp

Compilation doesn't start with the Arduino.h or the core files; rather, it starts with your own sketch, "whatever.ino". Your .ino file includes Arduino.h into the compilation which makes references to core modules. That compilation leaves many references to to be satisfied, and itself satisfies several - setup() and loop(), for two. At link time, the linker is told to read not only your compiled module(s), but also the compiled core files, from which it can extracts the modules required to satisfy references made by your compiled code. Then it combines your module, and those modules required by it, into the load file that avrdude uploads to the Arduino.

Just want to add, that the Arduino IDE also concatenates all the .ino files in the same sketch together; .cpp, files are compiled automatically as well, but are not modified like the .ino files.


text:
Is it possible to upload an arduino sketch through the serial port (RX) instead of USB
In another words, is it possible to develop a custom bootloader so sketches can be uploaded via serial connection made using the RX/TX pins and not via the USB connector (I am using Pro Micro boards)?
Thanks!

This is definitely possible. Bootloader is just a program which can communicate whatever hardware is available and write memory and jump to it.

This should be possible by adapting the serial bootloader typically used on the ATmega328p (etc) to your ATmega32u4.  The details of doing so however do not really fit in a question on a Stack Exchange site unless you explain a specific difficulty.  Make sure to do some searching, it is quite possible someone has already done this project.  Also consider if switching to an Arduino type board that simply has an ATmega328p (especially a compact one without a 2nd chip as a USB bridge, though you can bypass that) might be the simplest route to fill your need.

Makes sense, thanks for your answers, sorry I did make a search for that prior to asking but couldn't find any simple answer to this question.

No need to have a specific bootloader. The basic bootloader can do that (in Arduino that's the case so I hope this answer will apply in your case. But if not, the principle is certainly the same).
Once you perform a reset on the board, the bootloader look at the serial port during a short time. If something come, it checks if it's an hex file and if yes it send it to flash. The USB just use the RX input.
So you can send data using a direct connection or using for example a Bluetooh like HC-05. I do that for some project in order to update via Android: the Android app send an order to the Arduino, through Bluetooth.
Receiving this, the Arduino RESET itself, and then the Android App send immediatly data.
On Arduino side: connect for example A0 to RESET PIN and perform a digitalWrite(PIN_RESET,HIGH);
Have also a look at Reset an Arduino Uno in code
After the RESET, the board will reply with 0x14 0x10 (so it send this to TX and so if you have a bluetooh module, you'll received than on your Android App (eg))
You must then send  0x50 0x20 to the board to tell it you enter programming mode.
Then send 0x75 0x20 to get the id of the board in order to be sure you will send the HEX file for the right hardware.
You will receive 0x14 XXX 0x10 where XXX = id of the board
Then you can send the HEX file.
For that, you will send it by blocks of 128 bytes
So start by dividing the HEX to know the number of blocks then loop against this  number:
Start at ADR=0 (adresse dest in flash) and send:
For each block:
1) Send 0x55, low byte of ADR, high byte of ADR, 0x20
2) check reply (must be 0x14 0x10)
3) Send the 128 bytes: 0x64, 0x00, 0x80, 0x46 then the 128 bytes and finish by 0x20 (0x80 is the size)
4) check reply (must be 0x14 0x10)
5) update ADR. Take care: ADR is a word pointer (2 bytes). So ADR = ADR+0X40
Loop on num of blocks
Finish the job by sending 0x51 0x20 (exit programing mode)
Some details:

0x46 before the 128 bytes tells you want to write in flash. Other codes are available eg for checking, getting data etc..

It seems mandatory to send each time 128 bytes. So if your last block is smaller, you need to add some '\0' to get a total of 128. I've been unable to get good results trying to change the 0x80 value and send less bytes. :(

It's not very easy and need tests to get a good code but that really fine to be able to have an Arduino the user can update.
Hope this will help.

Yes. You can develop a bootloader for the ATmega32u4 that will receive firmware over any interface (UART, SPI, I2C etc.).
Loading via UART is a solved problem. Look for the AVR109 bootloader.

Yes, there is an Optiboot fork supporting ATmega32U4 supporting hardware UART to upload Arduino sketches.
Also, a detailed instructable post explaining how to use it with Arduino Pro Micro.


text:
Risks when commanding multiple chips with same address via I2C
I know that I2C devices are supposed to have unique addresses when used. What if I still use multiple devices with the same address, what can go wrong? Let me describe the situation:
I have multiple digital capacitors (NCD2400M by IXYS) and I would be using them so, that I always send the same command to every chip. I have no need of reading anything from those, which is the reason I was thinking why should I bother multiplexing my I2C line. I have no reason to identify them, only commanding. For the commanding I use Arduino (Nano currently, might change to some other Arduino model).
I have already tried commanding them simultaneously and it works like a charm. I tried so that I connected SDA and SCL of four chips and used RC circuit and square wave to check the rise time to verify that every chip indeed changes their capacitance.

However, I'm new to I2C protocol and I'm not yet aware of every detail. I guess there could be issues when one of the chips fail? Can I assume in this case that nothing goes wrong with the ACK/NACK bit since the chips are "identical"?
-RautSa
EDIT:
After using correct keywords for searching I found this previously asked question. Based on that I now understand at least there would be a problem when only one of the chips tries to send NACK bit.

Please add a link to the sensor to your question. https://www.ixysiss.com/ncd2400

@Jot Thanks for the note, I added the link.

@Jaromanda X I guess you didn't bother reading my post? It does work, I have tested. The question is does it pose risks when used in a way it isn't intended to be used.

@Jaromanda X You really should elaborate your answers. If I expect it to not work correctly, it propably works correctly? Comments like "propably won't work" aren't helpful. If you had commented why it propably won't work, now that would have been helpful.

There is no risk for damaging something, but the risk is the reliability.
The NCD2400M operates at 3.3V and 5V, so that will work with every Arduino board.
Your question is very similar to the question that you already found: electronics.stackexchange.com/questions/417263/multiple-instances-of-same-device-on-i2c-bus.
There are a few specific Arduino things to mention.
During Arduino setup() a sensor is often checked if it is connected and if it is possible to communicate with a sensor. That would be impossible when the sensors share the I2C address.
The Arduino Wire library detects a bus error, for example when there are other I2C Masters on the bus, and returns with an error.
Since your NCD2400M are only Slaves, I think that they will not trigger a bus error.
You need some luck, and I can not guarantee that it will always work:

When the NCD2400M behaves like a normal I2C Slave and it is not too
smart, then it does not detect that another one pulls the SDA low
for an acknowledge.
Some sensors send a NACK when they are busy, I
can not find such a note in the datasheet. You could write to the
NCD2400M twice to be sure that they have received it.
When they have an
internal clock and respond with different timings on the I2C bus,
then you can set the SCL clock lower. For example
Wire.setClock(50000); after Wire.begin() for a 50kHz SCL clock.

When one of NCD2400M is blown, then you are not able to identify the bad one. However, when one of the NCD2400M is blown, perhaps the whole circuit is no longer reliable.
For a good design, you should know if you are actually communicating with a sensor or just talking into thin air. When you have made more Arduino projects, then you know that it is essential to know if a sensor is connected or not.
Trying this solution to make it "easy" for now, might cause a lot of troubles later.
Conclusion: It will work. You can use it for a test. When you use it in the final version, you take the risk that it can cause a lot of troubles.
More about the basics of the I2C bus: http://www.gammon.com.au/i2c

Thank you for your answer and the tips. With my current prototype I'll proceed with this configuration, and later on I'll add multiplexing to the more final design. Not getting the NACK information is a reason serious enough to implement the multiplexing. Too bad they only have two addresses available for the chip.

@RautSa with 4 chips and no multiplexer, you need 5 digital pins of the arduino nano. With a software i2c library and a single scl and four sda, you have four i2c busses. When each chip can have two addresses, then you need only two i2c busses, that is 3 pins with a software i2c library.

Could always add a switch like DG406, DG409, or equivalent to select which cap is connected to SDA so that only one is commanded at a time. Pullup SDA on the output side so it is not floating at the chip.

True, that's possible. Most likely I'll have to go with the implementation which takes the least amount of space on the final designs PCB, so I'll have to check the options.


text:
Arduino ESP8266 ESP-01S GET command
Looking for some help on this please. It is a little long winded, but the point of it is I cannot retrieve a string response via my ESP8266 ESP-01S.
I connect my ESP to my Ardiuno using SoftwareSerial esp8266(2,3).
I can quite happily send POST and GET commands to my server and process the request server side. This is done through the AT sequence below. My server uses a REST API to receive the request and responds with a simple string (for example 'HELLO'). If I attempt the same client side functionality through C# code or Python on my Pi I receive the response from the server no problem. But on my Arduino the response is always 32 when reading via ESP.read() (which I believe is in bytes and signals end of data). I have also tried esp.readString() and esp.readStringUntil('\n') all with no luck.
Is it not possible to access the response sent back to the ESP using my approach?
I see many examples go down the route of programming the ESP directly. I'm not really looking to do that on this attempt as I am creating some basic Arduino tutorials for family and friends and would prefer to not add that complexity.
Result server response
esp8266.println(postRequest);
while (esp8266.available() > 0) {
  Serial.println("." + esp8266.readString() + ".");
}

So I guess in short, am I wrong in expecting the
//* AT SEQUENCE*
AT
AT+RST
AT+CWMODE
AT+CWJAP
AT+CIPMUX
AT+CIPSTART
AT+CIPSEND

// CREATE DATA

String data = "=DATA1";

// POST

String postRequest =
  "POST " + URI + " HTTP/1.1\r\n" +
  "Host: " + HOST + ":" + PORT + "\r\n" +
  "Accept: *" + "/" + "*\r\n" +
  "Content-Length: " + String(data.length()) + "\r\n" +
  "Content-Type: application/x-www-form-urlencoded\r\n" +
  "\r\n" +
  data;

// GET

String postRequest =
  "GET " + URI + "?data=" + data + " HTTP/1.1\r\n" +
  "Host: " + HOST + ":" + PORT + "\r\n" +
  "Accept: *" + "/" + "*\r\n" +
  "Connection: keep-alive\r\n" +
  "Content-Length: " + String(0) + "\r\n" +
  "Content-Type: text/plain\r\n" +
  "\r\n";

the host header value should not contain port

@Juraj That's not true. It's not needed only if it's the default, but even then it's nothing wrong having it.

Those AT commands are missing arguments. 32 is the ASCII code for a space character. The HTTP server's first character of the response should be "H". Neither your POST or GET request have the proper format for the parameters. GPIO3 is a hardware serial's RX pin.

thank you, @gre_gor. now I regret I was lazy to open the RFC

Juraj. Thanks, I understand. Although what is RFC?
@gre_gor, thanks for your response but I'm pretty new to this and what you've said is above my head. I've followed other tutorials (my project is a hybrid of many of them) to get here. Do you know what arguments I am missing? As I seem to have included enough to covert sending data to my server?

gre_gor corrects me with a link to RFC 2616 (HTTP protocol description). RFC is "Request for Comments" It is a way how standards are maintained at "Internet Engineering Task Force" organization


text:
Can an Arduino (Leonardo) be recognized via Bluetooth as a mouse/keyboard?
I'm new to wireless communication on Arduinos and doing research for a project. I'm looking at the Arduino Leonardo (which is like the Uno) which via its micro USB port can be automatically recognized as a mouse/keyboard. But also looking at a regular Uno wiFi Rev2.
I want to achieve the same result, but wirelessly via Bluetooth. Because I need to connect it to a device that only recognizes Bluetooth mice/keyboards and nothing else. If I buy something like the HC-05 how would the chip report itself?
How is the Bluetooth stack handled with regards to identification and authentication? Does it somehow copy the USB mouse/keyboard setup?
PS: Can anyone tell me if the Wifi Arduinos (Uno WiFi rev2) also have Bluetooth embedded?

warning, there is nothing regular on Uno WiFi Rev 2. It is completely different from Uno

I meant to say Leonardo is not regular because it has a built in usb keyboard thingy on chip.

If I buy something like the HC-05 how would the chip report itself?

As an SPP. I.e., a serial port.

How is the bluetooth stack handled with regards to identification and authentication?

By the firmware on the HC-05

Does it somehow copy the usb mouse/keyboard setup?

No.
You need a USB device that can emulate a keyboard. That's not the HC-05. The host microcontroller has absolutely nothing to do with what capabilities the bluetooth interface has.

Ok so the HC-05 can't spoof itself to report itself as a specific thing (keyboard). And even if it did it would not have anything to do with the on-chip built in usb thingy the leonardo has. Cool. So I'll probably try to find a usb-to-bluetooth keyboard adapter, or research a more advanced way to spoof a keyboard via bluetooth with a regular arduino like the uno wifi rev 2.


text:
Stepper wait for X seconds in a loop with millis (not delay)
In the code below I would like the stepper to bounce back and forward between two limit switches and while it is doing this it should turn and than wait for e.g. 1 second.
I thought I could achieve this with the if ((unsigned long)(currentMillis - previousMillis) >= interval) part, but it doesn't work.It won't turn. Any help would be great. Thank you.
// defines pins numbers
const int stepPin = 5;
const int dirPin = 4;
const int enPin = 12;
const int homeSwitchPin = 9;
const int homeSwitchPin2 = 11;

unsigned long interval=1000; // the time we need to wait
unsigned long previousMillis=0; // millis() returns an unsigned long.

void setup() {

   Serial.begin(9600);

  // Sets the two pins as Outputs
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
  pinMode(homeSwitchPin , INPUT);
  pinMode(homeSwitchPin2 , INPUT);
  pinMode(enPin,OUTPUT);
  digitalWrite(enPin,LOW);

  // Set Dir to Home switch
  digitalWrite(dirPin,LOW); // Enables the motor to move in a particular direction

}
void loop() {

    int homeSw = digitalRead( homeSwitchPin);
    int homeSw2 = digitalRead( homeSwitchPin2);

    if( homeSw == HIGH && (digitalRead(dirPin) == LOW) ){
        unsigned long currentMillis = millis();

        if ((unsigned long)(currentMillis - previousMillis) >= interval) {
        motorStep(1);
        previousMillis = millis();
        }
    }
    else if( homeSw == LOW && (digitalRead(dirPin) == LOW) ){
          digitalWrite(dirPin,HIGH);
          delay(2000);
    }

    if( homeSw2 == HIGH && (digitalRead(dirPin) == HIGH)){

        motorStep(1);
        // motorStep(32000);
        //digitalWrite(dirPin,LOW);

        //delay(2000);
    }
    else if( homeSw2 == LOW && (digitalRead(dirPin) == HIGH) ){
          digitalWrite(dirPin,LOW);
          delay(2000);
    }

}
void motorStep( int MAX){

   for(int x = 0; x < MAX; x++) {
        digitalWrite(stepPin,HIGH);
        delayMicroseconds(100);
        digitalWrite(stepPin,LOW);
        delayMicroseconds(100);
      }
}

Do the home switch pins have pull-up resistors on them? Your current code only makes the motor move one single step every second. So it's hardly moving. Are you sure it's not moving very slowly?

how many times do you want the motor to bounce back and forward between waits? ...... your description is unclear

Endless bounce back and forward, within that it should do other routines. @gerben maybe, but my question is how I can change that so it moves according to my routine. I need additional routines and therefore it would be great to know how to set this up. Thanks.

Have you tried spamming your code with print()s to determine if you are actually hitting the contents of the if() statement?

I asked two questions and you answer maybe. After reading your question 4 more times, it seem like you don't even need this if statement at all, and only change the delay(2000) to delay(1000) for your 1 second delay. And pinMode(homeSwitchPin , INPUT); to pinMode(homeSwitchPin , INPUT_PULLUP); to enable the pullup resistor.

I would like to solve this with millis() because I might have to integrate more than one stepper and for this using millis() is recommended even by Arduino. This is an excellent example of something I would call, in the lack of a better word, "best practices algorithms". I understand most of the lower level function, but lack the knowledge for these higher level algorithms and how they should be used. I would like to know where I can learn these most needed higher level algorithms for Arduino. Apart from asking on these forums.


text:
Reading a rotary encoder using digital pins of Mega 2560 directly using port registers?
I'm trying to write an interrupt service routine for an Arduino Mega 2560 to decode a quadrature rotary encoder. I've got an ISR (Interrupt Service Routine) that responds to the falling edge of digital pin 2.
I then need to look at the value of pin 3 and see if it is high or low to tell which direction the encoder is being turned.  I've built a simple debouncing circuit using a couple of resistors and a .01 μF capacitor per line from the encoder, so those signals are clean now.
Based on the reading I've done, it's best to read the pin states directly rather than using digitalRead in an ISR since the digitalRead() function is rather slow.
I am finding it hard to find and figure out the port mappings for the port registers to read the pins.
I believe that I should use
(PIND & (1 << 3) != 0 to read digital pin 3, since I think pins 2-9 are on register PIND?
I found this chart https://www.arduino.cc/en/Hacking/PinMapping2560 that lists the pin mappings for the Mega 2560, but I'm not sure how to read it.
If I use bool  pinBState =  digitalRead(rotaryPinB) == LOW in my ISR it works, but it seems to miss state changes sometimes.
If instead I use the code `bool pinBState = (PIND & (1 << 3)) == 0;
The value of pinBState never changes.
Can somebody tell me what I'm doing wrong?
See the self-answer below. It seems that digital pins 0-7 are read from PINE, not PIND.
However, now I have a new problem:
With the code shown in my answer I am getting readings that increase for clockwise rotation, and decrease for counterclockwise rotation, as expected:
If I rotate it very slowly through a full revolution, I can usually get exactly 12 steps in a rotation. If I rotate my encoder rapidly, or  through several full turns, it gives me values that aren't exact multiples of 12, and rotating it several turns clockwise, and then the same number of turns counterclockwise does not return the value to 0 like it should.
I'm using a simple debouncing circuit as recommended from the spec sheet for the encoder:
https://www.bourns.com/docs/Product-Datasheets/PEC11R.pdf
The circuit looks like this:

Shouldn't that circuit work? I wired it up on a breadboard, and have pretty long leads, and didn't cut the wires on the resistors or capacitors since this is still a test circuit. I wouldn't think this would be sensitive to RF noise though. The only other thing I've got on the project is an I2C LCD display. I've triple-checked my wiring and don't think I've made any mistakes.
I'm stumped as to why an interrupt-driven rotary encoder, with the recommended debouncing circuit,  that reads port registers to read the data from it's PIN B doesn't give reliable results for normal rates of turning on the control.

Are you looking for a complete list? https://forum.arduino.cc/index.php?topic=52534.0

No, I saw that page but can't make any sense of it. I need to know what code to use to read the value of digital pin 2 on my Mega 2560. Some coaching on how to read those tables would be a nice plus, but right now my focus is very narrow: Getting this single read to work.

Digital pin 2 is PE4  ... that is the 5th bit of port E

How is this different than what you asked here?  https://electronics.stackexchange.com/questions/423688/how-do-you-pick-component-values-for-a-debouncing-filter/423695?noredirect=1#comment1052330_423695

Digital pins 2 and 4, both have hardware interrupts on them. Why not use both interrupts? It's kind of overkill, but the mega has them, so why not use them. As to your current problem; You are missing steps, so either your code is too slow, or the debounce filter is to strong. The latter could easily be tested by using smaller capacitors. If rotaryValue and int? Is it defined as volatile?

Why the down-vote?

Gerben, my program can be set up to read just the falling edge of 1 pin (12 steps) the falling edge of both pins (24 steps) or the rising and falling edge of both pins (48 steps). For 12-step decoding, I only put an interrupt on one pin, and read the state of the other pin to figure out rotation direction. For the other cases I do set interrupts on both pins.

Ok, it looks like digital pins 0-7 are read from the PINE (That's PIN E) register, not PIND.
I am setting up my pins as input using normal Arduino code:
#define rotaryPinA 2
#define rotaryPinB 3

void setup() {
  attachInterrupt(digitalPinToInterrupt(rotaryPinA), encode, FALLING);

  pinMode(rotaryPinA, INPUT);
  pinMode(rotaryPinB, INPUT);
  //The rest of the setup function
}

And then my encode method:
void encode() {
  rotaryValueChanged = true;
  //Read my PinB (Digital Pin 3) using port register PINE, 5th bit
  bool pinBState = (PINE & (1 << 5)) == 0;
  //Here is the equivalent code using digitalRead:
  //bool  pinBState =  digitalRead(rotaryPinB) == LOW;
  rotaryValue +=  pinBState ? -1 : 1;
}

That code seems to work, but the value I'm getting from my rotary encoder drifts.

Have you tried some hardware denouncers - like MC14490?
Using Interrupts you can then detect all four phases of each encoder step.


text:
Millis() is Not Working
I have a sketch that uses two timers using millis() from a library I created to keep time. The timers seem to be working correctly, but when I print the start time of each timer, it is clearly wrong.
E.g. the timer is set to run for 3 seconds. When I start the timer the first time, it reads that it started at 0. The next time I start the timer, right after it has finished running once, it reads that it started at 2 seconds. This should not be possible.
I have even tried timing it on my phone, and have seen the timerStart value read 5 seconds, when the sketch has been running for 10.
Does anyone have any idea what could be going wrong? Code below.
Here is the library's .h file:
#ifndef Timer_h
#define Timer_h

#include <Arduino.h>

class Timer {
  public:
    Timer(unsigned long timerLength);
    unsigned long timerStart;
    unsigned long timeElapsed;
    boolean isFinished = true;
    boolean timerStarted = false;
    void startTimer();
    void checkTimer();
  private:
    unsigned long _timerLength;
};

#endif

Here is the library's .cpp file:
#include <Arduino.h>
#include <Timer.h>

Timer::Timer(unsigned long timerLength) {
  _timerLength = timerLength;
}

void Timer::startTimer() {
  if (!timerStarted) {
    timerStart = millis();
    timerStarted = true;
  }
}

void Timer::checkTimer() {
  timeElapsed = millis() - timerStart;
  if (timeElapsed >= _timerLength) {
    isFinished = true;
    timerStarted = false;
  } else {
    isFinished = false;
  }
}

And here is part of my sketch code, where the timerStart value is wrong:
#include <Timer.h>

Timer breathTimer(3000);
Timer betweenTimer(1000);

// this part determines if a turbine is spinning or not
SIGNAL(TIMER0_COMPA_vect) {
  uint8_t x = digitalRead(FLOWSENSORPIN);

  //if the turbine is spinning
  if (x == HIGH) {

    //start the breath timer
    if (betweenTimer.isFinished) {
      if (breathTimer.isFinished) {
        Serial.print("Breath Timer Started @ ");
        Serial.println(breathTimer.timerStart);
      }
      breathTimer.startTimer();
    }
  }
}

void setup() {
   Serial.begin(9600);
   pinMode(FLOWSENSORPIN, INPUT);
   digitalWrite(FLOWSENSORPIN, HIGH);
   betweenTimer.isFinished = true;
}

void loop() {

  // check the breath timer
  if (breathTimer.timerStarted) {
    breathTimer.checkTimer();
    if (breathTimer.isFinished) {
      Serial.println("Breath Timer is Finished");
      betweenTimer.startTimer();
      Serial.println("Between Timer Started");
    }
  }

  if (betweenTimer.timerStarted) {
    betweenTimer.checkTimer();
    if (betweenTimer.isFinished) {
      Serial.println("Between Timer is Finished");
    }
  }
}

Sorry, I just edited my post to hopefully include all the necessary information

Where is Timer.h? Which arduino board do you use, or is this in a simulation?

Timer.h is included in the libraries folder along with Timer.cpp. I can include it here if you'd like to see it. I am running this on an Arduino Uno. Not a simulation.

I would like to see it, for example to see the type of the variables in the class.

I just edited my original post to include it

The c++ variable is a 'bool', we prefer that. The 'boolean' is made up by Arduino, we think that is silly. You have isFinished and timerStarted, yet the timer is busy or not. The class is initialized with isFinished as true, but the timer has not run yet. In the ISR you check the isFinished (which is true at start) and the value is printed. There is somehow a wrong way in the logic of that. Start over and first figure out what you want to know and what you want to do with the timer. Using the Serial library inside an ISR is never a good idea, try to move that to the loop() if possible.

It helps (for us and for yourself) if you explain in words what the purpose of the library is. You can add that to your question.

Why use an ISR when the timer is on milli-second level and the sketch uses seconds? The BlinkWithoutDelay-pattern would work just as well and would, in this case, be easier to get working. You could use the Timemark library to make this even easier. https://github.com/mikaelpatel/Arduino-Timemark


text:
Parse a large json response with ESP8266
I'm doing a project where my Arduino uses an external ESP8266 wifi module (with AT firmware) to send http requests and receive server response.
I'm trying to get an NBA scoreboard, and here's what my Arduino sends to ESP:
> AT+CIPSTART=0,"TCP","data.nba.net",80
0,CONNECT

OK

> AT+CIPSEND=0,103
SEND OK

> GET /data/10s/prod/v1/20190214/scoreboard.json HTTP/1.1
Host: data.nba.net
Connection: keep-alive

+IPD,0,1460:HTTP/1.1 200 OK..
.............................
...here comes the response...
.............................

Now the code works fine, and I'm able to get the json file needed. The problem is that the response is sometimes too long and the file gets truncated, thus the response is incomplete. The file itself is sometimes pretty large, but I only need a few numbers from it (current teams + current score). So my questions are:

I use readString() method (of SoftwareSerial object instance) to read the response. Is there a way to parse the response chunk by chunk without loading everything in my ESP memory?
Is there a way to limit the response?
Are there any alternatives to the method I'm using? Maybe parsing the website (nba.com or espn.com/nba) directly? If so, how can I do that?
Maybe there's a way to write a separate (free) online API to parse json, constraint the response and send the small version upon request?

PS. I tried doing the same without AT firmware, flashing the module with a code that used HTTPClient directly (with ESP8266WiFi.h and ESP8266HTTPClient.h libraries):
HTTPClient http;
http.begin(request);
if (http.GET() > 0) {
    response = http.getString();
}
http.end();

That didn't help much. I'm still running out of memory since I'm directly loading the response to memory with getString().
PPS. Just in case it matters, I'm using ATmega2560 and a small ESP-01 module (similar to this).

large ... you'll need to be more specific than large

@JaromandaX .... go here .... http://data.nba.net/data/10s/prod/v1/20190214/scoreboard.json

what data are you retrieving? ..... you probably already know this, but here is the API for anyone else reading this https://github.com/kshvmdn/nba.js/blob/master/docs/api/DATA.md .......... there may be another way to pull the data

No. You go there. How hard is it to quantify large

@JaromandaX, > 10 KB is what I would call large. I think above that it just ignores the rest of the response.

@jsotola nah, not really. I looked around it before. The scoreboard.json is the closest I really need, and it's way too large as there is a data on streaming etc (who needs that anyway :D).

Ok, so I was able to do this. Here's the workaround.
Let's say the GET response is a flat string containing large .json file with all the commas and curly brackets. The idea is to read it byte-by-byte and instead of storing it just find the key you need and extract its value.
We want to find the field containing, say, "97.5 FM" from http://data.nba.net/data/10s/prod/v1/20190223/scoreboard.json (that's at the very end), skip 3 bytes (which is just " | ") and then read and Serial.print 4 bytes (which is "1280")*. We would do something like this (of course make sure to connect to wifi and include <ESP8266HTTPClient.h>:
HTTPClient http;
http.begin("http://data.nba.net/data/10s/prod/v1/20190223/scoreboard.json");
int httpCode = http.GET();
if (httpCode == HTTP_CODE_OK)
  Serial.println(getValue(http, "97.5 FM", 3, 4));

where the getValue() function is defined as follows:
String getValue(HTTPClient &http, String key, int skip, int get) {
  bool found = false, look = false;
  int ind = 0;
  String ret_str = "";

  int len = http.getSize();
  char char_buff[1];
  WiFiClient * stream = http.getStreamPtr();
  while (http.connected() && (len > 0 || len == -1)) {
    size_t size = stream->available();
    if (size) {
      int c = stream->readBytes(char_buff, ((size > sizeof(char_buff)) ? sizeof(char_buff) : size));
      if (len > 0)
        len -= c;
      if (found) {
        if (skip == 0) {
          ret_str += char_buff[0];
          get --;
        } else
          skip --;
        if (get <= 0)
          break;
      }
      else if ((!look) && (char_buff[0] == key[0])) {
        look = true;
        ind = 1;
      } else if (look && (char_buff[0] == key[ind])) {
        ind ++;
        if (ind == key.length()) found = true;
      } else if (look && (char_buff[0] != key[ind])) {
        ind = 0;
        look = false;
      }
    }
  }
  return ret_str;
}

You can call this getValue() whatever many times you like, but the strings you're looking for need to be only after each other, because the response to GET is read byte-by-byte just once.
There is probably (i.e., most likely) a better way of doing this, but this approach works and it's pretty fast, so...

* This, of course, is just an example, and you can overload this getValue() function definition to, say, read until it gets a curly bracket or whatever.

Check out the Streaming JSON Parser. It's designed to parse large JSON objects on processors with little memory. You'll just read one character at a time from the HTTP connection rather than the whole response; pass the character to the library and it'll call code you provide every time it sees an array, object, key or value. Then you can extract just the pieces you want without the overhead of loading it all in memory at once.
The library has good examples that'll show you how to use it.

Thanks, I've seen this before, but I'm not completely sure how this works. (a) In the example, in ESP.getFreeHeap(), is ESP the software serial instance? (b) What should I actually feed to the parse.parse(...)? Is it the http.getString() return?

ESP.getFreeHeap() is a diagnostic function. It returns how much memory is left to allocate. The example calls it to prove that the parser isn't leakimg or running out of memory. In the example it should be the same before and after running the parser. ESP is a special class with functions for dealing with the ESP8266 processor. You don't need to deal with any of the ESP functions. You need to read a single character at a time from your HTTP client and then feed each character to parse.parse().


text:
Arduino master/slave communication using RS485
I am using Arduino Uno as a Master Device and 3 Arduino Unos as slave devices.
I am sending data from each slave to master after every 3 seconds continuously, and is going to execute further logic accordingly.
I have been using a lot of libraries to test this scenario.
There are libraries which are using SoftwareSerial and HardwareSerial too, but these libraries are not working for me when i have multiple slaves and one master (It is only working with one master and one slave).
Please suggest me a better library which would be useful in my scenario.
Wiring Diagram:

addressing the slaves is on you. or use ModbusRTU

@Juraj : any particular library?

You need to implement one of automation protocols or write your own. https://en.wikipedia.org/wiki/List_of_automation_protocols

have you got any answer to solve this case? I am working to build system like this, but it is still not doing well :(

@Adwin not yet. what about you.. please let me know if u get anything.

First of all, your connection is just wrong, you should make the RS-485 bus as a straight line, with a 120 ohm resistor at the beginning and another one at the end. Each slave should tap into that line as close as possible to that line, look for datasheets and you will understand what I am talking about.
Second, you can use Modbus as a pretty good and easy to use communication protocol.

hey thanks for the reply on such old post.
which datasheet i shall exactly look into??

Max485 is a classic, probably has it, if not, look for Application Notes on RS-485, TI has good material on this.

And the post is not old, just half a year, I have seen a lot worse than that. Don't forget to accept if it answers.

RS485 module has resistor 120 Ohm inside


text:
How can I use my sim808 as Both GPS and GSM module for this code
#include<LiquidCrystal.h>
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

#include <SoftwareSerial.h>
SoftwareSerial gps(10,11); // RX, TX

//String str="";
char str[70];
String gpsString="";

char *test="$GPGGA";

String latitude="No Range      ";
String longitude="No Range     ";

int temp=0,i;
boolean gps_status=0;

void setup()
{
  lcd.begin(16,2);
  Serial.begin(9600);
  gps.begin(9600);

  lcd.print("Vehicle Tracking");
  lcd.setCursor(0,1);
  lcd.print("    System      ");
  delay(2000);
  gsm_init();
  lcd.clear();
  Serial.println("AT+CNMI=2,2,0,0,0");
  lcd.print("GPS Initializing");
  lcd.setCursor(0,1);
  lcd.print("  No GPS Range  ");
  get_gps();
  delay(2000);
  lcd.clear();
  lcd.print("GPS Range Found");
  lcd.setCursor(0,1);
  lcd.print("GPS is Ready");
  delay(2000);
  lcd.clear();
  lcd.print("System Ready");
  temp=0;
}

void loop()
{
  serialEvent();
  if(temp)
  {
    get_gps();
    tracking();
  }
}

void serialEvent()
{
  while(Serial.available())
  {
    if(Serial.find("Track Vehicle"))
    {
      temp=1;
      break;
    }
    else
    temp=0;
  }
}

void gpsEvent()
{
  gpsString="";
  while(1)
  {
   while (gps.available()>0)            //checking serial data from GPS
   {
    char inChar = (char)gps.read();
     gpsString+= inChar;                    //store data from GPS into gpsString
     i++;
     if (i < 7)
     {
      if(gpsString[i-1] != test[i-1])         //checking for $GPGGA sentence
      {
        i=0;
        gpsString="";
      }
     }
    if(inChar=='\r')
    {
     if(i>65)
     {
       gps_status=1;
       break;
     }
     else
     {
       i=0;
     }
    }
  }
   if(gps_status)
    break;
  }
}

void gsm_init()
{
  lcd.clear();
  lcd.print("Finding Module..");
  boolean at_flag=1;
  while(at_flag)
  {
    Serial.println("AT");
    while(Serial.available()>0)
    {
      if(Serial.find("OK"))
      at_flag=0;
    }

    delay(1000);
  }

  lcd.clear();
  lcd.print("Module Connected..");
  delay(1000);
  lcd.clear();
  lcd.print("Disabling ECHO");
  boolean echo_flag=1;
  while(echo_flag)
  {
    Serial.println("ATE0");
    while(Serial.available()>0)
    {
      if(Serial.find("OK"))
      echo_flag=0;
    }
    delay(1000);
  }

  lcd.clear();
  lcd.print("Echo OFF");
  delay(1000);
  lcd.clear();
  lcd.print("Finding Network..");
  boolean net_flag=1;
  while(net_flag)
  {
    Serial.println("AT+CPIN?");
    while(Serial.available()>0)
    {
      if(Serial.find("+CPIN: READY"))
      net_flag=0;
    }
    delay(1000);
  }
  lcd.clear();
  lcd.print("Network Found..");
  delay(1000);
  lcd.clear();
}

void get_gps()
{
   gps_status=0;
   int x=0;
   while(gps_status==0)
   {
    gpsEvent();
    int str_lenth=i;
    latitude="";
    longitude="";
    int comma=0;
    while(x<str_lenth)
    {
      if(gpsString[x]==',')
      comma++;
      if(comma==2)        //extract latitude from string
      latitude+=gpsString[x+1];
      else if(comma==4)        //extract longitude from string
      longitude+=gpsString[x+1];
      x++;
    }
    int l1=latitude.length();
    latitude[l1-1]=' ';
    l1=longitude.length();
    longitude[l1-1]=' ';
    lcd.clear();
    lcd.print("Lat:");
    lcd.print(latitude);
    lcd.setCursor(0,1);
    lcd.print("Long:");
    lcd.print(longitude);
    i=0;x=0;
    str_lenth=0;
    delay(2000);
   }
}

void init_sms()
{
  Serial.println("AT+CMGF=1");
  delay(400);
  Serial.println("AT+CMGS=\"+91**********\"");   // use your 10 digit cell no. here
  delay(400);
}

void send_data(String message)
{
  Serial.println(message);
  delay(200);
}

void send_sms()
{
  Serial.write(26);
}

void lcd_status()
{
  lcd.clear();
  lcd.print("Message Sent");
  delay(2000);
  lcd.clear();
  lcd.print("System Ready");
  return;
}

void tracking()
{
    init_sms();
    send_data("Vehicle Tracking Alert:");
    send_data("Your Vehicle Current Location is:");
    Serial.print("Latitude:");
    send_data(latitude);
    Serial.print("Longitude:");
    send_data(longitude);
    send_data("Please take some action soon..\nThankyou");
    send_sms();
    delay(2000);
    lcd_status();
}![enter image description here](https://i.stack.imgur.com/S5fc6.jpg)

The code is for two different modules a gsm and a GPS but I want to use the Sim 808 module with built in gps and gsm. What do I have to change in the code?

please add the question to the post above ...... also use the {} button to format the code


text:
Trying to install amforth on Leonardo board
Just got a Arduino Leonardo (with headers) dropped in my lap this week. I've tried experimenting with the Arduino C++ IDE and find it awkward. I have some previous experience with Forth and would like to try loading amforth directly onto the ATmega32u4 microcontroller.
I found some "how to" information on the web but find it confusing and contradictory. Can anyone point to some easy to follow instructions? I'd greatly appreciate it!
In case it matters, my development box is a Fedora 29 workstation.

what are easy to follow instructions? ..... which information did you find? .....  how was it contradictory?

https://arduino.stackexchange.com/questions/24969/amforth-on-arduino-uno

Instructions that make no assumptions about any experience with the board.

Oh BTW, I have but one Leonardo board and the example "wiring" diagram in the link above show 2 Leonardo boards. I assume that's not necessary to use amforth?


text:
Reading data from SPI on ESP32-WROOM-32
I'm newbie with Arduino and need to do a short task: read data from SPI (sent by another microcontroller) and send to WiFi (by ESP32-WROOM-32).
I can't understand how to initialize and read data from SPI. I'm using VSPI. I need to use VSPI class? Or a SPI class?
Any idea will help me a lot.
Thanks

can you use uart instead? it's a lot simpler...

@dandavis unfortunately no

ESP-32 is not an Arduino

@Juraj you are correct, but ESP-32 can be programmed with Arduino IDE and arduino code

do you use the Arduino IDE and the ESP32 Arduino package?

Yes. WiFi part is running ok. The problem is SPI communication.

did you see the example of the SPI library?

I saw SPI_Multiple_Buses example. Is it?

yes, there is everything explained

In this example there is no SPI slave. Correct me if I'm wrong. I have a master microcontroller, who send me information on SPI bus. I need do read these information and put on WiFi (ESP-32) connection. In this case ESP-32 is the SPI slave. Right?

you didn't ask about slave mode. slave can send data to master (if the master requests them). esp32 arduino SPI slave library is not implemented yet


text:
Sending double data from Matlab to the Teensy 3.6 via the microUSB
I've been hitting against a wall for over a week now.  My current project is to use a Teensy 3.6 to send data over an SPI bus to a chip which is effective going to be a signal generator.  I've made a GUI in Matlab to control this function generator in 'real-time' by sending over values such as frequency and amplitude.  For my initial case, I just want to output a sine wave.  to do this I am using the built in math function sin and just getting the amplitude and frequency from Matlab.  However, when I send over my data I'm getting nothing on the output, but when I hard program in the values, it works just fine.  From this I assume I am not sending the data over correctly OR not converting it correctly upon receiving it.
My order of operations are:

send my variable to the Teensy 3.6 using fwrite in Matlab
serialID = serial('COM5','BaudRate',115200);
fopen(serialID);
val = 2.55;
fwrite(serialID, val, 'double');

receiving the data on the Teensy 3.6 using Serial.read()
byte temp[8];

for (int c = 0; c<8; c++){
    temp[c] =Serial.read();
}

converting my byte array to a double using a union
double byteToDouble(byte DoubleInBytes[8]) {
    //Receives 8 bytes values and return them into a double value

    union {
       double   Out;
       byte   In[8];
    } U ;

    for (int c = 0; c < 8; c++) {
        U.In[c] = DoubleInBytes[c];
    }

    return U.Out;
}

I'm at a loss as to what I might be doing wrong.  I've tried to use the serial monitor to monitor variable states but I can't use that while Matlab is using the COM port.
Any helpful tips would be appreciated.

Have you verified byte-order? And read when there is data available, i.e. check Serial.available().

Yes, they are both little endian.  And yes, I used Serial.available to see if data is available.  I'm currently reading in the data and sending back some debugging text to Matlab to see where I am in the code.  When I hard code the numbers in I actually still read in data but don't use it to get into the if(Serial.available()) portion of the code.

You mean if (Serial.available() >= 8).

I did write it wrong, but not >= 8 but rather if(Serial.available() > 0)  I just want to know something is ready to be pulled before starting.

I got a bit more traction on this issue on the Arduino forums and was able to answer it over there.  I'm posting the link here to complete this post with a working answer.  Hope it helps!
https://forum.arduino.cc/index.php?topic=598595.new#new
Thanks!


text:
Problem with a code
I have one problem with my code and I'm a beginner and I can't solve it. Can you help me? Thank you so much.
I have this problem:
error: expected unqualified-id before '{' token

And this is my code:
int trigPin = 12;
int echoPin = 11;
long timeperiod, cm;
const int analogOutPin = 9;
int brightness;

void setup()
{
  Serial.begin(9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop(){

  if (timeperiod > 50)
  analogWrite(analogOutPin,0);
}
{

  if (timeperiod 10 < 50){
  for(brightness = 0; brightness < 256; brightness++){
    analogWrite(led,brightness);
    delay(10);}
}}
  if (timeperiod < 10)
  analogWrite(analogOutPin,0);

{
  digitalWrite(trigPin, LOW);
  delayMicroseconds(20);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(0);
  digitalWrite(trigPin, LOW);

  timeperiod = pulseIn(echoPin, HIGH);

  cm = microsecondsToCentimeters(timeperiod);
  Serial.print("dist=");
  Serial.print(cm);
  Serial.println();

  delay(10);
}
long microsecondsToInches(long microseconds)
{
  return microseconds / 74 /2;
}
  long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29/ 2;
}

Sort out your indenting and you will find that the brackets you have don't make any sense.

The only problem I can see in your code is that your code modules are starting and ending anywhere. See from where till where you want to run a particular line of code. If you writing this code on arduino IDE you will be able to see which the ending of a particular bracket when you keep the cursor on one.

For example, the first 5 lines:
void loop(){

  if (timeperiod > 50)
  analogWrite(analogOutPin,0);
}
{

Always align your braces, you can do it like this:
 xxx {
    yyy
 }

or
 xxx
 {
    yyy
 }

where xxx and yyy can be one or more statements.
If you align the first 5 lines correctly, you see you should add a {:
if (timeperiod > 50)
{ // <- added
    analogWrite(analogOutPin,0);
}

Also, if you have an if, for or while statement, ALWAYS add brackets, even if it is only one line. Thus:
if (timeperiod > 50)
    analogWrite(analogOutPin,0);

should be written as
if (timeperiod > 50)
{
    analogWrite(analogOutPin,0);
}

This is not a mandatory rule, but if you later misindent something, or add a new line in the body, it is easily forgotten to add the brackets, so you better can do it beforehand.
So (also), it is wise to

align brackets (like explained above)
always use brackets in if/while/loop statements.
always use the same amount of spaces (or a tab) to indent a new level (e.g. after an if, while, loop, or the body of a function).
use new lines between functions; this makes it much easier to read
split up big functions with many brackets, in (sub) functions/methods (not in your case, yet)

Thank you for the answer. I did all of this and it says that I have the same mistake!

@jupepi Edit your question and post your new, aligned and clean code.

I don't see your code changes yet.

Your problems start here:
void loop(){

  if (timeperiod > 50)
  analogWrite(analogOutPin,0);
}
{

You are missing an opening brace for your if statement, and then have an extra opening brace afterwords. Also, any code inside braces should be indented from the code before it:
void loop(){

  if (timeperiod > 50) {
    analogWrite(analogOutPin,0);
  }

  if (timeperiod 10 < 50){
    for(brightness = 0; brightness < 256; brightness++) {
      analogWrite(led,brightness);
      delay(10);
    }
  }
  //And the rest of your loop function also needs cleanup...

The rest of your loop function needs cleanup as well. You've got bad indentation and mismatched braces all over the place. As @Majenko says in their comment, if you clean up your code formatting then your syntax problems will be obvious.


text:
Arduino IDE + ESP32 Webserver - how to redirect to root after click on button
I'm trying to use ESP32 + Arduino IDE to control a relay.
I've started by using the  library and the code below.
The problem I'm having:
after clicking on the button and activating the pin, if the browser is left like this, and then the page gets refreshed by mistake, the action will be repeated.
What I thought might help, is if for any click on the button, the pin activates, and then I get a redirect back to the root of the page. so refreshing will not pose any issue.
I've searched allover the internet and could not find anything conclusive, except for this piece of code, which doesnt seem to make any difference nomatter where I place it in the main code
client.println("HTTP/1.1 307 Temporary Redirect");
client.println("Location: /");
client.println("Connection: Close");
client.println();
client.stop();

and this is the main code:
// Load Wi-Fi library
#include <WiFi.h>

// Replace with your network credentials
const char* ssid     = "WalrusnTiny";
const char* password = "994483329I";

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";

// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;

void setup() {

  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);
  digitalWrite(output27, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients

  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            if (header.indexOf("GET /26/on") >= 0) {
              client.println();
              output26State = "on";
              digitalWrite(output26, HIGH);

            } else if (header.indexOf("GET /26/off") >= 0) {
              Serial.println("GPIO 26 off");
              output26State = "off";
              digitalWrite(output26, LOW);

            } else if (header.indexOf("GET /27/on") >= 0) {
              Serial.println("GPIO 27 on");
              output27State = "on";
              digitalWrite(output27, HIGH);

            } else if (header.indexOf("GET /27/off") >= 0) {
              Serial.println("GPIO 27 off");
              output27State = "off";
              digitalWrite(output27, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html>");
            client.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("");

            // Web Page Heading
            client.println("
ESP32 Web Server
");
            // Display current state, and ON/OFF buttons for GPIO 26
            client.println("
GPIO 26 - State " + output26State + "
");
            // If the output26State is off, it displays the ON button
            if (output26State=="off") {
              client.println("
<button class=\"button\">ON</button>
");
            } else {
              client.println("
<button class=\"button button2\">OFF</button>
");
            }

            // Display current state, and ON/OFF buttons for GPIO 27
            client.println("
GPIO 27 - State " + output27State + "
");
            // If the output27State is off, it displays the ON button
            if (output27State=="off") {
              client.println("
<button class=\"button\">ON</button>
");
            } else {
              client.println("
<button class=\"button button2\">OFF</button>
");
            }
            client.println("");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable

    header = "";
    // Close the connection

    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

Any help would be greatly appreciated.
Thank you in advance.

Solved:
Just needed to add this code to every button press,
 client.print("");
 client.print("<meta http-equiv=\"refresh\" content=\"0;url=/\">");
 client.print("");

First probably mention this is too much overhead for a webserver
adding
include <WebServer.h>

you can handle those endpoints easily
See https://lastminuteengineers.com/creating-esp32-web-server-arduino-ide/
Basically:
setup() {
  ...
  server.on("/", handle_OnConnect);
  server.on("/led1on", handle_led1on);
  server.on("/led1off", handle_led1off);
  server.on("/led2on", handle_led2on);
  server.on("/led2off", handle_led2off);
  server.onNotFound(handle_NotFound);

  server.begin();
  Serial.println("HTTP server started");
}

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

void handle_led1on() {
  LED1status = HIGH;
  Serial.println("GPIO4 Status: ON");
  server.send(200, "text/html", SendHTML(true,LED2status));
}

Anyway this is still wrong, as you end with same problem, /led1on renders as your main page
A better solution would be to use this endpoint handlers to set the variable and just redirect:
Here a complete solution
#include <WiFi.h>
include <WebServer.h>

// Replace with your network credentials
const char* ssid = "SSID";
const char* password = "password";

// Set web server port number to 80
WebServer server(80);

uint8_t led1Pin = 12;
uint8_t led2Pin = 13;

bool led1State = LOW;
bool led2State = LOW;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  // Set outputs to LOW
  led1State = LOW;
  led2State = LOW;
  digitalWrite(led1Pin, led1State);
  digitalWrite(led2Pin, led2State);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handle_root);
  server.on("/led/1/on", handle_led1on);
  server.on("/led/1/off", handle_led1off);
  server.on("/led/2/on", handle_led2on);
  server.on("/led/2/off", handle_led2off);
  server.onNotFound(handle_NotFound);

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

void handle_root() {
  server.send(200, "text/html", sendHTML());
}

void handle_led1on() {
  led1State = HIGH;
  Serial.println("led1 state: ON");
  server.sendHeader("Location", "/",true);
  server.send(302, "text/plain", "");
}

void handle_led1off() {
  led1State = LOW;
  Serial.println("led1 state: OFF");
  server.sendHeader("Location", "/",true);
  server.send(302, "text/plain", "");
}

void handle_led2on() {
  led2State = HIGH;
  Serial.println("led2 state: ON");
  server.sendHeader("Location", "/",true);
  server.send(302, "text/plain", "");
}

void handle_led2off() {
  led2State = LOW;
  Serial.println("led2 state: OFF");
  server.sendHeader("Location", "/",true);
  server.send(302, "text/plain", "");
}

void handle_NotFound() {
  server.send(404, "text/html", sendPageUnknown());
}

String sendPageUnknown() {
    String ptr = "<!DOCTYPE html> \n";

  ptr += "";

  ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";
  //ptr += "<meta http-equiv=\"refresh\" content=\"0;url=/\">";

  ptr += "<title>Page unknown</title>\n";

  ptr += "\n";

  ptr += "\n";
  ptr += "
Page unknown
\n";

  ptr += "Return to main page\n";

  ptr += "\n";
  ptr += "\n";
  return ptr;
}

String sendHTML() {
  digitalWrite(led1Pin, led1State);
  digitalWrite(led2Pin, led2State);

  String ptr = "<!DOCTYPE html> \n";

  ptr += "";

  ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";

  ptr += "<title>LED Dashboard</title>\n";

  ptr += "\n";
  ptr += "\n";

  ptr += "\n";
  ptr += "
ESP32 Web Server
\n";

  if (led1State)
  {
    ptr += "
LED1: ON
OFF\n";
  }
  else
  {
    ptr += "
LED1: OFF
ON\n";
  }

  if (led2State)
  {
    ptr += "
LED2: ON
OFF\n";
  }
  else
  {
    ptr += "
LED2: OFF
ON\n";
  }

  ptr += "\n";
  ptr += "\n";
  return ptr;
}

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

Even that is suboptimal, as led endpoints shouldn't be GET endpoints but POST (really PUT as it only updates info, but let's stick to POST for simplicity)
Here a version using POST and unique endpoint /led to handle any number of less to manage:
#include <WebServer.h>

// Replace with your network credentials
const char* ssid = "SSID";
const char* password = "password";

// Set web server port number to 80
WebServer server(80);

uint8_t led1Pin = 12;
uint8_t led2Pin = 13;

bool led1State = LOW;
bool led2State = LOW;

void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  // Set outputs to LOW
  led1State = LOW;
  led2State = LOW;
  digitalWrite(led1Pin, led1State);
  digitalWrite(led2Pin, led2State);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  server.on("/", handle_root);
  server.on("/led", HTTP_POST, handle_led);
  server.onNotFound(handle_NotFound);

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

void handle_root() {
  server.send(200, "text/html", sendHTML());
}

uint8_t evaluate_led_state(String ledState) {
  uint8_t state;
  if (ledState == "on") {
    Serial.println("led state: ON");
    state = HIGH;
  } else if (ledState == "off") {
    Serial.println("led state: OFF");
    state = LOW;
  } else {
    Serial.println("unknow led state: "+ledState);
  }
  return state;
}

void handle_led() {
  String ledPin = server.arg("ledPin");
  String ledState = server.arg("ledState");

  if (ledPin == "1") {
    Serial.println("setting led1");
    led1State = evaluate_led_state(ledState);
  } else if (ledPin == "2") {
    Serial.println("setting led2");
    led2State = evaluate_led_state(ledState);
  } else {
    Serial.println("led unknow: "+ledPin);
  }
  server.sendHeader("Location", "/",true);
  server.send(302, "text/plain", "");
}

void handle_NotFound() {
  server.send(404, "text/html", sendPageUnknown());
}

String sendPageUnknown() {
    String ptr = "<!DOCTYPE html> \n";

  ptr += "";

  ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";

  ptr += "<title>Page unknown</title>\n";

  ptr += "\n";

  ptr += "\n";
  ptr += "
Page unknown
\n";

  ptr += "Return to main page\n";

  ptr += "\n";
  ptr += "\n";
  return ptr;
}

String build_led_form(String ledPin, uint8_t ledState) {
  String ptr = "<form action=\"led\" method=\"post\">\n";
  ptr += "  <input type=\"hidden\" name=\"ledPin\" value=\""+ledPin+"\">\n";

  String ledStateStr;

  if (ledState)
  {
    ledStateStr = "off";
  }
  else
  {
    ledStateStr = "on";
  }

  ptr += "  <input type=\"hidden\" name=\"ledState\" value=\""+ledStateStr+"\">\n";
  ptr += "  Led"+ledPin+"\n";
  ptr += "  <input type=\"submit\" class=\"button button-"+ledStateStr+"\" value=\"";
  ledStateStr.toUpperCase();
  ptr += ledStateStr+"\">\n";

  ptr += "</form>\n";
  return ptr;
}

String sendHTML() {
  digitalWrite(led1Pin, led1State);
  digitalWrite(led2Pin, led2State);

  String ptr = "<!DOCTYPE html> \n";

  ptr += "";

  ptr += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, user-scalable=no\">\n";

  ptr += "<title>LED Dashboard</title>\n";

  ptr += "\n";
  ptr += "\n";

  ptr += "\n";
  ptr += "
ESP32 Web Server
\n";

  ptr += build_led_form("1", led1State);
  ptr += build_led_form("2", led2State);

  ptr += "\n";
  ptr += "\n";
  return ptr;
}

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

For non trivial management you probably want to use spiffs
https://randomnerdtutorials.com/esp32-web-server-spiffs-spi-flash-file-system/


text:
Image Processing
I have a project I am working on where I need to check the pressure on a gauge using a camera. I am familiar with a little openCV programming using a laptop webcam. However, for this application, I need to use a camera and a micro-controller. The camera needs to take a picture of the pressure gauge and check if it is between certain values. If it is so, the micro-controller sends a true or a false to a PLC. The first thought I had was to use an Arduino because the software is easily available as well as easy to use. However, an Arduino may not have the image processing capability is what I read online. Can someone please suggest a micro-controller suitable for this application. Also, is it possible to send signals to a PLC from the micro-controller?

Not really the right place to post this question - Stackoverflow or RaspberryPi or Arduino sites SO sites would be more appropriate.

What is the distance to the pressure gauge? You could be able to detect the thresholds another way?

However, an Arduino may not have the image processing capability is what I read online.

Correct. An 8-bit Arduino cannot store a big enough image and process it.

Can someone please suggest a micro-controller suitable for this application.

One of the 32-bit offerings from Arduino or any of the many third-party board makers (Teensy, chipKIT, STM32, etc) may be up to the job.
Your main concern will be memory (RAM). The more memory you have the bigger the image you can store and process.
The actual processing will probably be simple enough if the colours of the different things are obvious enough - for instance if the pointer is red and the background (in the target area) is black, then if there is red within the target area the pointer is there.

Also, is it possible to send signals to a PLC from the micro-controller?

Probably. That all depends on how the PLC communicates.

If you want to use and Arduino (even if faster chip with more RAM would be better), there is an option: the small camera module Ov7670 is available in two versions. One just take pictures get them and send them immediatly which is a big challenge in terme of time and will certainly not give you enought time to analyse but the "FIFO" version of the Ov7670 has a buffer in which the module store the image.
So you can ask it to "take a photo" and then you have time to get the data.
Of course, it's impossible to retrieve the full picture and you'll have to check it pixel per pixel or maybe line per line.

I recommend using a Raspberry Pi or perhaps Arduino Yun for this project. They are both Linux computers and will have much more processing power to do image processing.
I'm sure there's a way to send signals into a PLC, but I don't know how PLCs communicate, and you haven't provided any user manuals or data sheets for one, so I can't explain any details at this time.


text:
Unusual use of << operator... not a bit shift?
Poking through the example code of SDFS, I saw the following:
static ArduinoOutStream cout(Serial);
// F stores strings in flash to save RAM
cout << F("\ntype any character to start\n");

What exactly is << doing in this case? Moreover, F seems to never be defined prior to this. This seems like a useful trick, but I don't understand how it works.
full code available here: https://github.com/greiman/SdFs/blob/master/examples/SdInfo/SdInfo.ino

What exactly is << doing in this case?

It's directing the data into an output device (stream).

http://www.cplusplus.com/doc/tutorial/basic_io/

Yes, it's confusing using the same symbols for more than one thing...

Moreover, F seems to never be defined prior to this.

F() is a macro. It's defined by the Arduino core in WString.h:
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

Thank you. Your last line there uses the < and > symbols in ways I've never seen as well, along with the pointer. These seem not to be logical or arithmetic operators, so what do I call them in a google search to understand your answer?

@BoThompson those are template

Compared to the < logical operator and the < arithmetic operator, what would you call that set of symbols?

To address your confusion with the bitshift operator;
It indeed is commonly used as a the arithmetic operator for bitshift, but appears to be 'overloaded', so that when used with streams, it is an 'insertion operator'.

In particular, stream insertion and stream extraction overloads of
  operator<< and operator>> return T&.

https://en.cppreference.com/w/cpp/language/operator_arithmetic
Basically there would be two definitions of the "<<" operator function:
function <<(integer){//Shift bits}
function <<(stream){//Join streams}