title: Wrong use of memory?

text:
# Question
Title: Wrong use of memory?
Probably I'm doing something wrong. I'm writing an Arduino sketch for ESP32. Among the others I have this function:

```
#define HDR_MAX_LENGHT 4
#define CMD_MAX_LENGHT 5
#define ARG_MAX_LENGHT 5
#define ARG_MAX_NUMBER 8

void ProcessLine(HardwareSerial *serial, char *line)
{
  int ret;
  int argc;
  char header[HDR_MAX_LENGHT + 1];
  char cmd[CMD_MAX_LENGHT + 1];
  char argv[ARG_MAX_NUMBER][ARG_MAX_LENGHT + 1];

  return; // for debugging
}

```

Usage example:

```
void loop()
{
    static char inBuf[64];

    if (Serial.available())
    {
      size_t size = Serial.readBytes(inBuf, 64);
      inBuf[size] = '\0';
      ProcessLine(&Serial, inBuf);
    }
}

```

In the last days all worked fine. After adding other code, I noticed that sometimes my program "hangs": nothing runs. Perhaps it goes in an exception trap.

Commenting out the different sections of the code, I discovered that if I remove the declarations of the variables in `ProcessLine()` no more hangs happen. The current RAM consumption is negligible: 0.5%.

During the tests NO serial data was received! So the function `ProcessLine()` was *never* called. Hence, only the declaration of the variables lead to the "hang".

I wonder if there are some mistakes in the code above. Otherwise, how I can further debug my code to understand what I've done wrong?

# Answer
> 4 votes
As I said in a comment, there is nothing wrong with these declarations. Now, here are some debugging strategies you may try:

1. You can rebuild your program with all compiler warnings enabled. Look carefully at the compiler messages and investigate any warning you see.
2. You can continue with your current strategy: put back those declarations, then try to remove something else. You may find that there are multiple pieces of code that, when removed, make your program work again. Chances are the problem resides in one of those pieces. But then, it may be that the problem is in the interaction between multiple pieces rather than in one specific piece.
3. You may just read the code carefully and see if you spot something suspicious. This can work sometimes: see how @Juraj spotted a buffer overflow in your code snippet just by reading it.
4. You can add debug messages across your program, to check what branches are executed, the values of variables...
5. I don't know the ESP32 dev environment, but you can check whether the compiler supports adding “sanitizers”. These are pieces of code added by the compiler that do run-time checks on your program, and report problems as they happen. You may want to enable at least an address sanitizer and an undefined behavior sanitizer.
6. If the environment supports it, you can try to run the program in a debugger. No success guaranteed: if the program corrupts its memory, it may crash in some place unrelated to the actual problem. The debugger will tell you where it crashed, which may not be very helpful in this case.
7. If the ESP dev environment supports neither 5 nor 6, you may try to run your program on your PC. There are a couple of Arduino-compatible cores that you can download for running on a PC.

---
Tags: esp32, variables, memory
---


# Question
Title: ''Wire1' was not declared in this scope' in I2C_MPU6886 library
I recently purchased a 6-axis IMU MCP6886 module by M5Stack. Product link: https://github.com/m5stack/M5-ProductExampleCodes/tree/master/Unit/IMU\_Unit. The example code provided by the manufacturer is as follows:

```
#include "I2C_MPU6886.h"

I2C_MPU6886 imu(I2C_MPU6886_DEFAULT_ADDRESS, Wire1);

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

  Wire1.begin(21, 22);

  imu.begin();
  Serial.print("whoAmI() = 0x%02x\n", imu.whoAmI());
}

void loop() {
  float ax;
  float ay;
  float az;
  float gx;
  float gy;
  float gz;
  float t;

  imu.getAccel(&ax, &ay, &az);
  imu.getGyro(&gx, &gy, &gz);
  imu.getTemp(&t);

  Serial.print("%f,%f,%f,%f,%f,%f,%f\n", ax, ay, az, gx, gy, gz, t);

  delay(100);
}

```

When I run this code on Arduino IDE 1.8.19, I get the following error: **'Wire1' was not declared in this scope**. I believe this issue is with the I2C\_MPU6886 library itself, but I am not able to troubleshoot it. I am using an Arduino Uno R3 board and running the IDE on Windows 11.

# Answer
> 3 votes
"M5Stack" is an ecosystem of ESP32 based boards and peripherals.

All code for M5Stack peripherals is written for the M5Stack system. Not for the Uno.

You have to find code for the Uno, not for the M5Stack. M5Stack code **will not work on the Uno since it is a completely different system.**

---
Tags: i2c, wire-library, imu, m5stack
---


# Question
Title: ESP8266 soft resets when using a GPIO Expander
In my project I'm trying to use a PCF8574 to drive some peripherals, since the ESP8266 doesn't offer all the GPIO pins I need, however I seem to be having problems at the most basic level of driving the pins of an e-paper display.

The e-paper display is connected to MOSI, MISO and SCL to the "native" pins GPIO12, 13 and 14, and I wanted to rely on the PCF to drive the other four pins (CS, DC, RST, BUSY).

I modified the original library so that it could accept an arbitrary `Pin` abstraction that looks like the following:

```
class Pin {
public:
  Pin(void){};
  ~Pin(void){};

  virtual uint8_t read() = 0;
  virtual void write(uint8_t value) = 0;
};

```

and at first implemented it as `ArduinoPin`, which all it does is setting up the pin mode and calling `digitalRead` or `digitalWrite` when needed.

While connecting the EPD with the `ArduinoPin` implementation, using D0, D1, D2, D4 as pins, the e-paper display works correctly, so I proceeded to make another implementation of Pin with the GPIO Expander.

Following the GPIO Expander and relative Pin implementations

`gpio-expander.h`

```
class GpioExpander {
public:
  GpioExpander(uint16_t address);
  GpioExpander();
  uint8_t read(uint8_t pin);
  void write(uint8_t pin, uint8_t value);

private:
  uint8_t buffer[1] = {0xFF};
  uint16_t address;
};

class GpioExpanderPin : public Pin {
public:
  GpioExpanderPin(GpioExpander *expander, uint8_t pinNumber);
  ~GpioExpanderPin(void);
  virtual uint8_t read();
  virtual void write(uint8_t value);

private:
  uint8_t myPin;
  GpioExpander *expander;
};

```

`gpio-expander.cpp`

```
GpioExpander::GpioExpander(uint16_t address) {
  this->address = address;
  buffer[0] = 0xFF;
  Wire.beginTransmission(address);
  Wire.write(buffer[0]);
  Wire.endTransmission();
}

GpioExpander::GpioExpander() : GpioExpander(0x20) {}

uint8_t GpioExpander::read(uint8_t pin) {
  write(pin, 1);
  Wire.requestFrom(address, 1);
  buffer[0] = Wire.read();
  return (buffer[0] >> pin) & 1;
}

void GpioExpander::write(uint8_t pin, uint8_t value) {
  if (value == 1)
    buffer[0] |= (1 << pin);
  else
    buffer[0] &= ~(1 << pin);
  Wire.beginTransmission(address);
  Wire.write(buffer[0]);
  Wire.endTransmission();
}

```

`gpio-expander-pin.cpp`

```
GpioExpanderPin::GpioExpanderPin(GpioExpander *expander, uint8_t pinNumber) {
  this->expander = expander;
  myPin = pinNumber;
}

GpioExpanderPin::~GpioExpanderPin(void) {}

uint8_t GpioExpanderPin::read() { return this->expander->read(myPin); }

void GpioExpanderPin::write(uint8_t value) {
  this->expander->write(myPin, value);
}

```

These implementations work fine, I tested everything with a multimeter and I can arbitrarily write 1s and 0s on all 8 pins of the PCF, but when I try to drive the four pins of the e-paper, the ESP8266 resets and I have no clue on why. I tried with the exception decoder and the following stacktrace appears:

```
Exception Cause: Not found

0x40202984: Twi::read_bit() at ??:?
0x402029db: Twi::write_byte(unsigned char) at ??:?
0x40202b94: Twi::writeTo(unsigned char, unsigned char*, unsigned int, unsigned char) at ??:?
0x40202bb9: Twi::writeTo(unsigned char, unsigned char*, unsigned int, unsigned char) at ??:?
0x40202cc0: twi_writeTo at ??:?
0x40201720: TwoWire::endTransmission(unsigned char) at ??:?
0x40105cfe: os_printf_plus at ??:?
0x40201748: TwoWire::endTransmission() at ??:?
0x402017f5: GpioExpander::write(unsigned char, unsigned char) at ??:?
0x40201794: GpioExpanderPin::write(unsigned char) at ??:?
0x402011f9: Epd::spiTransfer(unsigned char) at ??:?
0x40201238: Epd::sendData(unsigned char) at ??:?
0x40201385: Epd::clear() at ??:?
0x402010b6: setup at ??:?
0x4020583c: std::_Function_handler<bool (), settimeofday::{lambda()#1}>::_M_manager(std::_Any_data&, std::_Function_handler<bool (), settimeofday::{lambda()#1}> const&, std::_Manager_operation) at time.cpp:?
0x4020583c: std::_Function_handler<bool (), settimeofday::{lambda()#1}>::_M_manager(std::_Any_data&, std::_Function_handler<bool (), settimeofday::{lambda()#1}> const&, std::_Manager_operation) at time.cpp:?
0x4020583c: std::_Function_handler<bool (), settimeofday::{lambda()#1}>::_M_manager(std::_Any_data&, std::_Function_handler<bool (), settimeofday::{lambda()#1}> const&, std::_Manager_operation) at time.cpp:?
0x4020583c: std::_Function_handler<bool (), settimeofday::{lambda()#1}>::_M_manager(std::_Any_data&, std::_Function_handler<bool (), settimeofday::{lambda()#1}> const&, std::_Manager_operation) at time.cpp:?
0x40202158: loop_wrapper() at core_esp8266_main.cpp:?
0x40100e85: cont_wrapper at ??:?

```

