message:
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:
<!-- language-all: lang-cpp -->
```
#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?

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


sender: user

sender: assistant

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


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


message:
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][1]
but it seems that i don't know how to use it...

[![results][2]][2]

[![my code][3]][3]

  [1]: https://github.com/ivanseidel/DueTimer
  [2]: https://i.stack.imgur.com/9KUXI.png
  [3]: https://i.stack.imgur.com/4inEf.png

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


message:
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?

body:
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);


message:
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.[![enter image description here][1]][1]
Please suggest where I go wrong.

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

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


message:
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?

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


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

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

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.

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


message:
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?

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


message:
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!

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


body:
Yes, there is an [Optiboot fork supporting ATmega32U4](https://github.com/dmjlambert/optiboot) supporting hardware UART to upload Arduino sketches.

Also, a detailed [instructable post explaining how to use it](https://www.instructables.com/id/How-to-upload-sketches-to-Pro-MicroLeonardo-via-se/) with Arduino Pro Micro.


body:
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 https://arduino.stackexchange.com/questions/1477/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.


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

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

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][3] 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.

  [1]: https://www.ixysiss.com/ncd2400
  [2]: https://i.stack.imgur.com/gQSjT.png
  [3]: https://electronics.stackexchange.com/questions/417263/multiple-instances-of-same-device-on-i2c-bus

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

 1. 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.
 2. 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.
 3. 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][2]

  [1]: https://electronics.stackexchange.com/questions/417263/multiple-instances-of-same-device-on-i2c-bus
  [2]: http://www.gammon.com.au/i2c


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


message:
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][1] (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][2] 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?

  [1]: https://store.arduino.cc/arduino-leonardo-with-headers
  [2]: https://www.intorobotics.com/pick-right-bluetooth-module-diy-arduino-project/

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


message:
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:

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

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.

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

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


body:
Have you tried some hardware denouncers - like [MC14490](https://www.onsemi.com/pub/Collateral/MC14490-D.PDF)?
Using Interrupts you can then detect all four phases of each encoder step.


message:
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:

1. 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?
2. Is there a way to limit the response?
3. 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?
4. 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][1]).

  [1]: https://cdn.instructables.com/FE9/58ZS/IJX7FON7/FE958ZSIJX7FON7.LARGE.jpg?auto=webp

body:
Check out the [Streaming JSON Parser][1]. 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.

  [1]: https://github.com/squix78/json-streaming-parser


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


message:
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:**
[![Wiring Diagram][1]][1]

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

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


body:
RS485 module has resistor 120 Ohm inside

[![RS485 module diagram][1]][1]

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


message:
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;
    }

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


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


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


message:
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 <WiFi.h> 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.

body:
Solved:

Just needed to add this code to every button press,

     client.print("<HEAD>");
     client.print("<meta http-equiv=\"refresh\" content=\"0;url=/\">");
     client.print("</head>");


body:
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> <html>\n";

  ptr += "<head>";

  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 += "</head>\n";

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

  ptr += "<a href=\"/\">Return to main page</a>\n";

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

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

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

  ptr += "<head>";

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

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

  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
  ptr += ".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;padding: 13px 30px;text-decoration: none;font-size: 25px;margin: 0px auto 35px;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button-on {background-color: #3498db;}\n";
  ptr += ".button-on:active {background-color: #2980b9;}\n";
  ptr += ".button-off {background-color: #34495e;}\n";
  ptr += ".button-off:active {background-color: #2c3e50;}\n";
  ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";

  ptr += "<body>\n";
  ptr += "<h1>ESP32 Web Server</h1>\n";

  if (led1State)
  {
    ptr += "<p>LED1: ON</p><a class=\"button button-off\" href=\"/led/1/off\">OFF</a>\n";
  }
  else
  {
    ptr += "<p>LED1: OFF</p><a class=\"button button-on\" href=\"/led/1/on\">ON</a>\n";
  }

  if (led2State)
  {
    ptr += "<p>LED2: ON</p><a class=\"button button-off\" href=\"/led/2/off\">OFF</a>\n";
  }
  else
  {
    ptr += "<p>LED2: OFF</p><a class=\"button button-on\" href=\"/led/2/on\">ON</a>\n";
  }

  ptr += "</body>\n";
  ptr += "</html>\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> <html>\n";

  ptr += "<head>";

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

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

  ptr += "</head>\n";

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

  ptr += "<a href=\"/\">Return to main page</a>\n";

  ptr += "</body>\n";
  ptr += "</html>\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 += "  <label>Led"+ledPin+"</label>\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> <html>\n";

  ptr += "<head>";

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

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

  ptr += "<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
  ptr += "body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;} form {margin-bottom: 30px;}\n";
  ptr += ".button {display: block;width: 80px;background-color: #3498db;border: none;color: white;text-decoration: none;font-size: 25px;margin: auto;cursor: pointer;border-radius: 4px;}\n";
  ptr += ".button-on {background-color: #3498db;}\n";
  ptr += ".button-on:active {background-color: #2980b9;}\n";
  ptr += ".button-off {background-color: #34495e;}\n";
  ptr += ".button-off:active {background-color: #2c3e50;}\n";
  ptr += "p {font-size: 14px;color: #888;margin-bottom: 10px;}\n";
  ptr += "</style>\n";
  ptr += "</head>\n";

  ptr += "<body>\n";
  ptr += "<h1>ESP32 Web Server</h1>\n";

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

  ptr += "</body>\n";
  ptr += "</html>\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/


message:
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?

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


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


message:
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

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


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


message:
Will a simple RC filter work with my mechanical rotary encoder, or do I need a Schmitt trigger?

I bought some incremental rotary encoders online  https://www.bourns.com/docs/Product-Datasheets/PEC12R.pdf

The spec sheet for those suggests a filter circuit for the outputs of the encoder that looks like this:

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

Adding that filter reduces, but doesn't eliminate, spurious signals from the encoder. I wanted to avoid adding Schmitt triggers or other solid state components since I don't have a lot of room left on my proto board for an IC, but I'm beginning to think I will have to add something with hysteresis since any filter that reduces jitter will also slow the rise time/fall time for the output of the encoder and keep it in the "gray area" between LOW and HIGH for a digital signal for too long.

Is there a way to wire these encoders and/or software that lets you read from them with simple passive filtering and/or software rather than adding something like a latch or Schmitt trigger for debouncing?

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

body:
The answer seems to be no. I added the RC filter suggested by the manufacturer and the results still jump around (The values sometimes increase by several steps at once, or decrease even when turning the decoder clockwise.)

I added a CMOS Schmitt trigger and it resolves the problem.

I really don't understand why that is, since apparently Arduino digital inputs have integrated Schmitt triggers. This thread from the Arduino forum discusses it at length:

http://forum.arduino.cc/index.php?topic=452599.15

The only thing I can think of is that the hysteresis band of the built-in Schmitt triggers is too narrow (2.08 - 2.63V at VCC of 5V and typical operating conditions) and the filtered voltage still bounces between those values.

I'm using a MC14584B Schmitt trigger that I had lying around, and it looks like it's hysteresis band is ≈2.1V to 2.7V (typical at 25°C) which is slightly wider and goes slightly higher than the hysteresis range of the Arduino itself.

The differences seem quite small though, so I'm confused as to why the Schmitt trigger eliminates the "bobbling" of values I'm seeing.

I could add delay based debouncing code to my Arduino program, but the decoder handler is written as an ISR and those are supposed to be as fast as possible, and the millis() function is supposed to be quite slow, making it difficult.

## EDIT:

I asked a related question regarding filter component values on the EE stack exchange, and somebody there pointed out that I should only be seeing "bounce" on one pin at a time, and that I should be able to reject spurious changes purely through software. I'm trying to do that now.

My new code looks like this:

    bool rotaryValueChanged = false;

    bool pinAHasChanged = false;
    bool pinBHasChanged = false;

    enum ChangeTypes {
      fallingA,
      changingA,
      changingAOrB
      };
    ChangeTypes changesToDetect = fallingA;

    void encode() {
      pinAHasChanged = 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;
      //Ignore state changes to pinA unless pinB has changed since the last change.
      //Also only pay attention if this is a falling edge
      //or we're tracking both rising and falling edge changes
      if (pinBHasChanged && (pinAState == false || changesToDetect != fallingA)) {
        rotaryValue +=  (pinAState == pinBState) ? -1 : 1;
        rotaryValueChanged = true;
        pinBHasChanged = false;
      }
    }

    void encodePinB() {
      pinBHasChanged = true;

      //Unless we're counting 48 ticks/rotation, don't count PinB changes.
      if (changesToDetect != changingAOrB) {
        return;
      }
      //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;

      //Ignore state changes to pinB unless pinA has changed since the last change
      if (pinAHasChanged) {
        rotaryValue +=  (pinAState != pinBState) ? -1 : 1;
        rotaryValueChanged = true;
      }
    }

    void setup() {
      attachInterrupt(digitalPinToInterrupt(rotaryPinA), encode, CHANGE);//FALLING
      attachInterrupt(digitalPinToInterrupt(rotaryPinB), encodePinB, CHANGE);
      //More setup code here...
    }

This code is written to handle 3 possible options:

  - Only falling edge state changes on pin A (12 steps/rotation)
  - Rising or falling changes on pin A (24 steps/rotation)
  - Rising or falling state changes on either pin (48 steps/rotation.)

The key part of this is to have interrupts on both pins. When one pin changes, its interrupt handler sets a "this pin changed" bool to true. In the ISR (Interrupt Service Routine) for the other pin, it only pays attention to a state change if the other pin has changed. That way, when Pin A changes states, if it bounces, the other pin should not bounce at the same time and so unless pin B has changed, I can simply ignore additional changes to Pin A and handle my debouncing in software, and without having to do timing delays which are too slow for an ISR.

However, the code above doesn't quite work. Sometimes I get bogus reverse rotation readings. If I'm rotating the encoder clockwise, the values I get increase one by one as expected, but occasionally decrement by 1 and then go back to incrementing.

What am I doing wrong?

Since the bouncing should only ever occur on one pin at a time, the above code **should** give correct readings from a bare rotary encoder without any hardware debouncing needed, but it doesn't.

My test case is only counting falling edge transitions for Pin A of my encoder, so picking up spurious counterclockwise rotation readings suggests that sometimes Pin B is changing state at the same time as pin B. That shouldn't happen, so I'm confused.


body:
First of all, I would question the usefulness of debouncing a rotary
encoder. I would expect to have contact bounce only when the contact is
transitioning from `HIGH` to `LOW` or vice-versa. At this transition
point, both the `HIGH` and `LOW` readings are in a sense correct. A
non-debounced reading should then display a rotary angle that briefly
changes back and forth between two _consecutive_ positions, with no
cumulative error.

I would suggest you forget about debouncing and just look at the state
changes. If you think you do need debouncing, handle it downstream, by
periodically querying the “raw” angle and updating the “debounced”
angle:

* if the raw angle is more than one unit apart from the debounced angle,
  bring this difference back to one unit.

* if the raw angle has not changed since a fixed count of milliseconds,
  then make the debounced angle equal to the raw angle.

Second point: you are not looking at the falling edged of input A, you
are looking at the rising edges. This is because `pinAState`
uses negative logic: it is `true` when the pin is `LOW`. It shouldn't
make a big difference though in terms of the logic of the code.

Third point: there is some flaw in your counting logic. I will not try
to analyze it in detail, as the whole debouncing concept you use does
not make sense to me, but only provide an example of how it can fail.
Let's assume the encoder is in the position where both inputs are `LOW`,
and you wiggle it a little bit so that each input, in turn, gives a
positive pulse, like this:

                    _       _       _       _       _       _
    input A      __/ \_____/ \_____/ \_____/ \_____/ \_____/ \_____
                        _       _       _       _       _       _
    input B      ______/ \_____/ \_____/ \_____/ \_____/ \_____/ \_

    rotaryValue      0     |   1   |   2   |   3   |   4   |   5

Here, `rotaryValue` is incremented on each rising edge of input A, save
for the very first one. In this case, the expected behavior is for this
variable to stay, say, within [−1, +1].


body:
Having just chased a problem using a software based debounce for several days, what I'll add is that for the encoders I was using (green no-name Chinese ones), if you put 10mA though the contacts then the signal is a LOT better.   So change the 10k to 470 Ohms.

Or if using 3.3V use 330 Ohms.  Solved all my problems.


message:
Is it possible to connect miband2 and arduino nano (?)

I want to make an IOT project using an Arduino nano and I need heart rate sensors. I I have a miband2. So, is it possible to connect them ?

body:
To use BLE on Arduino, I tried google and found this [Article][1]:

Examples:

- HM-10 (HM-11) BLE Module
- BLE Nano
- BLE Mini
- BLE Shield v2.1
- RFduino
- Bluno series
- BLE WT51822-ABS
- Grove – BLE
- BLEduino

Chose one that fits best, and use it.

  [1]: https://developex.com/blog/best-modules-shields-and-boards-for-ble-usage-on-arduino/


body:
You need to connect as a central device.
I've had good luck with the adafruit nrf52 feather.  Also see: https://github.com/Freeyourgadget/Gadgetbridge for the protocol.


message:
HC-05 bluetooth module

I was able to connect my HC-05, pair it with my phone, and I can see data in the Serial Bluetooth Terminal Android App.  But when I try to connect it to a certain application it says it cannot find it.  Can the application force a certain version of Bluetooth?  Am I missing something?  Thanks.

body:
The HC-05 modules use bluetooth 2.0. Certain apps would only be compatible with bluetooth 4.0 devices (BLE - Bluetooth Low Energy), such as an HM10 or AT09.

It could be that your app requires the device to use v4.0+. Are you able to find, and pair with the device using your android's default bluetooth device scanning/pairing features?

Assuming that your app does not require v4.0+, have you removed the connection from 'en'/'ch_pd' to 3.3v? If that was still connected (which is a required connection to enter AT command mode), then your bt module would not be able to accept incoming pair requests etc.

hope this has helped. :)


message:
Converting code for ATTINY85 to ATMEGA2560. Pin change interupts

I have code that compiles correctly for an ATTINY85 board using the ARDUINO IDE but I don't have an ATTINY85 board. I have an Arduino Mega ATMEGA2560 and when I select this board in the Arduino IDE the code does not compile and throws this error message

 sketch_feb21a:216:3: error: 'GIMSK' was not declared in this scope

    GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts

    ^

 sketch_feb21a:216:16: error: 'PCIE' was not declared in this scope

    GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts

                 ^

 sketch_feb21a:217:3: error: 'PCMSK' was not declared in this scope

    PCMSK |= _BV(PCINT2);                   // Use PB3 as interrupt pin

    ^

 exit status 1
 'GIMSK' was not declared in this scope

Here is the code snippet that throws the error

 void sleep()
 {
   GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
   PCMSK |= _BV(PCINT2);                   // Use PB3 as interrupt pin
   ADCSRA &= ~_BV(ADEN);                   // ADC off
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement

   MCUCR &= ~_BV(ISC01);
   MCUCR &= ~_BV(ISC00);       // Interrupt on rising edge
   sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
   sei();                                  // Enable interrupts
   sleep_cpu();                            // sleep

   cli();                                  // Disable interrupts
   PCMSK &= ~_BV(PCINT2);                  // Turn off PB3 as interrupt pin
   sleep_disable();                        // Clear SE bit
   ADCSRA |= _BV(ADEN);                    // ADC on

   sei();                                  // Enable interrupts
 }

 ISR(PCINT0_vect) {
    /*noInterrupts();
    while (digitalRead(BUTTON_PIN) == LOW);

    delay(50);
    while (digitalRead(BUTTON_PIN) == LOW);
    playTrack(1 + (curTrack++ % 2));
    delay(400);

    interrupts();*/

 }

body:
Each processor has different registers, things that control stuff like interrupts, input and output. I would not expect code written for one processor, especially if it directly accesses the registers, to work on another processor.

You would need to look at the datasheet for the Atmega2560 and see how to control its pin change interrupts.


message:
Define preset colors using FastLed library

I'm using an addressable 150 led strip and an Arduino Nano to control it, using `FastLed` library.

I'm tring do create a function `turn_on_leds`, which gets 4 parameters:

1) delay time for lighting a led in the loop, 2) direction ( not relevant for now), 3) color index for `colors` array , 4) brightness percentage.

**Problem #1**: a color array is defined to select from a preset definitions of colors ([Fastled reference][1], but when selecting `col_indx` =2, meaning `colors[2]`, leds are not lit in `Red` as they should, AND when setting `leds[i]=0xFF0000`, the right result is set.

**Problem #2**: at `loop` there is a for intended for raise bightness from 0 to 100, BUT the results are 0 for first iteration and 9 for all others.

Appreciate any HELP!!

Guy

Code:

    #include <FastLED.h>

    #define NUM_LEDS 10
    #define BRIGHTNESS  55
    #define DATA_PIN 7

    char *colors[] = {0x000000,0xFFFFFF,0xFF0000,0x008000,0x0000FF}; // black, white,r,g,b
    CRGB leds[NUM_LEDS];
    int t = 0;

    void setup() {
      Serial.begin(9600);
      FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
      //  FastLED.setBrightness(BRIGHTNESS);
    }

    void turn_leds_on(int del_1, bool dir_1, int col_indx, int bright_1) {
      if (dir_1 == true ) { // start to end
        for (int i = 0; i <= NUM_LEDS; i++) {
          leds[i] = 0xFF0000;//colors[col_indx];
          FastLED.setBrightness(bright_1*255/100);
          FastLED.show();
          delay(del_1);
        }
      }
    }

    void loop() {
      Serial.println(t);
      turn_leds_on(50, true, 2, 100);
      delay(1000);
      //  turn_leds_on(50, true, 0, t);
      //  delay(1000);

      if (t < 100 ) {
        t += 10;
      }
      else {
        t = 0;
      }
    }

  [1]: https://github.com/FastLED/FastLED/wiki/Pixel-reference

body:
Your `colors` array should be `CRGB` type, not `char *`.

    CRGB colors[] = {0x000000,0xFFFFFF,0xFF0000,0x008000,0x0000FF}; // black, white,r,g,b

For your second problem - you are overflowing the bounds of your LEDs array:

    for (int i = 0; i <= NUM_LEDS; i++) {
      leds[i] = 0xFF0000;//colors[col_indx];

You are going from 0 to 10 inclusive. That's 11 iterations. There is no such array slice as `leds[10]`, so the value you write to it ends up overwriting the next two bytes in memory - and those happen to be occupied by the variable `t`.


message:
if/else on digitalRead not executing on 'else' portion

I am a beginner with C++ but used to be good with BASIC (2 decades ago lol). I'm building a peristaltic metered doser that allows you to input desired mL on a 4x4 keypad and then when 'fill' button is pressed it doses the desired mLs through the peristaltic.

I'm still drafting/printing the peristaltic housing and all of that but in the meantime I want to get as much of the coding done as possible. It's still incomplete, but one of the functions I want the doser to have is a 'PRIME/FLUSH' button.

Originally I wanted the button to run the pump as long as the button is held down to prime the tubing with solution or flush the tubing with DI water. But I haven't had luck figuring out how to use a 4x4 button in momentary switch mode.

A workaround I had was to have the button be an on/off button. So press it once, pump turns on, press it again, pump turns off. Since the pump isn't printed yet I've been using the onboard LED as a tester for the coding (hence the LED_BUILTIN).

The issue, from my research I figured what I would need was an if/else statement. When the button is pressed (in this case the 'a' button), it reads the LED_BUILTIN status and if its HIGH it turns it off and if its LOW it turns it on.

But the 'if' part is working, it turns it on, but the 'else' part is not. When the LED is already on and the 'a' button is pressed, it stays on and doesn't rewrite to LOW.

Code below, any advice?

    #include <KeypadShield.h>

    KeypadShield keypad;

    #include <LiquidCrystal_I2C.h>
    #include <Wire.h>

    LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

    char Data[15];
    byte data_count = 0;

    int x;

    char customKey;

    void setup() {
      pinMode(LED_BUILTIN, OUTPUT);

      keypad.begin();
      lcd.begin(20,4);
        lcd.setCursor(4,0);
        lcd.print("Let's Fill!");
        lcd.setCursor(4,1);
        lcd.print("Designed by");
        lcd.setCursor(4,2);
        lcd.print("JP");
        lcd.setCursor(5,3);
        lcd.print("2019 v1.0");

        delay (2000);

        lcd.clear();

        lcd.setCursor(1,0);
        lcd.print("Enter volume in mL");
        lcd.setCursor(3,1);
        lcd.print("on keypad then");
        lcd.setCursor(5,2);
        lcd.print("press DONE");
        lcd.setCursor(0,3);
        lcd.print("mL:");
    }

    void softReset()
    {
    asm volatile ("  jmp 0");
    }

    void loop()
    {
        customKey = keypad.getNextKeypress();

        if (customKey)
        {
          if (customKey == 'a')
          {
            if (digitalRead(LED_BUILTIN == LOW))
            {
              digitalWrite(LED_BUILTIN, HIGH);
              lcd.clear();
              lcd.setCursor(5,1);
              lcd.print("FLUSHING");
            }
            else
            {
              digitalWrite(LED_BUILTIN, LOW);
              lcd.clear();
              lcd.setCursor(1,0);
              lcd.print("Enter volume in mL");
              lcd.setCursor(3,1);
              lcd.print("on keypad then");
              lcd.setCursor(5,2);
              lcd.print("press DONE");
              lcd.setCursor(0,3);
              lcd.print("mL:");
            }
          }

          if (customKey == 'd')
          {
           softReset();
          }

          if (customKey != 'p' && customKey != 'a' && customKey != 'b' && customKey != 'c' && customKey != 'd' && customKey != 's')
          {
            Data[data_count] = customKey; // store char into data array
            lcd.setCursor(data_count+3,4); // move cursor to show each new char
            lcd.print(Data[data_count]); // print char at said cursor
            data_count++; // increment data array by 1 to store new char, also keep track of the number of chars entered
            x = atoi (Data); //convert string to integer 'x' for use in equations
          }

         if (customKey == 'p')
          {
           lcd.clear();
           lcd.setCursor(7,0);
            lcd.print(x);
            lcd.setCursor(Data[data_count]+13,0);
            lcd.print("mL");
            lcd.setCursor(0,1);
            lcd.print("FILL --> fill");
            lcd.setCursor(0,2);
            lcd.print("RESET --> change mL");
            lcd.setCursor(0,3);
            lcd.print("FLUSH --> finish");

          }
        }
    };

body:
(Heh... before even seeing the code I guessed you'd done this...)

You are comparing a pin number, not the results of `digitalRead()`, and then passing the results of that comparison to `digitalRead()`:

    if (digitalRead(LED_BUILTIN == LOW))

It should read:

    if (digitalRead(LED_BUILTIN) == LOW)

Note the order of the brackets:  `LED_BUILTIN` is passed to `digitalRead()`, and then the result of calling that function is compared to the value `LOW`.


message:
Powering L298N drivers from mains power supply

I am powering 2 stepper motors with an L298N driver each (from a 9V 2A external power supply powered from the mains: https://www.amazon.co.uk/BERLS-Power-Adapter-Elegoo-Connectors/dp/B07GSM6YLX/ref=sr_1_5?ie=UTF8&qid=1550859082&sr=8-5&keywords=AC/DC+Power+Adapter+for+Arduino).

I am wondering how I can connect the driver 5V and GND pins to the power supply?

Thanks in advance!

body: You would not connect the +5V lead to the power supply. Connect the ground between the driver, the Arduino, and the power supply. Connect the 9V from the power supply to the driver. Connect the logic lines from the Arduino to the inputs on the driver.


body:
You'll need another supply, or a step-down supply for the 5v; same ground for all.

Also H-bridges are really inefficient to drive steppers, you should get a dedicate stepper driver.


message:
Accessing 2 dimensional array in PROGMEM inside loop

I am unable to access elements of a 2D PROGMEM array from inside a loop. Please see the following example:

    const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
    const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
    const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
    const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

    const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

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

      Serial.println(pgm_read_byte(&(arr[0][0])));
      Serial.println(pgm_read_byte(&(arr[1][0])));
      Serial.println(pgm_read_byte(&(arr[2][0])));
      Serial.println(pgm_read_byte(&(arr[3][0])));
      for (int i = 0; i < 4; i++) {
        Serial.print(i);
        Serial.print(":");
        Serial.println(pgm_read_byte(&(arr[i][0])));
      }
      int j = 0;
      Serial.println(pgm_read_byte(&(arr[j][0])));
      j = 1;
      Serial.println(pgm_read_byte(&(arr[j][0])));
      j = 2;
      Serial.println(pgm_read_byte(&(arr[j][0])));
      j = 3;
      Serial.println(pgm_read_byte(&(arr[j][0])));
    }

    void loop() {

    }

The output is:

    97
    101
    106
    114
    0:12
    1:174
    2:12
    3:148
    97
    101
    106
    114

I verified and re-verified the syntax so many times. could not find anyone facing similar issue. I am at my wits end why it would not print correct values inside the loop. Any ideas?

EDIT: expected output is:

    97
    101
    106
    114
    0:97
    1:101
    2:106
    3:114
    97
    101
    106
    114

body:
After going through link given by Juraj above again, I could make it work as follows:

    const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
    const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
    const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
    const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

    const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

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

      Serial.println(pgm_read_byte(&(arr[0][0])));
      Serial.println(pgm_read_byte(&(arr[1][0])));
      Serial.println(pgm_read_byte(&(arr[2][0])));
      Serial.println(pgm_read_byte(&(arr[3][0])));
      for (int i = 0; i < 4; i++) {
        Serial.print(i);
        Serial.print(":");
        Serial.println(pgm_read_byte_near(pgm_read_word(&(arr[i])) + 0));
      }
      int j = 0;
      Serial.println(pgm_read_byte(&(arr[j][0])));
      j = 1;
      Serial.println(pgm_read_byte(&(arr[j][0])));
      j = 2;
      Serial.println(pgm_read_byte(&(arr[j][0])));
      j = 3;
      Serial.println(pgm_read_byte(&(arr[j][0])));
    }

    void loop() {

    }

Now it shows the expected output and access from inside loop using variable index is possible. Thanks.


body:
    const byte a1[] PROGMEM = {'a', 'b', 'c', 'd'};
    const byte a2[] PROGMEM = {'e', 'f', 'g', 'h', 'i'};
    const byte a3[] PROGMEM = {'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q'};
    const byte a4[] PROGMEM = {'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};

    const byte * const arr[] PROGMEM = {a1, a2, a3, a4};

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

      for (int i = 0; i < 4; i++) {
        Serial.print(i);
        Serial.print(':');
        for (int j = 0; j < 4; j++) {
          Serial.print((char) pgm_read_byte_near(pgm_read_word(arr + i) + j));
          Serial.print(',');
        }
        Serial.println();
      }
    }

    void loop() {

    }

output

    0:a,b,c,d,
    1:e,f,g,h,
    2:j,k,l,m,
    3:r,s,t,u,

at runtime the size of the arrays is unknown, so I print the first 4 items


message:
Choosing a motor for my project

Sorry For my bad English.
I will start to make a mini conveyor (100 cm x 30 cm) with an Arduino Uno.

What is the best motor should I choose for my project ?
- Stepper Motor ?
- DC Motor ?
Etc.

Please help me, I am Newbie.

body:
 - If you want to control how much the conveyor moves and want to move it a fix distance then stop and move again stepper would be better as you know that each step is equivalent to a certain amount of displacement. Stepper have the disadvantage that is more complicated to control so you will need a special driver.
 - If you want the conveyor to move continuously at a approximately speed or moving approximately, then DC motor is a good option. It's easier to drive. But if you want the conveyor to go back and forward then you will need a H bridge for the DC motor(similar to the driver for the stepper motor). Also you can get very accurate positioning with a DC motor using a rotary encoder, but it requires a complex software to drive it properly.


body:
I second the suggestion that a stepper motor might be a more suitable drive mechanism.  There are a lot of stepper motors for sale on line for very low cost that can provide great accuracy.  They are an amazing value, probably because of so many robotics projects to supply.  Their native accuracy can be enhanced many times by use of what is called a "micro-step" driver.  The micro-step driver can transform a stepper motor that has 200 native steps per revolution to one that effectively has 2000 or more steps per revolution. I have found repeatability to be excellent.  They are used commonly to drive precision CNC machines.

And you are correct that if you don't need the fastest motion, a gear reduction can enhance accuracy even more.  There are small stepper motors with affixed gear boxes sold as sets.  Consider a size NEMA 17 stepper motor for a small and inexpensive, but well engineered, motor.

A coupled worm gear box has the advantage that it serves as a natural brake if there is any tendency for system weight to move the laser in certain positions, but gear reduction means that fast motion require higher motor rpm's.

The Accel_Stepper library has worked well for me in helping to get them to function smoothly.  It helps a lot to make it easy to integrate the stepper with Arduino, and it is fairly user-friendly.


message:
Distributing power evenly to multiple pins

It's an arduino board, model UNO R3. I have 3 5cmx10cm heating pad power required 5V DC up to 1A and can withstand up to 12V DC. These 3 heating pad are wired up onto arduino board with red wires connected to pin 8 pin 9 and pin 10 on the digital side of the arduino and the black wire connected to GND (ground). Lastly I have a toggle on and off switch connected to the arduino with the red wire attached to digital pin 2 and the black wire to 5V. The arduino uno R3 withstand 20voltage and the 5V heating pads can withstand 12V. I would like my 20V external power to heat up all 3 heating pads evenly, how can I do this? Is it possible? Thank you!

body:
Yes, of course it is possible.  But if all you need to do it to turn these heat pads on and off, an Arduino is perhaps not the most suitable technology.

But presuming these heat pads are a component of some more complex system that responds to other inputs or outputs to/from the Arduino, you will need a few more components.  You need to accomplish two things that the UNO R3 cannot accomplish by itself, because your heat pads are very much too large a load for your UNO to power directly.  (The power for a single LED bulb is about the most that you can draw from an output pin.)

 1.  You need to reduce your 20-V external power source down to something less than 12 volts to supply your heating pads.

 2.  You need to switch on and off up to 1 amp of current to flow to each of the three heating pads.  The UNO cannot do this directly.

There are a lot of ways to reduce your 20-volt supply down to less than 12 volts.  Some are much more efficient than others.  Probably the lowest cost efficient way is to use your 20-V source as the input a small DC to DC voltage down stepping converter.  These are available online from Chinese vendors for very low cost.  Just search for "DC-DC converter down".  A quick search finds one rated at 20 amps, with adjustable voltage output can be purchased for less than $10.  These are pretty efficient devices that don't waste the power that a simple voltage dropping resistor would waste.

Then you need either one or three 5-volt relays of some type to switch the power on to the heat pads.  The UNO pins output of 5-volts would not provide current to heat pads, put only enough current to energize the relay(s).  The relay(s) can be either solid state, or coil energized.  Just be sure the relay "contacts" are rated to handle well more than 1 amp if there are three of them, and more than 3-amps if only one.   An Arduino relay shield with four relays, each rated for 10 amps, can be purchased for less than $5.

If you only every want all three heat pads energized at the same time, you only need one relay, and one Arduino output to energize it.

The very simplest solution, if you only want all the pads heating simultaneously, would be to wire the three heat pads in series.  Then you could apply your 20-volts directly across all three heat pads, and you would not need any device to reduce your supply voltage.  Each heat pad would have 1/3 of 20 volts across it, which is well under their 12 volt tolerance.  And you would only need one relay.


body:
Can you state the full goal of the project? Are you supposed to be turning the heating pad on and off with the Arduino? (The rest of my answer assumes that that is what you want to do.)

You will need a source of DC power to drive the Arduino. (You can't power an Arduino with AC.)

You will need a 5V relay so you can turn off the power to the heating pad from a logic pin on the Arduino. There are various relay modules made to be controlled by microcontrollers like Arduinos. This one, for example: https://www.jameco.com/z/VMA406-Velleman-Arduino-Compatible-5V-Relay-Module_2255306.html?CID=GOOG&gclid=EAIaIQobChMIr9bSioLT4AIVkpOzCh3X7gqbEAQYBSABEgLf1PD_BwE

Then you will be able to rig the Arduino to turn the relay on and off. You'll wire the power for the heating pad through the relay. You will also need a way to lower the voltage of your power supply to the 5V - 12V range you mentioned. A 1:2 step-down transformer would be a good choice for that.


message:
Trying to use an LCD 1602 to display, but I don't have a 10 KOhm potentiometer

I'm following this [tutorial page][1] and I don't have a 10k ohm potentiometer on hand. Could I replace it with resistors to simulate a manual setting and replace the resistors to adjust to a new settings.

From what I was reading this pin is for contrast and I'm sure I could manually set the contrast once and be happy with it for quick prototyping. I'll be ordering a 10k ohm potentiometer on Monday.

  [1]: https://aibodoctor.com/arduino_lcd/

body:
Yes. All a potentiometer is, is two resistors end to end.  The "wiper" is the join between the two resistors.

It doesn't matter too much what value potentiometer (and hence what value resistors) you use, as long as it's "around" the 10kΩ mark (100kΩ should be fine, 50kΩ, 1kΩ etc - anything below 1kΩ may not work) - what matters is the ratio of the values of the resistor.


body:
Yes, you always can do that, depending on the resistors you have at hand, you can combine them to make e.g. 1 KOhm, 2 KOhm etc resistors.

Probably you need a linear potentiometer (which means halfway is 5 KOhm).

In a linear potentiometer, you can use the following resistance (made up by a single or a combination of resistors in series or parallel):


body:
Yes, but you need only one resistor to GND. The display has already one resistor inside the display. I forgot what the value should be and I don't have a display at hand right now, so you have to try which value is best.

In most examples with a LCD display, a potentiometer is used for the contrast. Not many people know that only a (variable) resistor to GND is needed.

With a fixed resistor, you are not able to quickly adjust the display when the temperature changes.


message:
Comparing byte array with multi-dimensional array

I am having a byte array let us say

    byte arr[7]={123456};

How to compare this array with a list of of other array like this for example

    byte  buffers[5][7] = {123456,654321,987654,456789,765432};

if this method is wrong how can I declare that ?

body:
    byte arr[7]={123456};

sets arr[0] = 64 - which is 123456 % 256 - and arr[1-6] are left at 0

And you also only want 6 (not 7) values - so the code would be

    byte arr[6]={1,2,3,4,5,6}; // this is how to initialise an array
    byte  buffers[5][6] = {{1,2,3,4,5,6},{6,5,4,3,2,1},{9,8,7,6,5,4},{4,5,6,7,8,9},{7,6,5,4,3,2}}; // this is how to initialise a 2d array

    void setup() {
      Serial.begin(74880);
      delay(100);
      // this code will find a match, the vlaue of `i` will be the matched index
      int i;
      int j;
      for(i = 0; i < 5; i++) {
        for(j = 0; j < 6; j ++) {
          if(arr[j] != buffers[i][j]) {
            break;
          }
        }
        if(j == 6) {
          break;
        }
      }
      if (i < 5) {
        Serial.print("Found at index ");
        Serial.println(i);
      }

    }


message:
Outputting 400 mV using Arduino Nano PWM pin

[![blood glucose breakout board][1]][1]

I am trying to output analog voltage (400 mV) using Arduino Nano PWM pins. Is it okay to directly connect (using jumper wires) the PWM pins to the Vin+ of the INA219 current sensor?

I badly need it for my graduation project. Thanks for the help.

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

body:
PWM pins don't output analog voltages. They output pulses of 5V. You then need to average the output in order to get an actual analog voltage out of it. You should be able to use a capacitor and resistor to average out the voltage of the PWM pin, making a [low-pass filter][1]. You won't get exactly to 400mV. If I remember correctly the PWM pin has a value of 0 - 255, and 1/255 is 0.0196 V after a good low-pass filter, or 19.6 mV, so `analogWrite(pin,20)` should get close to the 400mV you want.

Another option would be to use a voltage divider to the output to get the output you want. That way you can use the full range of `analogWrite()` in producing the 400 mV and smaller voltages, thus gaining precision. Then again, if all you want is a fixed 0 or 400mV you could accomplish that with a digital output pin and a fixed voltage divider - no need for PWM.

  [1]: https://en.wikipedia.org/wiki/Low-pass_filter


body:
Of course it's possible !

Duncan you made a little error of 10^2 ;)

5V / 1023 = 0.004887.. = 4.88mV

For 400mV you got 400/4.88 = 81.9.

So in the arduino a value of 82 (0-1023) will send you an output of 400.16mV after beeing redressed by a RC filter.


message:
Bypass a function error

I have a long code written in Arduino101 that works fine. I use a prepared function (connected to a library) in my code that I have not written it. My input to this function is an array. In 99.9999..% of the time, the function works great. However, it might stops due to an unknown reason, maybe because of my wrong input. This causes the program to stop.
My question is: how to bypass this function if it fails for any reason? Something like 'on error' function in normal programming.

Thanks a lot in advance,

body:
If your function is crashing then there is no way to recover. Arduinos are unprotected real mode devices. If your code does something invalid, your program crashes and the device will likely either hang or restart.

You need to debug your function, or find the invalid data you are passing into it.


message:
Parsing Data and Comparing two string in arduino

I am working on my final assignment. The problem is I want to make a prototype tool, with 2 string compare. If I send data "OK DISC DISCLOSED: 341513DB689AOK RSSI: -056 OK NAME: CarBT1 OK DISCE" will be parsed and bring up data "CarBT1 OK DISCE" if the data is correct then the LED will turn on, but my program isn't working? does anyone know the problem?

    String dataIn;
    String dt[10];
    int i;
    boolean parsing=false;
    const int pinLED = 8;
    String readString;

    void setup (){
      Serial.begin(9600);
      pinMode(pinLED, OUTPUT);
      Serial.print("Sketch:   ");   Serial.println(__FILE__);
      Serial.print("Uploaded: ");   Serial.println(__DATE__);
      Serial.println(" ");
      while(!Serial){
        ;
      }
    }

    void loop (){
      if(Serial.available()>0) {
      char inChar = (char)Serial.read();
      dataIn += inChar;
      if (inChar == '\n'){
      parsing = true;
      }
    }
    if(parsing){
      parsingData();
      parsing=false;
      dataIn="";
    }
    while(Serial.available()){
      delay(3);
      char c =  Serial.read();
      readString += c;
    }
    readString.trim();
      if(readString.length()>0){
        if(readString == "CarBT1 OK+DISCE"){
          digitalWrite(pinLED, HIGH);
          Serial.println("Switching On");
       }
      if(readString == "off"){
          digitalWrite(pinLED, LOW);
          Serial.println("Switching Off");
       }
    readString = "";
     }
    }

    void parsingData(){
    int j=0;
    Serial.print("data masuk : ");
    Serial.print(dataIn);
    Serial.print("\n");
    dt[j]="";
    for(i=1;i<dataIn.length();i++){
      if ((dataIn[i] == ':') || (dataIn[i] == ':')){
      j++;
      dt[j]="";
    }
      else{
      dt[j] = dt[j] + dataIn[i];
      }
     }
    }
    Serial.print("data 1 : ");
    Serial.print(dt[0]);
    Serial.print("\n");
    Serial.print("data 2 : ");
    Serial.print(dt[1]);
    Serial.print("\n");
    Serial.print("data 3 : ");
    Serial.print(dt[2]);
    Serial.print("\n\n");
    Serial.print("data 4 : ");
    Serial.print(dt[3]);
    Serial.print("\n\n");
    }

body:
I think that the biggest problem that you are encountering is that reading a line from serial is not as straightforward as you would like. I don't have a quick and easy solution for you, but there is much on this issue that you can look at.

You have two serial read while loops. The first exits as soon as there are no characters to read (even though some may be on the way). When "\n" is read, you set parsing but it does not mean that \n is removed from dataIn.

The second serial read while loop is using a delay(3) after detecting that a character is available, but that character could have arrived after the first read and be the only character in the buffer, for example.

I suspect that the reason that your String comparison does not work is simply because the Strings are not equal.

Your String looks like something read from an HM-10/11 or something similar. I have had some success reading those transmissions by doing the following:

Make sure the serial buffer is empty. When a character is available, read it into your building String, but continue looking for characters that are available for a set amount of time (maybe a couple of seconds). Continue looking for characters until the time has elapsed and not as soon as there are no characters available (because more may be coming). Alternatively, keep building the string until you recognize the "DISCE" marking the end of that transmission.

A problem, however, is that, in my experience, if it is a very long line (that can occur when there are many devices out there), you will never get that "DISCE". I assumed that this was a firmware issue.

Hope it helps.