(Not sure why I can't get the source lines to appear, any suggestion in that is most welcome.)

Anyway apparently the problem appears when ending the I2C transmission, at the lowest level possible, at Twi::read\_bit, which I include for the sake of all of you trying to help me out

`core_esp8266_si2c.cpp`

```
bool Twi::read_bit(void)
{
    SCL_LOW(twi_scl);
    SDA_HIGH(twi_sda);
    busywait(twi_dcount + 2);
    SCL_HIGH(twi_scl);
    WAIT_CLOCK_STRETCH();
    bool bit = SDA_READ(twi_sda);
    busywait(twi_dcount);
    return bit;
}

```

The most upsetting thing is that this same setup, when programmed in Micropython works just fine (I can't use Micropython though, because I need all the RAM I can get from the ESP to draw pictures, and I'm much interested in the overall performance I can get with C++).

Anyone had this same problem? Any advice on how to fix this behavior?

**EDIT**

With some experimentation, I managed to replicate the problem in a smaller scale. The following code resets the ESP8266 as well:

```
void setup() {
  Wire.begin();
  GpioExpander expander;
  GpioExpanderPin pin(&expander, 0);
  while(true) {
    pin.write(0);
    pin.write(1);
  }
}

```

It looks like fast cycles of on-off crash the system (which is what the EPD library does when sending data, turning on and off the pins relatively fast to switch between modes etc.). Not sure how to address this though, but I believe it might be something related to the Twi libraries at this point.

**EDIT 2**

Adding a `yield()` to the `write` function of the gpio expander class makes the issue go away, but the time to execute a simple display clear grows to unacceptable levels (~3 seconds to perform a full display refresh).

Any suggestion is appreciated at this point.

**EDIT 3**

I did some more experimenting and benchmarking, and reached the following conclusions:

* the time that it takes for the Wire library to send data to the GPIO expander (the `write` function) is ~50µs
* when using the gpio expander, the time to write data to the SPI device (DC write + enable CS + SPI transfer + disable CS) takes a total of ~170µs (which checks out, 3 times calling the gpio expander makes for ~150µs and the rest is SPI transaction)
* when using the arduino pins, the time to write data to the SPI device takes ~10µs (an order of magnitude less than the GPIO expander).

To send a total of 150,000 bytes to the e-paper display, then, with the GPIO expander takes roughly 3 seconds, while with the normal pins it would take 10 times less (0.3 seconds). The reset issue is surely due to the time spent in the send loop: the watchdog thinks the program is stuck in an infinite loop and thus resets the board. This is why the calls to `yield` remove the reset issues.

I believe I must either find a faster implementation of wire (?) or try to minimize usage of CS / DC pins

# Answer
> 2 votes
In the end the answer to the problem is the update frequency of the pins that drive the e-paper display:

The original waveshare library (as linked in the post) does the following to send data to the EPD:

* enable DC (to tell the EPD that it's receiving DATA)
* enable CS (to tell the EPD to listen to the incoming SPI data)
* send SPI data
* disable CS (to tell the EPD that anything received after that is not its competence)

Normally with arduino's `digitalWrite` this happens in a matter of ~10µs, and even if we repeat this process 15k times (that's how many bytes a 4.2 inch display supports) we spend 0.15 seconds to update **half** of the display's content (because the EPD has 2 memory banks which must be written).

When using the GPIO expander, instead, the mean time to send data via I2C is something around 50µs, which means that to enable / disable the pins three times we increase tenfold the time that the normal digital write takes (~150µs) which translates to 1.5 seconds to update half of the display and finally roughly 3 seconds for a full update.

During this loop, the watchdog thinks that the program is stalling and resets the chip. This is why using `yield` the update runs its course correctly.

To fix this issue, I worked on the EPD library and reduced the use of the digital writes, by creating a "session" of sorts: whenever I start writing data in a loop, I enable the CS pin, and disable it only at the end of the loop, so that the 100µs are only expended around the data transfer loop.

This is actually what happened in the Micropython driver for the e-paper display: the SPI connection sent data in chunks, enabling and disabling the chip select pin only at the beginning and end of the "transaction".

I'm planning to publish the updated library at some point, once everything is smoothed out, if this can interest anyone leave a message :)

---
Tags: esp8266, i2c, io-expander
---


title: Create a library when using PlatformIO

text:
# Question
Title: Create a library when using PlatformIO
**(1)** I'm trying to work with libraries in PlatformIO format", for , of a library, located in Arduino's `libraries`, where code is llocated under `\src` directry.

**(2)** Any other library, not it "PlatformIO format" as I call it, has to contain inside `libraries/EXMPLE` lib a `EXMPLE.h`, and `EXMPLE.cpp` file.

**(3)** Now, when I try to create a "PlatromIO format" library (since I want to move to PlatfromIO) compilation fails, saying `.h` file was not found (an error you would get since `.h` `.cpp` was not located in their parent directory), as noted in **2** . see library `ABCD` in  (which contains only library structures).

Appreciate any help

Guy

# Answer
> 1 votes
You're describing "1.5.x" format libraries, not "PlatformIO". This arrangement for a library was created for Arduino IDE version 1.5.0.

The critical part of this library format is the `library.properties` file which describes the library, and also identifies it as being a library (and which you seem to be lacking). The format of the file is described here.

---
Tags: library, platformio
---


# Question
Title: ESP8266 - How to recieve UDP multicast packet?
how can I recieve udp multicast packets in ESP8266? I have this piece of code:

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

const char* ssid = "my_wifi_ssid";
const char* password = "my_wifi_password";

WiFiUDP Udp;
unsigned int multicastPort = 5683;  // local port to listen on
IPAddress multicastIP(224,0,1,187);

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

    Serial.printf("Connecting to %s ", ssid);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
    delay(500);
    Serial.print(".");
    }
    Serial.println("connected");

    Udp.beginMulticast(WiFi.localIP(), multicastIP, multicastPort);
    Serial.printf("Now listening at IP %s and %s, UDP port %d\n", WiFi.localIP().toString().c_str(), multicastIP.toString().c_str(), multicastPort);
}

void loop(){
    int packetSize = Udp.parsePacket();
    if (packetSize){
    Serial.println("RECEIVED!");
    }
}

```

I wrote it according to this documentation and this addition to that about adding multicast.
It just set server listening on port 5683.
It prints something like:
Now listening at IP 192.168.1.6 and 224.0.1.187, UDP port 5683
But if I send UDP packet to 224.0.1.187:5683 (eg. via Packet sender app), it doesn't print message "RECEIVED!" (which should, look in loop function). Why ESP8266 is not receiving anything? Strange is, that when I send packet to 192.168.1.6:5683 (its local IP), it prints that message ("RECEIVED!").
Why it works only for local message but not for multicast??

Thanks for every help! :)

PS: this advice didn't help me...

# Answer
I think you need to call

```
Udp.begin(multicastPort);

```

right before calling

```
Udp.beginMulticast(WiFi.localIP(), multicastIP, multicastPort);

```

At least that's what did the trick for me.
> -1 votes

---
Tags: esp8266, networking, tcpip, esp
---


# Question
Title: Problem with messuring capacitance with 50 Arduinos connected by I²C
I want to measure changes in capacitance over time. One Arduino is used per capacitance sensor. There is one anode per Arduino and a total of one common cathode (see the picture)

With four Arduinos connected in series via an I²C master-slave connection, successful results were obtained. With more than four Arduinos, all measurement results were 0, because no voltage is measured at the input pin anymore.

I then lowered the reference voltage for analogRead. So 10 Arduinos in series were possible. However, the measured values are clearly lower. However, no absolute values are to be measured, but any difference in the capacitance is sufficient. Finally 50 Arduinos should be used.

I have thought of the following possibilities:

1. reduce the reference voltage further, but this may reduce the measurement results further, so that no deflection is measured.
2. increase the output voltage at the Arduino via an operational amplifier to compensate the voltage drop.

How could I proceed to get a usable result with all 50 Arduinos? The code I used is to be found below.

### Master

```
#include <Wire.h>

volatile byte x1, x2;
volatile int val_slave;

const int OUT_PIN = A0;
const int IN_PIN = A2;

#define nodeMax 10
#define nodeStart 2

void setup() {
  analogReference(DEFAULT);
  Wire.begin();

  pinMode(OUT_PIN,OUTPUT);
  pinMode(IN_PIN,OUTPUT);

  Serial.begin(9600);
  // put your setup code here, to run once:

}

  void loop() {

    pinMode(IN_PIN,INPUT);
    digitalWrite(OUT_PIN,HIGH);

    int val = analogRead(IN_PIN);

    digitalWrite(OUT_PIN,LOW);
    pinMode(IN_PIN,OUTPUT);

    Serial.print(val);
    Serial.print(",");

      delay(10);

    for (int node = nodeStart; node <= nodeMax; node++) {

        // Ask the slave to release the input pin.
        Wire.beginTransmission(node);
        Wire.write(0);
        Wire.endTransmission();
        delay(10);  // give it time to do so

        // Charge the capacitors.
        digitalWrite(OUT_PIN, HIGH);

        // Ask the slave to read val.
        Wire.requestFrom(node, sizeof(val));

        // Discharge.
        x1 = Wire.read();
    x2 = Wire.read();

    val_salve = (int)x1 << 8 | (int)x2;

        Serial.print(val_slave);
        Serial.print(",");

        digitalWrite(OUT_PIN, LOW);
        delay(10);

    }
    Serial.println();
    delay(50);
}

```

### Slave

```
const int IN_PIN=A2;

#include <Wire.h>
#define node 10

void setup() {
    // ...
    analogReference(DEFAULT);
    Wire.begin(node);
    Serial.begin(9600);

    pinMode(IN_PIN,OUTPUT);

    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);

}

// Release IN_PIN when the master sends a message.
void receiveEvent(int byte_count) {
    pinMode(IN_PIN, INPUT);
    while (byte_count--)
        Wire.read();  // discard the received message
}

void loop ()
{
}

void requestEvent() {
    int val = analogRead(IN_PIN);
    // transmit the result... then

    Wire.write(highByte(val));
    Wire.write(lowByte(val));

    pinMode(IN_PIN, OUTPUT);  // discharge
}

```

# Answer
> 3 votes
The cathode line is being shared by all the Arduinos' `OUT_PIN`. When one of them tries to set the pin `HIGH`, all the others are trying to hold it `LOW`. This is a short-circuit condition that can damage the Arduino's outputs. Even if they do survive, the voltage on the line will be significantly below 5 V because of those Arduinos pulling the line `LOW`. The more of them pull the line `LOW`, the lower the voltage will be.

The simple solution would be to change the protocol such that only the Arduino that is currently making a measurement can pull that line, while the others keep their `OUT_PIN` in high-impedance mode (i.e. `INPUT`). This is fragile because... bugs happen, and you may still be making a short-circuit. A more robust solution would be to connect *only* the master to the cathode, and give it the responsibility to drive the line `HIGH` and `LOW`.

Now, a coupe of unrelated comments:

* A `float` is four bytes: there is no point in transmitting ten bytes.
* You can measure up to four capacitors with each Arduino (pins `A0` through `A3`, you can use a digital pin for `OUT_PIN`), it is wasteful to use one Arduino per capacitor.

**Edit**: If only the master controls `OUT_PIN`, then some communication protocol is needed in order to synchronize it with the slaves, so that they can release `IN_PIN` at the right time. The simplest protocol I can think of is the following: when the master sends something (*anything*) to a slave, this message means “please release `IN_PIN` now”.

Here is some untested code implementing this idea:

**master**:

```
void loop() {
    // ...
    for (int node = nodeStart; node <= nodeMax; node++) {

        // Ask the slave to release the input pin.
        Wire.beginTransmission(node);
        Wrire.write(0);
        Wire.endTransmission();
        delay(10);  // give it time to do so

        // Charge the capacitors.
        digitalWrite(OUT_PIN, HIGH);

        // Ask the slave to read the capacitance.
        Wire.requestFrom(node, sizeof(capacitanceSlave));

        // Discharge.
        digitalWrite(OUT_PIN, LOW);

        // ...
    }
}

```

**slave**:

```
void setup() {
    // ...
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
}

// Release IN_PIN when the master sends a message.
void receiveEvent(int byte_count) {
    pinMode(IN_PIN, INPUT);
    while (byte_count--)
        Wire.read();  // discard the received message
}

void requestEvent() {
    int val = analogRead(IN_PIN);
    // transmit the result... then
    pinMode(IN_PIN, OUTPUT);  // discharge
}

```

# Answer
> 1 votes
The I²C bus was never intended as a distribution bus between many computers. The outputs are not designed to drive long wires. With a lot of kludging you may get this to work, but it is definitely not repeatable or reliable.

Consider something else. CAN can do maybe 60 nodes, depending on the transceiver chosen. It is relatively inexpensive.

# Answer
> 1 votes
You might want to consider using a RS485 protocol. Unlike I2C this uses "balanced" wiring so is more suitable for longer cable runs.

I described a way of coding a number of Arduinos using a "rolling master" protocol here \- this lets you connect a considerable number of Arduinos to the two wires, and they take turns to send the data.

However in your case, since you are measuring capacitance (not capacity?) then each of your Arduinos can measure 6 (or possibly more) analog readings, so you don't need 50, you need 50/6 = 8.33 Arduinos (OK, nine).

The Arduino Micro, for example, has 12 analog input channels, so you would only need 4 (to get 48 inputs) or 5 (to get 60 inputs). Then you could stick to I2C.

---
Tags: i2c, capacitors
---


# Question
Title: Stm32 Blue Pill Internal reference voltage Arduino IDE
I want to use the internal reference voltage (1.2V) of stm32f103 blue pill using Arduino IDE. I searched the whole internet but couldn't find anything. I need help with this. Thanks.

# Answer
> 1 votes
There's no way of using the internal 1,2v reference as the ADC reference. (in the same way that you can do on an AVR) You can only use the ADC to read the internal vref, and use that value to adjust the next ADC reading you take. Like a compensation factor.

---
Tags: arduino-ide, stm32
---


# Question
Title: Connect to 8Base API with TLS on Arduino Uno Wifi Rev2
I'm trying hit some endpoints on the 8Base API with the Arduino Uno Wifi Rev2. I was able to get this API call to work with Postman, but I've had no luck once I convert it to my Arduino code. In Postman, clicking the "Code" button reveals that this is what the successful Postman request looks like:

```
POST /MY_PATH HTTP/1.1
Host: api.8base.com
Authorization: Bearer MY_TOKEN
Content-Type: application/json
Content-Length: 64

{
    "query": "{ listOfMachinesList { items{ machineID } } }"
}

```

Here's what the relevant parts of my Arduino code look like after translating this API call into my Arduino:

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

WiFiSSLClient client;
char server[] = "api.8base.com";

const String requestBody = "{\"query\": \"{ listOfMachinesList { items{ machineID } } }\"}";
int status = WL_IDLE_STATUS;

void setup(){
  Serial.begin(9600);
  Serial.println("Starting");
  status = WiFi.begin(WifiSSID, WifiPassword);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Waiting for connection");
  }

  Serial.println("Connected to wifi");
  attemptConnect();

}

void attemptConnect() {

  Serial.println("\nStarting connection to server...");

  if (client.connectSSL(server, 443)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.print("POST /MY_PATH HTTP/1.1");
    client.println("User-Agent: Arduino/2.2.0");
    client.print("Authorization: Bearer ");
    client.println(String(APIKey));
    client.println("Content-type: application/json");
    client.print("Host: ");
    client.println(server);
    client.println("Connection: keep-alive");
    client.println();
    Serial.println("finished POST request");
  } else {
    Serial.println("didn't connect");
  }

}

```

The connection appears to fail on"client.connectSSL(server, 443)" before it can get inside the "if". My Serial Monitor shows the "didn't connect" message. Further, I added some additional Serial.println statements inside the connectSSL function. It looks like the connection fails in a function called void ServerDrv::startClient'", specifically here:

```
 if (!SpiDrv::waitResponseCmd(START_CLIENT_TCP_CMD, PARAM_NUMS_1, &_data, &_dataLen))
 {
        WARN("error waitResponse");
 }

```

I added the certificates from both api.8base.com and 8base.com following the instructions here: https://support.arduino.cc/hc/en-us/articles/360016119219-How-to-add-certificates-to-Wifi-Nina-Wifi-101-Modules-

Using this code and the certificate instructions above, I was able to connect to google.com on port 443, but no luck with 8base. I know that 8base uses GraphQL for their connections, but I was able to hit another GraphQL endpoint on a different, non-SSL server. I also checked to see if 8base was using a non-standard port, but, according to Postman, it is using 443. I'm a little confused why I can't get past the connectSSL function. On the surface, it seems like it should behave the same way as it does when I connect to Google, but there must be something else going on that I'm missing. Any help would be greatly appreciated!

# Answer
Unfortunately, our 8base team doesn't have much knowledge/content around C++. That said, I'd check out the following.

1. Here's a high-level HTTP client for Arduino that's modeled after the browser fetch API: https://github.com/instanceofMA/arduino-fetch
2. You wrote the API string as "api.8base.com". Try it with the full API endpoint; "https://api.8base.com/WORKSPACE\_ID" (where is your workspace ID?)

LMK if this helps.
> -1 votes

---
Tags: http, networking, arduino-uno-wifi
---


# Question
Title: Error while uploading the sketch to Arduino UNO using CLI
I have connected my Arduino UNO through USB to Raspberry pi 3B. I am using CLI for editing, compiling and uploading sketches \> `arduino-cli upload --fqbn arduino:avr:uno cli-test`. However, after attempting to upload the sketch, it throws the error, `Error during Upload: Failed uploading: no upload port provided` I even checked if the Arduino is detected on the respective port using `arduino-cli board list` and it shows

```
/dev/ttyACM0 serial   Serial Port (USB) Arduino Uno arduino:avr:uno arduino:avr
/dev/ttyAMA0 serial   Serial Port       Unknown

```

The support forum of Arduino says to 'select' the port. Nevertheless the support forum resolves the error for GUI application and not for CLI. I searched for how to select the port in CLI, but in vain. Any help is appreciated.

# Answer
> 2 votes
You specify the port with the `--port` flag to the upload command:

```
$ arduino-cli upload --fqbn arduino:avr:uno --port /dev/ttyACM0 cli-test

```

You can find all these things out for yourself by using `--help` at any time. For example:

```
$ arduino-cli upload --help
Upload Arduino sketches. This does NOT compile the sketch prior to upload.

Usage:
  arduino-cli upload [flags]

Examples:
  arduino-cli upload /home/user/Arduino/MySketch

Flags:
      --board-options strings        List of board options separated by commas. Or can be used multiple times for multiple options.
      --discovery-timeout duration   Max time to wait for port discovery, e.g.: 30s, 1m (default 1s)
  -b, --fqbn string                  Fully Qualified Board Name, e.g.: arduino:avr:uno
  -h, --help                         help for upload
      --input-dir string             Directory containing binaries to upload.
  -i, --input-file string            Binary file to upload.
  -p, --port string                  Upload port address, e.g.: COM3 or /dev/ttyACM2
  -P, --programmer string            Programmer to use, e.g: atmel_ice
  -l, --protocol string              Upload port protocol, e.g: serial
  -t, --verify                       Verify uploaded binary after the upload.

Global Flags:
      --additional-urls strings   Comma-separated list of additional URLs for the Boards Manager.
      --config-file string        The custom config file (if not specified the default will be used).
      --format string             The output format for the logs, can be: text, json, jsonmini, yaml (default "text")
      --log-file string           Path to the file where logs will be written.
      --log-format string         The output format for the logs, can be: text, json
      --log-level string          Messages with this level and above will be logged. Valid levels are: trace, debug, info, warn, error, fatal, panic
      --no-color                  Disable colored output.
  -v, --verbose                   Print the logs on the standard output.

```

---
Tags: arduino-uno, serial, raspberrypi, arduino-cli
---


# Question
Title: Problem with "converting a string constant to 'char*'" in the WiFi library
error:

```
C:\Users\mrtas\Desktop\sketch_may23a\sketch_may23a.ino: In function 'void setup()':

C:\Users\mrtas\Desktop\sketch_may23a\sketch_may23a.ino:41:24:
warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

   WiFi.begin(SSID, PASS);   //Begin WiFi
              ^     ^

```

code:

```
#include <DHT.h>
#include <WiFi.h>
#define DHTTYPE DHT11
#define DHTPIN 5

DHT dht(DHTPIN, DHTTYPE);

String msg = "GET /update?key=TWE505JXFTXDPNB3";
float temp;
char SSID;
char Pass;

int hum;

String tempC;

int error;
void updateTemp();
#define SSID "wifi name"

#define PASS "wifi pass"

#define IP "184.106.153.149"

void setup()
{
  dht.begin();
  Serial.begin(9600);
  delay(10);

  // Connect to WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(SSID);
  WiFi.begin(SSID, PASS);     //Begin WiFi

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

void loop() {
start:
  error = 0;

  temp = dht.readTemperature();
  hum = dht.readHumidity();

  char buffer[10];
  tempC = dtostrf(temp, 4, 1, buffer);
  updateTemp();

  if (error == 1) {
    goto start;
  }
  delay(5000);
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  Serial.println(cmd);
  delay(2000);

  if (Serial.find("Error")) {
    return;
  }
  cmd = msg ;
  cmd += "&field1=";
  cmd += tempC;
  cmd += "&field2=";
  cmd += String(hum);
  cmd += "\r\n";
  Serial.print("AT+CIPSEND=");
  Serial.println(cmd.length());

  if (Serial.find(">")) {
    Serial.print(cmd);
  }
  else {
    Serial.println("AT+CIPCLOSE");
    //Resend...
    error = 1;
  }

  Serial.println("AT+CWMODE=1");
  delay(2000);
}

boolean connectWiFi()
{
  String cmd = "AT+CWJAP=\"";
  cmd += SSID;
  cmd += "\",\"";
  cmd += PASS;
  cmd += "\"";
  Serial.println(cmd);
  delay(5000);

  if (Serial.find("OK")) {
    return true;
  }
  return false;
}

```

# Answer
> 2 votes
It's basically a bug in the library which is expecting "char \*" when you are supplying "const char \*.

You could work around it by changing:

```
#define SSID "wifi name"
#define PASS "wifi pass"

```

to:

```
char SSID [] =  "wifi name";
char PASS [] =  "wifi pass";

```

That makes them non-const so the error message should go away.

Not tested. But that is the general idea.

---
Tags: iot
---


title: Input Oscillating Wildly

text:
# Question
Title: Input Oscillating Wildly
I'm trying to read an input from a switch but instead of getting 0 and 1 for closed/open, I'm getting 0 and a rapid series of 1s and 0s. Originally I tried (and failed) to simply read a rotary encoder but when I swap it for a standard rocker switch or even connect wires directly then it's the same.

This is my first time trying to get an input into an Arduino so I'm probably missing something quite straightforward.

I've got ground going to one pin of the switch and pin 2 to the other. Here's the code I'm using to see if the switch is on or off.

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

void loop() {
 Serial.println(digitalRead(2));
}

```

# Answer
Pins configured as INPUT are in a high impedance state and very sensitive to electrical noise from the environment, especially with wires connected to them See Arduino Tutorial

Try using INPUT\_PULLUP in your pinMode statement.

Additionally you might want to investigate switch debouncing methods for when your switch is operated.
> 9 votes

---
Tags: switch, input, pull-up
---


# Question
Title: How to make the compiler ensure that local variables memory allocation won't cause any RAM overflow during execution?
Upon compiling a sketch using the Arduino IDE, a message like the following gets displayed in the console:

```
Global variables use 1540 bytes (75%) of dynamic memory, leaving 508 bytes for local variables. Maximum is 2048 bytes.

```

In addition, it seems that if the global variables use exceeds around 75% of total dynamic memory, the following message gets displayed in addition:

```
Low memory available, stability problems may occur.

```

So, it seems that by using the IDE in a regular way, the compiler does not ensure that local variables memory allocation won't cause any RAM overflow during program execution. Instead, it just displays a warning message when little RAM is left for local variables.

This can lead to program malfunctions at execution time, if local variables happen to take up more space than the remaining RAM.

How can one have the compiler detect whether local variables memory allocation will cause RAM overflow during execution or not, and warn the user at compile time only in those specific cases?

# Answer
You are describing "memory profiling" and is not typically a feature of C or C++. It is more common in higher level languages, such as Java, but C is a considered a much lower level language.

Typically such profiling is done at runtime using external tools such as `valgrind` and `massif`.

It's not really possible for the compiler to work out what your program will be doing when it is using external data and inputs to control how it works. Any such tests at compile time would be pretty much meaningless since any that pass in testing may still cause problems at runtime depending on what else may be happening at the same time, or even what may have happened in the past (see heap fragmentation).
> 2 votes

---
Tags: arduino-uno, memory-usage, compiler
---


# Question
Title: HD44780 display incorrectly black-on-blue instead of white-on-blue
I have a generic HD44780 compatible 16x2 LCD display, with an already soldered on PCF8574 module. Its backlight is blue, and the characters are supposed to be white (on blue).

It is connected to a generic "Lolin" ESP8266 module which is working fine and is not related to the problem, I hope.

Using the LiquidCrystal\_I2C library available at https://github.com/lucasmaziero/LiquidCrystal\_I2C, I uploaded the simple "Hello, World" sketch provided, and it works. Used the most current libraries and Arduino IDE as of 2019-03-20.

However, the text displayed is a *very dim black-on-blue* instead of a *bright white-on-blue*.

I do not have any clue on why it happens and how to fix it (and that's my question).

What I know is that if I somehow "glitch" the display (for example by disconnecting and reconnecting the power lead) it will sometimes display gibberish, but in a *very clear white-on-blue*, so I know the LCD hardware is not defective *per se*.

I also tried a few other libraries to the same effect: LiquidCrystal\_PCF8574 and LiquidCrystal\_I2C (the version available directly from the Arduino IDE, source at https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library)

Below, the example sketch used to generate the problem. Be aware it is for the first LiquidCrystal\_I2C library I referred above, but with changes, works with the others I tried.

```
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup()
{
  // initialize the LCD
  lcd.begin(); // Init with pin default ESP8266 or ARDUINO
  // lcd.begin(0, 2); //ESP8266-01 I2C with pin 0-SDA 2-SCL
  // Turn on the blacklight and print a message.
  lcd.backlight();
  lcd.setCursor(0, 0);

#if defined(ESP8266)
  lcd.print("ESP8266");
#else
  lcd.print("ARDUINO");
#endif

  lcd.setCursor(0, 1);
  lcd.print("Hello, world!");
}

void loop()
{
  // Do nothing here...
}

```

And a photo of the anomalous display. Turning the constrast potentiometer does not help.

# Answer
> 0 votes
There is a chance that this LCD would need a negative voltage on contrast PIN. Below there is a simple schematic. You would need to provide pulses on the 'Pulse in' branch. Use Negative voltage branch and potentiometer to feed your contrast pin.

# Answer
> 1 votes
This answer is just to complement @smajli's answers posted (and accepted) before.

The problem lies in that the contrast pin has to be fed negative voltages when the module is powerered via a 3.3V supply to be able to show text in the correct white-on-blue setting and not on the faint black-on-blue.

@smajli correctly showed how the negative voltage may be generated from the normal positive supply and a pulse generator. However, in my scenario, the pulse generator was connected to the +3.3V rail instead of +5V and the pulses where generated via the ESP8266's PWM feature. Using a duty cycle of 50% it generates about -2V. I'll not reproduce his schematic here, though, but below is a photo of it assembled and in action.

The updated code is exactly the same, with only the PWM generation added inside the setup() function:

```
  pinMode(D8, OUTPUT);
  analogWrite(D8, 512);   // 10-bit!

```

Finally, the photo below illustrates the final result.

Again, thanks again to @smajli for the previous insights and answer.

P.S.: Keen readers will notice the module used now is NOT the same used when I asked the question originally. It is another generic HD44870 module, but without the I2C interface, working in 4-bit mode. However, the exact same problem (black-on-blue text) occurs when the contrast pin is set to anywhere between +3.3V and GND and is promptly solved when using negative voltage.

# Answer
> 0 votes
I have a similar LCD display (I assume it's virtually identical, hard to confirm). In my case, driving the display VCC (and SCK and SDA) at 3.3v produced the same behaviour you described (dim black text on blue background), but setting VCC to 5v gave me the correct white-on-blue display (even with SCK and SDA still driven at 3.3v, since those are the outputs of the MCU I was using).

It's curious that setting the VCC to 5v did not work in your case.

---
Tags: esp8266, i2c, display
---


# Question
Title: How to power Arduino Uno from L298N motor driver's 5v terminal?
I am trying to setup L298N motor driver controller with my Arduino. Different online schematics about how to connect them are mostly similar - but they differ in powering the Arduino from the drive controller's 5v pin.

I am connecting 7.5v to the Vin and Gnd to the motor driver controller screw terminal , and I wish the power the Arduino from the 5v screw terminal. Since I am planning to use the 5v screw terminal as output I am choosing to leave the 5v jumper on.

Here are 3 of the schematics I've found online,

1. Source Homemade-circuits:

This is what I was expecting to see. But from Arduino Uno Rev3 Faq,

```
Vin -- The input voltage to the Arduino board when it's using an external power source (as opposed to 5
volts from the USB connection or other regulated power source). You can supply voltage through this pin,
or, if supplying voltage via the power jack, access it through this pin.

5V -- This pin outputs a regulated 5V from the regulator on the board. The board can be supplied with power
either from the DC power jack (7 - 12V), the USB connector (5V), or the VIN pin of the board (7-12V).
Supplying voltage via the 5V or 3.3V pins bypasses the regulator, and can damage your board. We don't advise it.

```

*This one looks wrong to me.* I am under the assumption that Vin pin is expecting 7-12V because it's connected to voltage regulator which will cause a 2v drop. Which mean I should not connect 5v from the motor controller to Vin - making this schematic incorrect. Is my analysis correct? Here is an answer that says I can not use the 5v pin to power an Arduino since it an input pin and not an output pin.

2. Source teachmemicro:

*This one looks ok to me* since the 5v source at motor controller is a regulated source and that's what exactly Arduino is expecting on 5v pin based on aforementioned FAQ. Can I implement is safely?

3. Source Instructables:

*I do not know if it's correct or not.* Notice that the 5v screw terminal is not connected to Arduino in any way. Is it setup going to work? I am wondering where the Arduino is getting its power from?

I am wondering which schematic should I follow. I am hesitant to hook up my L298N motor driver and Arduino without without understanding why each schematic is choosing to power the Arduino differently.

# Answer
> 2 votes
Clearly, your design (last image) won't work, because as you expected, the Arduino won't have power. It is a feasible design however, if you use it while still developing and you have the USB cable connected. Because then the Arduino will draw the power for itself from there.

Vin expects 7-12V, but allows an unregulated input (which is fine for connecting a battery). You can use the 5V pin to supply power from a regulated output as well. Since (pressumably) the output of the motor driver is regulated, that could work, however I would not advise it and directly connect the battery to the VIn pin.

Connecting the 5V output of the motor driver to the VIn pin *might* work. While this will likely not destroy anything, it may be to low to drive the internal regulator, which might cause the Arduino to run on undervoltage levels. You might see weird behavior in that case (pins not correctly recognizing high from low, incorrect measurements on analog inputs or even software crashes).

# Answer
> 0 votes
I was facing same problem but I solved it by attaching L298 power pins to icsp power pins

Remember the voltage should be constant and there should not be any fluctuation other wise atmega will go in programming mode

# Answer
> -1 votes
I happened to just set up a similar circuit yesterday on a RC car. L298 is powered through a 3S lipo batterie, Uno is powered through the 5v output which also powers a servo. Uno powers a rc receiver. I burnt an Uno trying to power both servo and receiver.

---
Tags: arduino-uno, pins, l298n
---


# Question
Title: Serial ports grayed out when Arduino plugged in (MS Surface Pro X, Windows 10 Pro 21H2). How do I get Arduino IDE to recognize them?
I am helping a Windows user program an Arduino application. The computer is a Surface Pro X running Windows 10 Pro 21H2. It only has USB-C ports (which cannot be used to power or program Arduinos) so he's using this USB-C hub and a USB-type A to USB-C cable to program it. The Arduino is a Sparkfun Artemis Redboard (Cortex M4).

When he connects the Arduino to the Surface Pro, the Arduino powers up as normal, but no serial ports are visible in the Arduino IDE, and the serial port line remains grayed out.

By contrast, the same USB-C hub, cable, and Arduino can be programmed by a Mac. I run Linux and don't know anything about USB port access on either Mac or Windows, but I got the impression that manually installing drivers should not be necessary on either.

Any advice on how to get the Arduino IDE to recognize this as a serial port when plugged in to a Surface Pro?

# Answer
> 2 votes
Consider running through this Sparkfun Hookup Guide for the SparkFun RedBoard Artemis. There is a section dealing with this problem:

> My Nano is not showing up as a COM port?! Most Artemis carrier boards use the CH340C IC which is not affected by this issue. This issue is only for the Nano that uses the much smaller CH340E.

---
Tags: arduino-ide
---


title: Arduino not responding to macbook pro

text:
# Question
Title: Arduino not responding to macbook pro
When I try to upload my code onto the Arduino it just gives me the error message: "avrdude: ser\_open(): can't open device "/dev/cu.usbmodem14201": No such file or directory Problem uploading to board. See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions."

My Arduino used to function just fine. Now when a plug it in, the lights on the Arduino do not blink like they used to, and the only pins that do anything are the ones to power. It also said something like: Arduino is not optimized for mac os. It seems that the Arduino is taking in the power but not the code. here's the code:

```
int led = 13; // the pin the LED is connected to
void setup() {
  pinMode(led, OUTPUT); // Declare the LED as an output
}

void loop() {
  digitalWrite(led, HIGH); // Turn the LED on
}

```

# Answer
I had this issue and it was because the port was not set in my Arduino IDE.

I fixed it by going to Tools -\> Port, and selecting my usb device. In my case it was called /dev/cu.SLAB\_USBtoUART
> 3 votes

# Answer
I fixed it by plugging it into my other USB port (which I had previously been using)

So possibly this is caused by switching USB ports
> 2 votes

---
Tags: arduino-uno, avrdude, mac-os
---


# Question
Title: How to convert a reading to percentage in Arduino
I am using this example on how to use a photoresistor to detect the value of light that the sensor is getting but I want to convert the reading of the resistor to a percentage but I can't use the `map()` function from the Arduino docs but I can implement something similar to it

so I created this simple function

```
float photo_resistor(int pinNum)
{
    float reading = analogRead(pinNum);
    if (reading == 54)
    {
     return 0.0;
    }
    return (reading - 54)/(100/920);

}

```

as in the docs I want to use an output range from 0 to 100 and the minimum reading i got is 54 and the maximum is 974

```
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
// this becomes (x - 54)*(100 - 0 ) / ( 974 - 54) + 0;
// (x-54)/(100/920);

```

but this does not output a value from on the scale from 0-100

# Answer
You wrote:

> ```
> return (reading - 54)/(100/920);
>
> ```

In C++, `100/920` is zero. This is because, when both operands are integers, the division operator performs an integer division. You can overcome this problem by making sure that at least one of the operands is a floating point number. For instance, `100.0/920` is roughly 0.1087.

However, your division is backwards. You probably mean

```
return (reading - 54) * (100.0/920);

```
> 4 votes

---
Tags: arduino-uno, c++
---


title: TVout characters don't line up

text:
# Question
Title: TVout characters don't line up
I am messing around with the Arduino TVout library and I have created some multi-character tiles (I don't know what else to call them). Just to start out, I created a simple X that spans across 4 characters but when I print them to the screen they align correctly.

How they should align:

How they really align:

Here is the code I have so far:

Main file:

```
#include "expressions.h"
#include <TVout.h>

TVout win;
unsigned char x = 0, y = 0;

void setup() {
  win.begin(NTSC);
  win.select_font(expr8x8);
}

void loop() {
  win.clear_screen();
  x = 2, y = 5;
  print_char(0, x, y);

  win.delay(1);
}

void print_char(char c, int startx, int starty) {
  int tmpx = startx, tmpy = starty;
  for (char i = c; i < c + 4; i++) {
    win.print_char(tmpx * 8, tmpy * 8, i);
    if (++tmpx == c + 2) {
      tmpy++;
      tmpx = startx;
    }
  }
}

```

expressions.h

```
#define EXPRESSIONS8x8_H

#include <avr/pgmspace.h>
extern const unsigned char expr8x8[];

```

expressions.cpp

```
#include "expressions.h"

PROGMEM const unsigned char expr8x8[] = {
  8, 8, 0, // width, height, start

  // broken
  0x00, 0x00, 0x30, 0x38, 0x1c, 0x1e, 0x07, 0x03,
  0x00, 0x00, 0x0c, 0x1c, 0x38, 0x70, 0xe0, 0xc0,
  0x03, 0x07, 0x0e, 0x1c, 0x38, 0x38, 0x00, 0x00,
  0xc0, 0xc0, 0x70, 0x38, 0x1c, 0x0c, 0x00, 0x00,

  // happy
  0x00, 0x00, 0x00, 0x00, 0x07, 0x1f, 0x38, 0x70,
  0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0x1c, 0x0e,
  0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00
};

```

Is there something I am doing wrong? How do I fix this bug/issue?

# Answer
I believe your problem is in this line:

```
if (++tmpx == c + 2) {

```

Here you are mixing two different things:

* `c` is a character code, i.e. the index of a glyph within the `expr8x8` font
* `tmpx` is the index of a character cell (a 8×8 block of pixels) within a line of the screen

Comparing those makes little sense. And in fact, the comparison will always be false, as `c` is zero, and `tmpx` starts at 2 and increases from there.

I guess what you meant was:

```
if (++tmpx == startx + 2) {

```
> 4 votes

---
Tags: arduino-nano, library
---


# Question
Title: Why are raw data bytes not converting to ASCII, but only in one part of my program?
I am writing a program to read from the Atlas Scientific EZO-HUM, -O2, and -CO2 sensors simultaneously via the I2C protocol with an Arduino Uno. The sensors all work, but for some reason, just the O2 sensor data does not convert to ASCII text. Below is my program:

```
#include <Ezo_i2c.h>
#include <Ezo_i2c_util.h>
#include <iot_cmd.h>
#include <sequencer1.h>
#include <sequencer2.h>
#include <sequencer3.h>
#include <sequencer4.h>
#include <Wire.h>                //enable I2C.

#define HUM_address 111          //default I2C ID number for EZO Humidity sensor.
#define O2_address 108           //default I2C ID number for EZO O2 sensor.
#define CO2_address 105          //default I2C ID number for EZO CO2 sensor.

//EZO-HUM vars
//   | |
//   V V
char computerdata[32];           //we make a 32 byte character array to hold incoming data from a pc/mac/other.
byte received_from_computer = 0; //we need to know how many characters have been received.
byte serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte code = 0;                   //used to hold the I2C response code.
char Humidity_data[22];          //we make a 22-byte character array to hold incoming data from the Humidity sensor.
byte in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Humidity  sensor.
byte i = 0;                      //counter used for Humidity_data array.
int time_ = 1000;                 //used to set the delay needed to process the command sent to the EZO Humidity sensor.

//EZO-CO2 vars
//   | |
//   V V
//char CO2_computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte CO2_received_from_computer = 0; //we need to know how many characters have been received.
byte CO2_serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte CO2_code = 0;                   //used to hold the I2C response code.
char CO2_data[20];               //we make a 20-byte character array to hold incoming data from the Co2 sensor.
byte CO2_in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the Co2 sensor.
byte CO2_i = 0;                      //counter used for Co2_data array.
//int CO2_time_ = 1000;                 //used to set the delay needed to process the command sent to the EZO Co2 sensor.
int Co2_int;                     //int var used to hold the value of the Co2.

//EZO-O2 vars
//   | |
//   V V
//char O2_computerdata[20];           //we make a 20 byte character array to hold incoming data from a pc/mac/other.
byte O2_received_from_computer = 0; //we need to know how many characters have been received.
byte O2_serial_event = false;       //a flag to signal when data has been received from the pc/mac/other.
byte O2_code = 0;                   //used to hold the I2C response code.
char O2_data[20];                //we make a 20-byte character array to hold incoming data from the o2 sensor.
byte O2_in_char = 0;                //used as a 1 byte buffer to store inbound bytes from the o2 sensor.
byte O2_i = 0;                      //counter used for o2_data array.
//int O2_time_ = 600;                 //used to set the delay needed to process the command sent to the EZO o2 sensor.

char *HUM;                       //char pointer used in string parsing.
char *TMP;                       //char pointer used in string parsing.
char *NUL;                       //char pointer used in string parsing (the sensor outputs some text that we don't need).
char *DEW;                       //char pointer used in string parsing.
char *O2_reading;
char *O2_reading_2;

float HUM_float;                 //float var used to hold the float value of the humidity.
float TMP_float;                 //float var used to hold the float value of the temperatur.
float DEW_float;                 //float var used to hold the float value of the dew point.
float O2_float;
float CO2Con_float;

void setup()                    //hardware initialization.
{
  Serial.begin(9600);           //enable serial port.
  Wire.begin();                 //enable I2C port.
  while(!Serial);            //wait for serial monitor to be open
}

void serialEvent() {                                                              //this interrupt will trigger when the data coming from the serial monitor(pc/mac/other) is received.
  received_from_computer = Serial.readBytesUntil(13, computerdata, 22);           //we read the data sent from the serial monitor(pc/mac/other) until we see a <CR>. We also count how many characters have been received.
  computerdata[received_from_computer] = 0;                                       //stop the buffer from transmitting leftovers or garbage.
  serial_event = true;                                                            //set the serial event flag.
}

void loop() {                                                                     //the main loop.
  if (serial_event == true) {                                                     //if a command was sent to the EZO device.
    for (i = 0; i <= received_from_computer; i++) {                               //set all char to lower case, this is just so this exact sample code can recognize the "sleep" command.
      computerdata[i] = tolower(computerdata[i]);                                 //"Sleep" ≠ "sleep"
    }
    i=0;                                                                          //reset i, we will need it later

 //---------------------------------------------------------EZO-HUM Sensor-----------------------------------------------------------------------------//
    Wire.beginTransmission(HUM_address);                                              //call the circuit by its ID number.
    Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
    Wire.endTransmission();                                                       //end the I2C data transmission.

// Need to talk to each sensor separately. Because they're all Atlas Scientific EZO sensors, they all respond to the same commands

    if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
                                                                                //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

      Wire.requestFrom(HUM_address, 22, 1);                                           //call the circuit and request 22 bytes.
      code = Wire.read();                                                         //the first byte is the response code, we read this separately.

      switch (code) {                       //switch case based on what the response code is.
        case 1:                             //decimal 1.
          Serial.println("HUM Success");        //means the command was successful.
          break;                            //exits the switch case.

        case 2:                             //decimal 2.
          Serial.println("HUM Failed");         //means the command has failed.
          break;                            //exits the switch case.

        case 254:                           //decimal 254.
          Serial.println("HUM Pending");        //means the command has not yet been finished calculating.
          break;                            //exits the switch case.

        case 255:                           //decimal 255.
          Serial.println("HUM No Data");        //means there is no further data to send.
          break;                            //exits the switch case.
    }

    while (Wire.available()) {              //are there bytes to receive.
      in_char = Wire.read();                //receive a byte.
      Humidity_data[i] = in_char;           //load this byte into our array.
      //Serial.println((int)in_char);
      i += 1;                               //incur the counter for the array element.
      if (in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
    if (computerdata[0] == 'r') string_pars();    //uncomment this function if you would like to break up the comma separated string into its individual parts.
  }

 //---------------------------------------------------------EZO-O2 Sensor-----------------------------------------------------------------------------//

    Wire.beginTransmission(O2_address);                                           //call the circuit by its ID number.
    Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
    Wire.endTransmission();                                                       //end the I2C data transmission.

    if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
                                                                                //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

      Wire.requestFrom(O2_address, 22, 1);                                           //call the circuit and request 22 bytes.
      O2_code = Wire.read();                                                         //the first byte is the response code, we read this separately.

      switch (O2_code) {                       //switch case based on what the response code is.
        case 1:                             //decimal 1.
          Serial.println("O2 Sensor Success");        //means the command was successful.
          break;                            //exits the switch case.

        case 2:                             //decimal 2.
          Serial.println("O2 Sensor Failed");         //means the command has failed.
          break;                            //exits the switch case.

        case 254:                           //decimal 254.
          Serial.println("O2 Sensor Pending");        //means the command has not yet been finished calculating.
          break;                            //exits the switch case.

        case 255:                           //decimal 255.
          Serial.println("O2 Sensor No Data");        //means there is no further data to send.
          break;                            //exits the switch case.
    }

    while (Wire.available()) {              //are there bytes to receive.
      O2_in_char = Wire.read();                //receive a byte.
      O2_data[i] = O2_in_char;           //load this byte into our array.
      Serial.println((int)O2_in_char);
      Serial.println(O2_data);
      i += 1;                               //incur the counter for the array element.
      if (O2_in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
//    Serial.print("O2 Concentration:");                      //This code doesn't output any information, although the program receives bytes which display in the while loop.
//    Serial.println(O2_data);
//    Serial.println();

    if (computerdata[0] == 'r') O2_string_pars();             //This code also doesn't output any information.
  }

 //---------------------------------------------------------EZO-CO2 Sensor-----------------------------------------------------------------------------//

    Wire.beginTransmission(CO2_address);                                          //call the circuit by its ID number.
    Wire.write(computerdata);                                                     //transmit the command that was sent through the serial port.
    Wire.endTransmission();                                                       //end the I2C data transmission.

    if (strcmp(computerdata, "sleep") != 0) {                                     //if the command that has been sent is NOT the sleep command, wait the correct amount of time and request data.
                                                                                //if it is the sleep command, we do nothing. Issuing a sleep command and then requesting data will wake the Humidity  sensor.

      delay(time_);                                                               //wait the correct amount of time for the circuit to complete its instruction.

      Wire.requestFrom(CO2_address, 22, 1);                                           //call the circuit and request 22 bytes.
      CO2_code = Wire.read();                                                         //the first byte is the response code, we read this separately.

      switch (CO2_code) {                       //switch case based on what the response code is.
        case 1:                             //decimal 1.
          Serial.println("CO2 Sensor Success");        //means the command was successful.
          break;                            //exits the switch case.

        case 2:                             //decimal 2.
          Serial.println("CO2 Sensor Failed");         //means the command has failed.
          break;                            //exits the switch case.

        case 254:                           //decimal 254.
          Serial.println("CO2 Sensor Pending");        //means the command has not yet been finished calculating.
          break;                            //exits the switch case.

        case 255:                           //decimal 255.
          Serial.println("CO2 Sensor No Data");        //means there is no further data to send.
          break;                            //exits the switch case.
    }

    while (Wire.available()) {              //are there bytes to receive.
      CO2_in_char = Wire.read();                //receive a byte.
      CO2_data[i] = CO2_in_char;           //load this byte into our array.
      //Serial.println((int)CO2_in_char);
      i += 1;                               //incur the counter for the array element.
      if (CO2_in_char == 0) {                   //if we see that we have been sent a null command.
        i = 0;                              //reset the counter i to 0.
        break;                              //exit the while loop.
      }
    }
    Serial.print("CO2 Concentration:");
    Serial.println(CO2_data);
  }

  serial_event = false;                     //reset the serial event flag

//  if (computerdata[0] == 'r') string_pars();    //uncomment this function if you would like to break up the comma separated string into its individual parts.
}
   }

void string_pars() {                        //this function will break up the CSV string into its 3 individual parts. HUM|TMP|DEW.
                                            //this is done using the C command “strtok”.

  HUM = strtok(Humidity_data, ",");         //let's pars the string at each comma.
  TMP = strtok(NULL, ",");                  //let's pars the string at each comma.
  NUL = strtok(NULL, ",");                  //let's pars the string at each comma (the sensor outputs the word "DEW" in the string, we dont need it.
  DEW = strtok(NULL, ",");                  //let's pars the string at each comma.

  Serial.println();                          //this just makes the output easier to read by adding an extra blank line.

  Serial.print("HUM:");                      //we now print each value we parsed separately.
  Serial.println(HUM);                       //this is the humidity value.

  Serial.print("Air TMP:");                  //we now print each value we parsed separately.
  Serial.println(TMP);                       //this is the air temperatur value.

  Serial.print("DEW:");                      //we now print each value we parsed separately.
  Serial.println(DEW);                       //this is the dew point.
  Serial.println();

  //uncomment this section if you want to take the values and convert them into floating point number.
  /*
    HUM_float=atof(HUM);
    TMP_float=atof(TMP);
    DEW_float=atof(DEW);
  */
}

void O2_string_pars() {                        //this function will break up the CSV string
                                            //this is done using the C command “strtok”.

  O2_reading = strtok(O2_data, ",");         //let's pars the string at each comma.
//  O2_reading_2 = strtok(NULL, ",");

  Serial.println();                          //this just makes the output easier to read by adding an extra blank line.

  Serial.print("O2 Concentration: ");
  Serial.println(O2_reading);
//  Serial.println("O2 extra info: ");
//  Serial.print(O2_reading_2);

}

```

The following is the output from the program:

> HUM Success
>
> HUM:45.39
>
> Air TMP:23.61
>
> DEW:11.16
>
> O2 Sensor Success
>
> 50
>
> 48
>
> 46
>
> 56
>
> 53
>
> 0
>
> O2 Concentration:
>
> CO2 Sensor Success
>
> CO2 Concentration:599

# Answer
You are relying on a NULL byte being received to reset your `i` pointer variable. If that NULL never arrives for whatever reason you won't be writing your new data to the start of your next array.

You should *always* reset the counter before receiving new data regardless of what you have just received.
> 2 votes

---
Tags: arduino-uno, i2c
---


# Question
Title: What sensor do I use to measure the intensity of direct sunlight?
I'm trying to measure how bright the day is on a particular day to see how it affects plant growth. The brightest sun can be 120,000 lux. It possible to measure such a large brightness? What sensor do I use?

The best options I've found is the BH1750FVI since its sheet says, "\[i\]t is possible to detect min. 0.11 lx, max. 100000 lx"

However, it still doesn't go high enough.

**Note:** I live "only" 3,494 km (2171 miles) from the equator, and it can get fairly bright here.

# Answer
You can use a photo resistor. It is also known as an LDR (Light dependent resistors) and here is a great tutorial to do just that. You can also find a conversion from the 8-bit analog value to lumens if you wish. Here is a tutorial:

https://www.instructables.com/id/Measuring-Light-Using-Light-Sensor/

You can also use a LUX which is the advanced version of a LDR. Here is a tutorial:

https://www.instructables.com/id/How-to-Measure-LUX-With-Arduino/
> 3 votes

# Answer
What about SiLabs SI11xx Sensors? Some of them are designed for direct sunlight.
> 2 votes

---
Tags: sensors
---


title: A bug with multiple IR detectors

text:
# Question
Title: A bug with multiple IR detectors
I have a device power by arduino nano atmega328. The idea of this HW is to detects dropped seed (corn, oil bean etc.) and to count it.

I wrote initial code, but id does not work in an expected way. it increments one count "channel" (I have 8 pairs of IR diodes 3mm) automatically, and passing it does not detect.

Here is the code maybe, someone has some similar experience and maybe help me to refactor the code.

```
#include<wire.h>
#include<Adafruit_SSD1306.h>

int irPin1 = 1;
int irPin2 = 2;
int irPin3 = 3;
int irPin4 = 4;
int irPin5 = 5;
int irPin6 = 6;
int irPin7 = 7;
int irPin8 = 8;

int count1,count2,count3,count4,count5,count6,count7,count8, count = 0;
boolean state = true;

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

void loop(){
if(!digitalRead(irPin1) && state)
 {
   count1++;
   state = false;
   Serial.print("count1: ");
   Serial.println(count1);
   delay(200);
 }

if(digitalRead(irPin1))
  {
    state=true;
    delay(100);
  }

if(!digitalRead(irPin2) && state)
 {
   count2++;
   state = false;
   Serial.print("count2: ");
   Serial.println(count2);
   delay(200);
 }

if(digitalRead(irPin2))
  {
    state=true;
    delay(100);
  }

  if(!digitalRead(irPin3) && state)
 {
   count3++;
   state = false;
   Serial.print("count3: ");
   Serial.println(count3);
   delay(200);
 }

if(digitalRead(irPin3))
  {
    state=true;
    delay(100);
  }

    if(!digitalRead(irPin4) && state)
 {
   count4++;
   state = false;
   Serial.print("count4: ");
   Serial.println(count4);
   delay(200);
 }

if(digitalRead(irPin4))
  {
    state=true;
    delay(100);
  }

 if(!digitalRead(irPin5) && state)
 {
   count5++;
   state = false;
   Serial.print("count5: ");
   Serial.println(count5);
   delay(200);
 }

if(digitalRead(irPin5))
  {
    state=true;
    delay(100);
  }
 if(!digitalRead(irPin6) && state)
 {
   count6++;
   state = false;
   Serial.print("count6: ");
   Serial.println(count6);
   delay(200);
 }

if(digitalRead(irPin6))
  {
    state=true;
    delay(100);
  }
 if(!digitalRead(irPin7) && state)
 {
   count7++;
   state = false;
   Serial.print("count7: ");
   Serial.println(count7);
   delay(200);
 }

if(digitalRead(irPin7))
  {
    state=true;
    delay(100);
  }

 if(!digitalRead(irPin8) && state)
 {
   count8++;
   state = false;
   Serial.print("count8: ");
   Serial.println(count8);
   delay(200);
 }

if(digitalRead(irPin8))
  {
    state=true;
    delay(100);
  }
count= count1+count2+count3+count4+count5+count6+count7+count8;
}

```

I work in platformIO.

# Answer
Use arrays instead of a copy/paste coding style. Use millis() instead of delay() statements to eliminate blocking code. Explicitly configure input pins.

compiles, but untested:

```
uint8_t irPin[ 8 ] = { 2, 3, 4, 5, 6, 7, 8, 9 } ; // set the sensor pins here . Avoid 0 and 1.
uint16_t seedCount[ 8 ] = { 0 } ;
uint32_t lastSeedAtMs[ 8 ] = { 0 } ;
const uint32_t lockOutTimeMs = 200UL ; // milliseconds - prevent 1 seed generating multiple counts

void setup() {
  Serial.begin(9600);
    for ( uint8_t channel = 0; channel < 8 ; channel++ ) {
      pinMode( irPin[ channel ] , INPUT_PULLUP ) ;  // configure all input pins
    }
}

void loop() {
  for ( uint8_t channel = 0; channel < 8 ; channel++ ) {
    if ( digitalRead( irPin[ channel ] ) == LOW ) {  // sensor active low
      if ( millis() - lastSeedAtMs[ channel ] > lockOutTimeMs )  {  // if X ms passed since last detection on this channel
        seedCount[ channel ] ++ ;
        lastSeedAtMs[channel ] = millis() ;
        Serial.print("count");
        Serial.print(channel);
        Serial.print(": ");
        Serial.println( seedCount[ channel ] );
      }
    }
  }
}

```
> 1 votes

---
Tags: arduino-nano, adafruit
---


# Question
Title: Is possible to use ESP-NOW in LR mode (long range) simultaneously with WIFI STA (to connect to internet over wifi)
I am building esp-now gateway with mqtt but need long distance (200 meters). I try to use LR mode but when I enable de LR mode I lost connection with WiFi.

Is licit to make use of LR and STA at the same time?

# Answer
> 1 votes
you can easily use both ESPnow and WiFi - you just configure it as WiFi.mode(WIFI\_MODE\_APSTA); no need to switch between AP and STA And I have not experienced any delays for my gateway - sending MQTT message over WiFi to MQTT broker takes 6ms

---
Tags: wifi, esp32
---


title: Assign a list of char *

text:
# Question
Title: Assign a list of char *
Explain in a simple example. How to pass a `char*` to a function?

```
#define name1 "ABCD"
#define name2 "EFGH"
#define name3 "HIJK"

char *list[3] = {};

void printList(char *l, int x) {
  for (int i = 0; i < x; i++) {
    Serial.println(l[i]);
  }

}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("start");
  list[0] = name1;
  list[1] = name2;
  list[2] = name3;

  printList(list, 3);

}

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

}

```

I get an error:

```
/home/guy/Documents/Dropbox/Arduino/sketch_jun12a/sketch_jun12a.ino: In function 'void setup()':
sketch_jun12a:24:13: error: cannot convert 'char**' to 'char*'
   24 |   printList(list, 3);
      |             ^~~~
      |             |
      |             char**
/home/guy/Documents/Dropbox/Arduino/sketch_jun12a/sketch_jun12a.ino:7:22: note:   initializing argument 1 of 'void printList(char*, int)'
    7 | void printList(char *l, int x) {
      |                ~~~~~~^
exit status 1
cannot convert 'char**' to 'char*'

```

# Answer
Just change this:

```
void printList(char *l, int x) {

```

to this:

```
void printList(char **l, int x) {

```

OK, this deserves some explanation...

In C and C++, when you **use** (not when you *define*) an array identifier, it decays to a pointer to its first element. In this case,

```
char *list[3] = {};

```

is an array of pointers to `char`. When you use it here:

```
printList(list, 3);

```

it decays to a pointer to pointer to `char`. Thus the double `*` needed in the parameter declaration.

**Side note**: to get really correct C++, you should replace every instance of `char` by `const char`. This is because the characters in question belong to string literals, and you are not allowed to modify a string literal at run time.
> 7 votes

---
Tags: char
---


# Question
Title: Enable full float-capable snprintf() library with PlatformIO
I want to use snprintf() to format floats to a string.

I know the "normal" version of Arduino's avrlibc had all the float-formatting code removed to make it smaller.

I also know that at some point in the fairly recent past, it became possible to force gcc to use an alternate (forked?) larger Arduino avrlibc that had all the float-formatting functionality that was originally removed put back in.

However... I'm still trying to find an actual explanation of *how to **do** that* for an Arduino project using **PlatformIO**.

I found a clue someplace where someone said, "change linker rules in platform.txt file to enable floating point xxprintf()" (which hopefully enables floating point support in other float-to-string functions as well).

Problem #1: `platform.txt` appears to be global rather than local to this one project. There's no file named "platform.txt" anywhere in the project's directory.

Problem #2: I **do** have *several dozen* files on my computer named `platform.txt`... I don't know which one is the one that actually matters to PlatformIO, and I don't know enough about PlatformIO's internals to know how to figure out which `platform.txt` is the one that *matters*.

Problem #3: Even if I manage to figure out which `platform.txt` is the one I need to modify, I still don't know what exact modifications actually need to be *made*.

---

Update: I stumbled over a thread in Arduino's Issue discussion ("Sprintf for floats on Arduino Mega 293") that said to append the text quoted further down to boards.txt. The relevant line appears to be `mega.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt`

So... I'm guessing that what I need to put somewhere in `platform.txt` (once I figure out which `platform.txt` is the one that matters) is `-Wl,-u,vfprintf -lprintf_flt`

```
##############################################################

menu.printf=AVR printf Version
menu.scanf=AVR scanf Version

yun.menu.printf.default=Default printf
yun.menu.printf.default.avr_printf_flags=
yun.menu.printf.full=Full printf
yun.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
yun.menu.printf.minimal=Minimal printf
yun.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

yun.menu.scanf.default=Default scanf
yun.menu.scanf.default.avr_scanf_flags=
yun.menu.scanf.full=Full scanf
yun.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
yun.menu.scanf.minimal=Minimal scanf
yun.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

yun.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

uno.menu.printf.default=Default printf
uno.menu.printf.default.avr_printf_flags=
uno.menu.printf.full=Full printf
uno.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
uno.menu.printf.minimal=Minimal printf
uno.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

uno.menu.scanf.default=Default scanf
uno.menu.scanf.default.avr_scanf_flags=
uno.menu.scanf.full=Full scanf
uno.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
uno.menu.scanf.minimal=Minimal scanf
uno.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

uno.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

diecimila.menu.printf.default=Default printf
diecimila.menu.printf.default.avr_printf_flags=
diecimila.menu.printf.full=Full printf
diecimila.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
diecimila.menu.printf.minimal=Minimal printf
diecimila.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

diecimila.menu.scanf.default=Default scanf
diecimila.menu.scanf.default.avr_scanf_flags=
diecimila.menu.scanf.full=Full scanf
diecimila.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
diecimila.menu.scanf.minimal=Minimal scanf
diecimila.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

diecimila.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

nano.menu.printf.default=Default printf
nano.menu.printf.default.avr_printf_flags=
nano.menu.printf.full=Full printf
nano.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
nano.menu.printf.minimal=Minimal printf
nano.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

nano.menu.scanf.default=Default scanf
nano.menu.scanf.default.avr_scanf_flags=
nano.menu.scanf.full=Full scanf
nano.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
nano.menu.scanf.minimal=Minimal scanf
nano.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

nano.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

mega.menu.printf.default=Default printf
mega.menu.printf.default.avr_printf_flags=
mega.menu.printf.full=Full printf
mega.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
mega.menu.printf.minimal=Minimal printf
mega.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

mega.menu.scanf.default=Default scanf
mega.menu.scanf.default.avr_scanf_flags=
mega.menu.scanf.full=Full scanf
mega.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
mega.menu.scanf.minimal=Minimal scanf
mega.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

mega.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

megaADK.menu.printf.default=Default printf
megaADK.menu.printf.default.avr_printf_flags=
megaADK.menu.printf.full=Full printf
megaADK.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
megaADK.menu.printf.minimal=Minimal printf
megaADK.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

megaADK.menu.scanf.default=Default scanf
megaADK.menu.scanf.default.avr_scanf_flags=
megaADK.menu.scanf.full=Full scanf
megaADK.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
megaADK.menu.scanf.minimal=Minimal scanf
megaADK.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

megaADK.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

leonardo.menu.printf.default=Default printf
leonardo.menu.printf.default.avr_printf_flags=
leonardo.menu.printf.full=Full printf
leonardo.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
leonardo.menu.printf.minimal=Minimal printf
leonardo.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

leonardo.menu.scanf.default=Default scanf
leonardo.menu.scanf.default.avr_scanf_flags=
leonardo.menu.scanf.full=Full scanf
leonardo.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
leonardo.menu.scanf.minimal=Minimal scanf
leonardo.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

leonardo.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

micro.menu.printf.default=Default printf
micro.menu.printf.default.avr_printf_flags=
micro.menu.printf.full=Full printf
micro.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
micro.menu.printf.minimal=Minimal printf
micro.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

micro.menu.scanf.default=Default scanf
micro.menu.scanf.default.avr_scanf_flags=
micro.menu.scanf.full=Full scanf
micro.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
micro.menu.scanf.minimal=Minimal scanf
micro.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

micro.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

esplora.menu.printf.default=Default printf
esplora.menu.printf.default.avr_printf_flags=
esplora.menu.printf.full=Full printf
esplora.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
esplora.menu.printf.minimal=Minimal printf
esplora.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

esplora.menu.scanf.default=Default scanf
esplora.menu.scanf.default.avr_scanf_flags=
esplora.menu.scanf.full=Full scanf
esplora.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
esplora.menu.scanf.minimal=Minimal scanf
esplora.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

esplora.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

mini.menu.printf.default=Default printf
mini.menu.printf.default.avr_printf_flags=
mini.menu.printf.full=Full printf
mini.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
mini.menu.printf.minimal=Minimal printf
mini.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

mini.menu.scanf.default=Default scanf
mini.menu.scanf.default.avr_scanf_flags=
mini.menu.scanf.full=Full scanf
mini.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
mini.menu.scanf.minimal=Minimal scanf
mini.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

mini.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

ethernet.menu.printf.default=Default printf
ethernet.menu.printf.default.avr_printf_flags=
ethernet.menu.printf.full=Full printf
ethernet.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
ethernet.menu.printf.minimal=Minimal printf
ethernet.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

ethernet.menu.scanf.default=Default scanf
ethernet.menu.scanf.default.avr_scanf_flags=
ethernet.menu.scanf.full=Full scanf
ethernet.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
ethernet.menu.scanf.minimal=Minimal scanf
ethernet.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

ethernet.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

fio.menu.printf.default=Default printf
fio.menu.printf.default.avr_printf_flags=
fio.menu.printf.full=Full printf
fio.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
fio.menu.printf.minimal=Minimal printf
fio.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

fio.menu.scanf.default=Default scanf
fio.menu.scanf.default.avr_scanf_flags=
fio.menu.scanf.full=Full scanf
fio.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
fio.menu.scanf.minimal=Minimal scanf
fio.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

fio.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

bt.menu.printf.default=Default printf
bt.menu.printf.default.avr_printf_flags=
bt.menu.printf.full=Full printf
bt.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
bt.menu.printf.minimal=Minimal printf
bt.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

bt.menu.scanf.default=Default scanf
bt.menu.scanf.default.avr_scanf_flags=
bt.menu.scanf.full=Full scanf
bt.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
bt.menu.scanf.minimal=Minimal scanf
bt.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

bt.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

LilyPadUSB.menu.printf.default=Default printf
LilyPadUSB.menu.printf.default.avr_printf_flags=
LilyPadUSB.menu.printf.full=Full printf
LilyPadUSB.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
LilyPadUSB.menu.printf.minimal=Minimal printf
LilyPadUSB.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

LilyPadUSB.menu.scanf.default=Default scanf
LilyPadUSB.menu.scanf.default.avr_scanf_flags=
LilyPadUSB.menu.scanf.full=Full scanf
LilyPadUSB.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
LilyPadUSB.menu.scanf.minimal=Minimal scanf
LilyPadUSB.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

LilyPadUSB.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

lilypad.menu.printf.default=Default printf
lilypad.menu.printf.default.avr_printf_flags=
lilypad.menu.printf.full=Full printf
lilypad.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
lilypad.menu.printf.minimal=Minimal printf
lilypad.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

lilypad.menu.scanf.default=Default scanf
lilypad.menu.scanf.default.avr_scanf_flags=
lilypad.menu.scanf.full=Full scanf
lilypad.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
lilypad.menu.scanf.minimal=Minimal scanf
lilypad.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

lilypad.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

pro.menu.printf.default=Default printf
pro.menu.printf.default.avr_printf_flags=
pro.menu.printf.full=Full printf
pro.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
pro.menu.printf.minimal=Minimal printf
pro.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

pro.menu.scanf.default=Default scanf
pro.menu.scanf.default.avr_scanf_flags=
pro.menu.scanf.full=Full scanf
pro.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
pro.menu.scanf.minimal=Minimal scanf
pro.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

pro.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

atmegang.menu.printf.default=Default printf
atmegang.menu.printf.default.avr_printf_flags=
atmegang.menu.printf.full=Full printf
atmegang.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
atmegang.menu.printf.minimal=Minimal printf
atmegang.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

atmegang.menu.scanf.default=Default scanf
atmegang.menu.scanf.default.avr_scanf_flags=
atmegang.menu.scanf.full=Full scanf
atmegang.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
atmegang.menu.scanf.minimal=Minimal scanf
atmegang.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

atmegang.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

robotControl.menu.printf.default=Default printf
robotControl.menu.printf.default.avr_printf_flags=
robotControl.menu.printf.full=Full printf
robotControl.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
robotControl.menu.printf.minimal=Minimal printf
robotControl.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

robotControl.menu.scanf.default=Default scanf
robotControl.menu.scanf.default.avr_scanf_flags=
robotControl.menu.scanf.full=Full scanf
robotControl.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
robotControl.menu.scanf.minimal=Minimal scanf
robotControl.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

robotControl.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

robotMotor.menu.printf.default=Default printf
robotMotor.menu.printf.default.avr_printf_flags=
robotMotor.menu.printf.full=Full printf
robotMotor.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
robotMotor.menu.printf.minimal=Minimal printf
robotMotor.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

robotMotor.menu.scanf.default=Default scanf
robotMotor.menu.scanf.default.avr_scanf_flags=
robotMotor.menu.scanf.full=Full scanf
robotMotor.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
robotMotor.menu.scanf.minimal=Minimal scanf
robotMotor.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

robotMotor.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

gemma.menu.printf.default=Default printf
gemma.menu.printf.default.avr_printf_flags=
gemma.menu.printf.full=Full printf
gemma.menu.printf.full.avr_printf_flags=-Wl,-u,vfprintf -lprintf_flt
gemma.menu.printf.minimal=Minimal printf
gemma.menu.printf.minimal.avr_printf_flags=-Wl,-u,vfprintf -lprintf_min

gemma.menu.scanf.default=Default scanf
gemma.menu.scanf.default.avr_scanf_flags=
gemma.menu.scanf.full=Full scanf
gemma.menu.scanf.full.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_flt
gemma.menu.scanf.minimal=Minimal scanf
gemma.menu.scanf.minimal.avr_scanf_flags=-Wl,-u,vfscanf -lscanf_min

gemma.compiler.c.elf.extra_flags={avr_printf_flags} {avr_scanf_flags}

##############################################################

```

### Update 2:

I found what appears to be the solution & posted it as my own answer, but I'm going to hold off for a day or two to test it thoroughly and make sure it actually works.

# Answer
I finally found the answer at https://github.com/sstaub/LCDi2c

When using PlatformIO, add the following line to `platformio.ini` to enable full support for floats to printf():

`build_flags = -Wl,-u,vfprintf -lprintf_flt -lm`

### Caution:

This solution increases the amount of required flash by at least 2k. If you're using a Mega2560, you probably have flash to burn and really don't care. If you're using an Uno, Leonardo, Nano, or some other smaller AVR-based variant... it might matter, and you might *have* to care.

Tip: if the Nano/Leonardo/Uno doesn't have enough flash or SRAM, but you don't have space for a full-blown Mega2560, consider the "Arduino Nano Every". It uses the ATMega4809, with 48k flash and 6k SRAM.
> 2 votes

---
Tags: string, float, platformio
---


# Question
Title: How often should we poll the 74HC165 if we wish to detect 'button' presses?
I am going to either chain 4 shift registers, or connect 4 shift registers to an ESP32 that is connected to a computer with bluetooth.

I understand at 3.3 volts, the 74HC165 can run at a clock speed of up to 18mhz. (5mhz at 2v, 25mhz at 4v).

What is normal for monitoring events on the shift registers? Is it normal to endlessly poll the shift registers? Or is a short delay between each read possible and/or desirable?

I cant imagine a reason for wanting to check for "events" (button presses, etc...) 1 million times per second. We could I guess, I just don't know if we should.

(I am new to the ESP32, so I am not sure how maintaining a bluetooth connection impacts things)

# Answer
> 3 votes
For this you can employ the *nyquist-shannon* theory for signal sampling.

In short it states that "to sample a signal frequency of X you need at least 2x X samples per second".

So if you know how long a button will be pressed for (or released for, whichever is faster, i.e., the "highest frequency component of interest") then you know you need to sample with an interval of *at most half* that time.

So for a button that you may press for 100ms you know you need to sample at most every 50ms, preferably faster.

# Answer
> 1 votes
Yes, it's pretty normal to endlessly poll the buttons. Even the original NES controller did it exactly that way, its protocol works exactly like you'd talk to a shift register. Majenko alredy gave an answer on a good polling frequency, here's the additional hardware you'd need to work with interrupts instead of polling:

You'd need to add a bunch of OR gates (or AND gates if your buttons pull down instead of up) in "parallel" to your shift registers, so that you've got one signal with the semantics "(at least) one of the buttons have been pressed".

This signal then can be connected to the SH/LD input of your shift registers, triggering the shift registers to load (i.e. sample and hold) the inputs. In addition, it needs to be connected to one GPIO of your Arduino/ESP, to which you connect an interrupt handler on the software side. That interrupt handler then polls the shift register once (or sets a flag that causes your main loop to poll it). You may need an additional gate and GPIO to allow the polling routine to keep SH/LD HIGH while polling, depending on your use case and how bouncy your buttons are.

You could even use that signal to wake the ESP from deep sleep, poll the buttons once, do whatever needs to be done as a reaction to that button, then go back to deep sleep.

In conclusion: Endless polling is mostly the way to go, because of the hardware overhead to implement an interrupt solution.

---
Tags: esp32, shift-register
---


# Question
Title: Fluctuation in 4 half bridge load cell via combinator
I'm currently using a Sparkfun 4 Half-Bridge load sensor (50 Kg) with combinator and amplifier both are from the Sparkfun. Link:https://www.sparkfun.com/products/10245 (For Load Sensors)https://www.sparkfun.com/products/13878 (Combinator) https://www.sparkfun.com/products/13879 (HX711) Our application requires long-term use i.e 8 to 10 hours of load application and monitoring the weight change during this time. Is this possible to achieve the above requirement using these chips/amplifiers? As we have experienced a drift in the readings if a weight is placed for more than approx. 3 minutes. We are using 4 half-bridge sensors, a combinator, and an amplifier.The issues I am tackling right now are,

1. Zero balance: Load sensor value exponentially increases or decreases after calibration(this is a cyclic thing and keeps happening). The error ranges usually from -20g to +40g.
2. Drift in reading: When the load is placed and kept for more than 3 minutes a drift is observed which increases with time and rises up to 50 to 60g. Can you please assist in this matter? have used different libraries. Results are the same.

# Answer
> 0 votes
Consider a change in temperature either the cause or partially the cause for weight drift. This supplier web page talks about load cell temperature compensation. There they consider a 2000lb load cell. Their chart infers a 20 degree Fahrenheit change can cause an temperature uncompensated load cell to change about 1.5lb.

---
Tags: arduino-uno, arduino-mega, library, communication, calibration
---


# Question
Title: ESP8266 - Can't upload or use Serial Monitor - Ubuntu 22.04 LTS
When trying to use the ESP8266 Node MCU or Multiple Feather Huzzah's I get the following error. I can program Arduino Uno & Mega without issue.

```
warning: espcomm_sync failed
error: espcomm_open failed
error: espcomm_upload_mem failed
error: espcomm_upload_mem failed

```

I have tried all the many fixes on the web, the real issue is that all of these devices work fine with a windows machine. Also I use VMM and QEMU, I built a Windows 10 VM and Ubuntu 20.04 - When I share ttyS0 with either of these VM's I can program the 8266 just fine, but I can not directly from my host running 22.04. I can work with the VM's but I would rather not.

Any help would be appreciated.

Thank you

# Answer
I found this solution in a separate post - it fixed my issue and I was able to replicate and validate this worked on a second 22.04 machine.

```
systemctl stop brltty-udev.service
sudo systemctl mask brltty-udev.service
systemctl stop brltty.service
systemctl disable brltty.service

```
> 2 votes

---
Tags: arduino-ide, ubuntu, feather
---