body:
I'm trying to read and write to this [MAX16826 LED controller evaluation board][1] through I2C. There is no specific library for this IC so I have to use the Wire library and the datasheet to try to communicate with it. My use of this library is limited and my test code doesn't seem to work. While I wait for the MAXIM tech support, I thought I'd ask here.

According to the IC datasheet, the **7-bit address is 0x58** while the **8-bit read and write addresses are 0xB1 & 0xB0 respectively**. I was able to detect the 7-bit address using the i2c_scanner example sketch but after a while, it seems to lose communications with it. Attached below is a picture of what I meant.

[![Serial Monitor i2c scanner][2]][2]

My code tries to read and write to the MAX16826's register 0x00 by following along the Wire API and the datasheet. However the results I got out of the register from Wire.requestFrom() was 255 when it should be 0. Not sure what's exactly going on. I read through the Wire API but still not sure how to detect the ack bits from the slave IC.

Here are the relevant key information from the datasheet:

[![Read Write Format][3]][3]
[![Register Table][4]][4]

Here is my Arduino test code. I did remove parts that were extra and unnecessary for simplicity purposes:

    #include <Arduino.h>
    #include <Wire.h>

    #define MaxAddr 0x58        //7-bit address
    #define MaxAddrRead 0xB1    //8-bit read address
    #define MaxAddrWrite 0xB0   //8-bit write address
    #define enPin 12            //Arduino pin for IC enable

    //protoype function declarations
    void basicWriteTest();
    void basicReadTest();

    void setup() {
      Serial.begin(115200);
      Wire.begin();
      //enable the MAX16826 IC
      pinMode(enPin, OUTPUT);
      digitalWrite(enPin, HIGH);
      //wait for the serial monitor to be opened
      while (!Serial);
      delay(1500);
      //function to write to register 0x00
      basicWriteTest();
    }

    void loop() {
      //function to write the value at register 0x00
      basicReadTest();
      delay(1500);
    }

    void basicWriteTest(){
      Wire.beginTransmission(MaxAddrWrite);
      //write to register 0x00
      Wire.write(0x00);
      //write the value 0x00 to that register
      Wire.write(0x00);
      Wire.endTransmission();
    }

    void basicReadTest(){
      Wire.beginTransmission(MaxAddrRead);
      Wire.write(0x00);
      Wire.endTransmission();

      Wire.requestFrom(MaxAddrRead, 1);
      if (Wire.available() <= 1){
        uint8_t data = Wire.read();
        Serial.println("Data = " + String(data));

        float mV = float(316) - 1.72 * (data & 0x7F);
        float mA = mV/2.2;

        Serial.println("mV = " + String(mV));
        Serial.println("mA = " + String(mA));
      }else{
        Serial.println("Failed to get read on MAX!");
      }
    }

  [1]: https://www.mouser.ca/ProductDetail/Maxim-Integrated/MAX16826EVKIT+?qs=LbY2dft4ljAJCiFiW%2Bs8Xg==
  [2]: https://i.stack.imgur.com/8YSqI.jpg
  [3]: https://i.stack.imgur.com/H27JM.jpg
  [4]: https://i.stack.imgur.com/90BBW.jpg

title: Help with the Arduino Wire I2C Communication with MAX16826 LED Controller IC

Answers: 0


body:
I used the TCS3200 sensor to read the RGB color values.First, I calibrated the sensor with white and black colors.The sensor detects red, blue, and green correctly, but does not give an accurate value.For example, green is 105 190 150 instead of 0 255 0 .  I have to recognize the brown copper with the RGB value 138 73 49 .But it seems that I can not recognize this color with this method.I will be grateful if you can guide me.

    #define S0 4
    #define S1 5
    #define S2 6
    #define S3 7
    #define sensorOut 8
    int redPW = 0 ;
    int greenPW = 0 ;
    int bluePW = 0 ;

    void setup() {
      // Set S0 - S3 as outputs
      pinMode(S0, OUTPUT);
      pinMode(S1, OUTPUT);
      pinMode(S2, OUTPUT);
      pinMode(S3, OUTPUT);
      pinMode(sensorOut, INPUT);

      // Setting frequency-scaling to 20%
      digitalWrite(S0,HIGH);
      digitalWrite(S1,LOW);

      Serial.begin(9600);

    }

    void loop() {

    // Calibration Values
    int redMin=40;// Red minimum value
    int redMax=470;//346 Red maximum value
    int greenMin=40;// Green minimum value
    int greenMax=510;//348 Green maximum value
    int blueMin=30;// Blue minimum value
    int blueMax=390;//262 Blue maximum value

    int redValue;
    int greenValue;
    int blueValue;

    //Read Red Pulse Width
    digitalWrite(S2,LOW);
    digitalWrite(S3,LOW);
    // Read the output Pulse Width
    redPW = pulseIn(sensorOut,LOW);
    redValue=map(redPW, redMin,redMax,255,0);
    delay(200);

    // Read Green Pulse Width
    digitalWrite(S2,HIGH);
    digitalWrite(S3,HIGH);
    // Read the output Pulse Width
    greenPW = pulseIn(sensorOut,LOW);
    greenValue=map(greenPW, greenMin,greenMax,255,0);
    delay(200);

    // Read Blue Pulse Width
    digitalWrite(S2,LOW);
    digitalWrite(S3,HIGH);
    // Read the output Pulse Width
    bluePW = pulseIn(sensorOut,LOW);
    blueValue=map(bluePW, blueMin,blueMax,255,0);
    delay(200);

    // Print output to Serial Monitor
    Serial.print("redValue = ");
    Serial.print(redValue);
    Serial.print(" - greenValue = ");
    Serial.print(greenValue);
    Serial.print(" - blueValue = ");
    Serial.println(blueValue);

    }

title: Requires accurate RGB color values by the tcs3200 RGB color sensore

Answers: 1

body:
As I said, you MUST either
  - know the spectrum of the light source that exposes your sample or
  - calibrate the sensor under the exact same light you use for detection later on.

However, the actual calibration values don't matter at all. It should be as simple as saving the value you get for copper as a reference and compare your test color with that value, including some margin, of course. Any sensor will always have specific/individual properties, like the spectral sensitivity in case of the TCS3200. But the reason of calibration is that you don't have to bother.


body: I need to rename my Arduino UNO in a way that when it connects to the computer then it reads not as "Arduino" in device manager but as "My instrument name". I need to know how to do this on an UNO and Pro micro specifically but also on other arduinos. Please also suggest if there are other development boards available where names is not preprogrammed but programmable. Thank you.

title: How can I rename how my Arduino UNO (or any other Arduino) shows up on the computer?

Answers: 0


body:
I am implementing a BLE peripheral in my firmware with Arduino ESP32.

When the central gets connected to it, I'd like to log the name of the central & its address.

How can I do that?

```cpp
#include <BLEServer.h>

class ServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
  ble.log("ServerCallbacks: Connected");

// ==> how can I add the connected device ID or name in the log?

       ble.deviceConnected = true;

  #if SUPPORT_LEDS_INDICATOR

  // === Show France flag colors
  // RGBW = 1,2,3, 4
  // CODE : BBWRR
  // CODE = 33411
  const String code = "BBWRR";
  ledIndicator.showAccessCode(code);
  #endif

  #if SUPPORT_BUZZER
  /// BLE connection jingle
  buzzer.playBleConnectedMelody();
  #endif
    };

    void onDisconnect(BLEServer* pServer) {
  ble.deviceConnected = false;
  ble.log("ServerCallbacks: Disconnected");

  #if SUPPORT_BUZZER
  /// BLE connection jingle
  buzzer.playBleDisconnectedMelody();
  #endif
    }
};

/// Somewhere in the setup:
server = BLEDevice::createServer();

// == Set up our calbacks
server->setCallbacks(new ServerCallbacks());

```

title: How to get the name of connected device over BLE?

Answers: 1

body:
(Note: this is all just from reading the library source code, nothing has been tested).

You can't get the details of the just-connected-client. However you *can* get a list of the currently connected clients.

There is a function in the `BLEServer` class:

    std::map<uint16_t, conn_status_t> getPeerDevices(bool client);

You can use that to get the list of connected clients. The "key" of the map is the connection id, and the "value" of the map is the "conn_status_t" struct, which includes a pointer to the peer device structure:

```c++
typedef struct {
    void *peer_device;
    bool connected;
    uint16_t mtu;
} conn_status_t;
```

You can keep your own list of "current" connection IDs and compare that to the "live" list when a new connection is made to find which is the new connection.

So you can take that `peer_device` pointer, cast it to a `BLEClient` pointer, then you call any of the normal BLEClient functions on that, including `toString()` which will return a string representation of the client.

That of course isn't the "name" of the client. I am not sure (not being an expert on BLE) how you get the name, but I think you may have to actively query it from the client, which should be perfectly possible now you have the `BLEClient` object pointer.


body:
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][1] so that it could accept an arbitrary `Pin` abstraction that looks like the following:

```cpp
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`
```cpp
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`
```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`
```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`
```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:

```cpp
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

[1]: https://github.com/waveshare/e-Paper/tree/master/Arduino/epd4in2

title: ESP8266 soft resets when using a GPIO Expander

Answers: 1

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


body:
I've bought such on Amazon. My main problem is that it stays in 1sec-blink, meaning it can't registrer cellular network.

First I tried with all anntennas possiblities (one of each, both, none) - failed.

Using NodeMCU (for 3.3 TxRx) and `SoftwareSerial.h` to communicate. It answers all AT command as expected.

I tried several powering possibilities (as noted extensively about 2A on the internet), including 18650 , 2000mAh battery connected only to SIM800L module with no MCU connected, still same state.

What Can be done else?

SEE PELEPHONE:
[![Carrier support - "PELEPHONE"][1]][1]

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

title: SIM800L stays in 1sec-blink-state

Answers: 1

body:
Your mobile network provider does not provide a 2G (GPRS / GSM) network.

2G is graduallly being phased out around the globe, so switching to an LTE modem is really the way forward.

If you still want to use the SIM800L then you need a network provider that gives 2G services. Fortunately the SIM800L is a "quad band" modem, so it will work with pretty much any 2G provider (it works on 850/900/1800/1900MHz, hence the "quad" of "quad band").


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

title: Wrong use of memory?

Answers: 1

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


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

[![Enter image description here][1]][1]

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

### 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
}

```

  [1]: https://i.stack.imgur.com/5KHSo.png
  [2]: https://i.stack.imgur.com/JGqCJ.png

title: Problem with messuring capacitance with 50 Arduinos connected by I²C

Answers: 3

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

```c++
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**:

```c++
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
}
```

body:
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][1] can do maybe 60 nodes, depending on the transceiver chosen. It is relatively inexpensive.

  [1]: https://en.wikipedia.org/wiki/CAN_bus

body:
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](https://gammon.com.au/forum/?id=11428) - 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](https://store-usa.arduino.cc/products/arduino-micro?selectedStore=us), 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.


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

title: Connect to 8Base API with TLS on Arduino Uno Wifi Rev2

Answers: 1

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


body:
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() = 0xx\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.

title: ''Wire1' was not declared in this scope' in I2C_MPU6886 library

Answers: 1

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


body:
**(1)** I'm trying to work with libraries in PlatformIO format", for [![example][1]][1], 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 [![snapshot][2]][2] (which contains only library structures).

Appreciate any help

Guy

  [1]: https://i.stack.imgur.com/lq1ad.png
  [2]: https://i.stack.imgur.com/uFoBt.png

title: Create a library when using PlatformIO

Answers: 1

body:
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](https://arduino.github.io/arduino-cli/0.20/library-specification/).


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

title: Problem with "converting a string constant to 'char*'" in the WiFi library

Answers: 1

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


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

  [1]: https://support.arduino.cc/hc/en-us/articles/360020831120-Error-2-UNKNOWN-uploading-error-no-upload-port-provided

title: Error while uploading the sketch to Arduino UNO using CLI

Answers: 1

body:
You specify the port with the `--port` flag to the upload command:

```bash
$ 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:

```bash
$ 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.
```


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

title: A bug with multiple IR detectors

Answers: 1

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


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

title: Input Oscillating Wildly

Answers: 1

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

  [1]: https://www.arduino.cc/en/Tutorial/Foundations/DigitalPins

Try using INPUT_PULLUP in your pinMode statement.

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


body:
When i try to upload code to the esp32 the following error shows up in the command line:

__A fatal error occurred: Packet content transfer stopped (received 8 bytes).__

I use platformio in VScode the platform.ini file looks like this:

        [env:esp-wrover-kit]
        platform = espressif32
        board = esp-wrover-kit
        framework = arduino
        upload_port = COM4
        monitor_speed = 115200

Here's the code i'm trying to upload:

    #include <Arduino.h>

    void setup() {
        Serial.begin(115200);
        Serial.println("init");
    }

    void loop() {
    }

It's an esp32-wrover-dev from freenove. When i unplug it and plug it back in it starts to write random stuff to the serial monitor, when i attempt an upload it stops but it also gives me the error above.

title: esp32, platformio A fatal error occurred: Packet content transfer stopped (received 8 bytes) *** [upload] Error 2

Answers: 4

body: For anyone wondering, i found out it means that there's some kind of disconnect between the computer from which your uploading and the file system. Essentially, the esp32 is broken.

body:
I was able to resolve this issue by detaching jumpers that i had connected to the GPIO 12/13 pins during upload.

After uploading they can be attached again.
See this github issue: [https://github.com/espressif/arduino-esp32/issues/2415][1]

  [1]: https://github.com/espressif/arduino-esp32/issues/2415

body:
Hi all I found I got this error because my FTDI adapter was in 3.3V mode, not 5V as soon as I set it to 5V the issue was resolved and it programmed fine. One more thing to check before you scrap your ESP32.

Mick

body:
I had this error when trying to upload a sketch from Arduino IDE to a TTGO T-Display, found that I could resolve this by changing the upload speed from the default of 921600 to 115200.

After doing that it uploaded just fine with no issues.


body:
I'm trying to create a `AsyncWebServer` after enabling the `SoftAP`:

    #include <Arduino.h>
    #include <SPIFFS.h>
    #include <WiFi.h>
    #include <WiFiAP.h>
    #include <AsyncTCP.h>
    #include <ESPAsyncWebServer.h>

    WebApp webapp;

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

      File f = SPIFFS.open("/index.html");
      String s = f.readString();
      Serial.println(s);
      f.close();

      WiFi.softAP("ssid", NULL);
      WiFi.softAPsetHostname("ssid");
      Serial.println(WiFi.softAPIP());

      webapp.Begin();
    }

    void loop()
    {
    }

    class WebApp
    {
    public:
        WebApp();
        void Begin();

    private:
        AsyncWebServer _server;
    };

    #include "webapp.h"

    WebApp::WebApp() : _server(80)
    {
    }

    void WebApp::Begin()
    {
      _server.on("/", HTTP_GET, [this](AsyncWebServerRequest *request)
      {
        Serial.println("GET request");
        _server.serveStatic("/", SPIFFS, "/").setDefaultFile("/index.html");
      });

      _server.onNotFound([](AsyncWebServerRequest *request){
        request->send(404);
      });

      _server.begin();
      Serial.println("[WEB] HTTP server started");
    }

The `SoftAP` brings up the network and I can connect to it (`softAPgetStationNum()` tells me that 1 client is connected). It answers to pings.
The `index.html` is stored into the flash (the contents is printed out correctly).

But when I try to open the root page (192.168.4.1) it prints out "GET request" but the browser request timeouts and nothing is received.

Am I missing anything in the code?

title: ESP32 AsyncWebServer with softAP does not serve pages

Answers: 2

body:
I don't have enough rep to make a comment on your post, but is it possible that when you give the parameter for the function `setDefaultFile()` that the forward slash on `/index.html` is causing the path of the file to be `//index.html` instead of `/index.html`.

Because serveStatic is probably appending the filename of `setDefaultFile()` to the root directory of `/` (the third parameter of `serveStatic()`), you're probably getting an extra character you don't want in your filepath.

**TL;DR** you don't need the `/` in `index.html` for `setDefaultFile()`.

See https://github.com/me-no-dev/ESPAsyncWebServer#serving-files-in-directory for the example.

body:
The usage of `serveStatic()` is wrong. It's not intended to be used inside a callback. Just place the call in the setup of the webserver, i.e.:

    void WebApp::Begin()
    {
      _server.serveStatic("/", SPIFFS, "/").setDefaultFile("/index.html");

      _server.onNotFound([](AsyncWebServerRequest *request)
      {
        request->send(404);
      });

      _server.begin();
      Serial.println("[WEB] HTTP server started");
    }


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

title: How to make the compiler ensure that local variables memory allocation won't cause any RAM overflow during execution?

Answers: 1

body:
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](https://cpp4arduino.com/2018/11/06/what-is-heap-fragmentation.html)).


body:
I have code involving the use of an Adafruit Ultimate GPS Breakout v3 and an Adafruit RFM95W LoRa Radio that will compile with an Uno Rev3 but not with a Nano Every. The code I'm using comes almost directly from the examples provided by Arduino. I tried just the GPS code using the GPS_SoftwareSerial_Parsing test from Arduino and that worked, but I when I try using the Feather9x_TX code from Arduino it does not and I am not sure why. I am new to using Arduinos and have little experience with coding. I have attempted to search my error messages but have not been able to really find any answers so any help would be useful.

Here's the code
```
#include <SPI.h>
#include <RH_RF95.h>

#define RFM95_CS 9
#define RFM95_RST 8
#define RFM95_INT 2

// Change to 434.0 or other frequency, must match RX's freq!
#define RF95_FREQ 915.0

// Singleton instance of the radio driver
RH_RF95 rf95(RFM95_CS, RFM95_INT);

void setup()
{
  pinMode(RFM95_RST, OUTPUT);
  digitalWrite(RFM95_RST, HIGH);

  Serial.begin(115200);
  while (!Serial) {
    delay(1);
  }

  delay(100);

  Serial.println("Feather LoRa TX Test!");

  // manual reset
  digitalWrite(RFM95_RST, LOW);
  delay(10);
  digitalWrite(RFM95_RST, HIGH);
  delay(10);

  while (!rf95.init()) {
    Serial.println("LoRa radio init failed");
    Serial.println("Uncomment '#define SERIAL_DEBUG' in RH_RF95.cpp for detailed debug info");
    while (1);
  }
  Serial.println("LoRa radio init OK!");

  // Defaults after init are 434.0MHz, modulation GFSK_Rb250Fd250, +13dbM
  if (!rf95.setFrequency(RF95_FREQ)) {
    Serial.println("setFrequency failed");
    while (1);
  }
  Serial.print("Set Freq to: "); Serial.println(RF95_FREQ);

  // Defaults after init are 434.0MHz, 13dBm, Bw = 125 kHz, Cr = 4/5, Sf = 128chips/symbol, CRC on

  // The default transmitter power is 13dBm, using PA_BOOST.
  // If you are using RFM95/96/97/98 modules which uses the PA_BOOST transmitter pin, then
  // you can set transmitter powers from 5 to 23 dBm:
  rf95.setTxPower(23, false);
}

int16_t packetnum = 0;  // packet counter, we increment per xmission

void loop()
{
  delay(1000); // Wait 1 second between transmits, could also 'sleep' here!
  Serial.println("Transmitting..."); // Send a message to rf95_server

  char radiopacket[20] = "Hello World #      ";
  itoa(packetnum++, radiopacket+13, 10);
  Serial.print("Sending "); Serial.println(radiopacket);
  radiopacket[19] = 0;

  Serial.println("Sending...");
  delay(10);
  rf95.send((uint8_t *)radiopacket, 20);

  Serial.println("Waiting for packet to complete...");
  delay(10);
  rf95.waitPacketSent();
  // Now wait for a reply
  uint8_t buf[RH_RF95_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  Serial.println("Waiting for reply...");
  if (rf95.waitAvailableTimeout(1000))
  {
    // Should be a reply message for us now
    if (rf95.recv(buf, &len))
   {
      Serial.print("Got reply: ");
      Serial.println((char*)buf);
      Serial.print("RSSI: ");
      Serial.println(rf95.lastRssi(), DEC);
    }
    else
    {
      Serial.println("Receive failed");
    }
  }
  else
  {
    Serial.println("No reply, is there a listener around?");
  }

}
```
And here are the errors
```
Arduino: 1.8.19 (Windows 10), Board: "Arduino Nano Every, None (ATMEGA4809)"

C:\Users\jfeze\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp: In member function 'virtual void RHHardwareSPI::attachInterrupt()':
C:\Users\jfeze\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp:49:25: error: 'virtual void SPIClassMegaAVR::attachInterrupt()' is private within this context

     SPI.attachInterrupt();
                         ^

In file included from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead/RadioHead.h:731:0,
                 from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead/RHGenericSPI.h:10,
                 from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead/RHHardwareSPI.h:10,
                 from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp:7:

C:\Users\jfeze\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.7\libraries\SPI\src/SPI.h:186:15: note: declared private here

   inline void attachInterrupt() { SPI0.INTCTRL |= (SPI_IE_bm); }
               ^~~~~~~~~~~~~~~

C:\Users\jfeze\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp: In member function 'virtual void RHHardwareSPI::detachInterrupt()':
C:\Users\jfeze\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp:56:25: error: 'virtual void SPIClassMegaAVR::detachInterrupt()' is private within this context

     SPI.detachInterrupt();
                         ^

In file included from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead/RadioHead.h:731:0,
                 from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead/RHGenericSPI.h:10,
                 from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead/RHHardwareSPI.h:10,
                 from C:\Users\jfeze\Documents\Arduino\libraries\RadioHead\RHHardwareSPI.cpp:7:

C:\Users\jfeze\AppData\Local\Arduino15\packages\arduino\hardware\megaavr\1.8.7\libraries\SPI\src/SPI.h:187:15: note: declared private here

   inline void detachInterrupt() { SPI0.INTCTRL &= ~(SPI_IE_bm); }
               ^~~~~~~~~~~~~~~

Multiple libraries were found for "RH_RF95.h"
 Used: C:\Users\jfeze\Documents\Arduino\libraries\RadioHead
 Not used: C:\Users\jfeze\Documents\Arduino\libraries\RadioHead-master
exit status 1

Error compiling for board Arduino Nano Every.
```

title: RFM9x LoRa Radio code will compile with Uno but not Nano Every

Answers: 0


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

  [1]: https://www.mokinglobal.com/product/usb-c-hub-5-in-1-21.html

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?

Answers: 1

body:
Consider running through [this Sparkfun Hookup Guide][1] for the [SparkFun RedBoard Artemis][2].  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.

  [1]: https://learn.sparkfun.com/tutorials/hookup-guide-for-the-sparkfun-redboard-artemis-nano/troubleshooting
  [2]: https://www.sparkfun.com/products/15444https://


body:
I have been messing around with this application for a while but seem to keep hitting roadblocks. I am trying to have a public HTTPS page make a fetch to a private ESP8266.

As you can guess I ran into several infamous CORS issues and had to become with these posts: https://developer.chrome.com/blog/private-network-access-update/

https://web.dev/cors-rfc1918-feedback/

https://wicg.github.io/private-network-access/

After reading this I became persuaded that I needed to have an HTTPS server on my ESP8266 because this is the only way that the CORS policy would allow me to make a request from a public page to a private one. My issue now is that Chrome will allow these requests with a self-signed certificate on the ESP8266, but Firefox (which didn't throw any errors about this until very recently) blocked my request because the certificate was self-signed.

Is there any easy way to have a trusted certificate (i.e. something not self-signed) on my ESP8266 so that both Chrome and Firefox will allow this request?

If not, what is the most appropriate way to allow HTTPS connections to come to my ESP8266 without having to have a user trust the self-signed certificate in their browser?

title: Accessing HTTPS server of ESP8266 through fetch

Answers: 0


body:
 I'm using PlatformIO, and I'm trying to create a library who uses another library in it.

(1) For that I created an empty library called `ABCD.h` stored in a `newrep` github repository.

(2) 3rd party library chosen is `Panda_segmentBed_I2C.h` with no particular reason.

(3) That library was inserted as needed to `lib_deps` and initiate `build` update the newly create library that it pulled 3rd party library as needed, as shown in pic1 [![enter image description here][1]][1]

(4) `ABCD.h` includes `#include <Panda_segmentBed_I2C.h>`

(5) Now to simulate a use of `ABCD.h` library inside a code, I've created a new project called `TEST_NEWREP`. Only 1 line was added to project:  `#include <ABCD.h>`

(6) After running `build` I get an error that 3rd party library, inside `ABCD.h` is not found.

(7) see `TEST_NEWREP` tree:

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

**Edit 1 - update `.gitignore` **

Somehow, when Project is created, a default `.gitignore` includes an ignore of `.pio` library. Perhaps in some cases it should be ignored, but when that Project is a library, it does not upload `.pio\libdeps`. Now after the exclude is removed, all dependencies are pulled as needed when `build` the project, BUT STILL ERROR REMAINS THAT `Panda_segmentBed_I2C.h` is not found.

  [1]: https://i.stack.imgur.com/RZBrj.png
  [2]: https://i.stack.imgur.com/aHUbc.png

title: PlatformIO - Creating a library including a 3rd party library

Answers: 0


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

title: ESP8266 - Can't upload or use Serial Monitor - Ubuntu 22.04 LTS

Answers: 1

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


body:
I am using [this example][1] 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][2] 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

[![enter image description here][3]][3]

  [1]: http://developer.wildernesslabs.co/Hardware/Tutorials/Electronics/Part5/Resistive_Sensor_Lab/
  [2]: https://www.arduino.cc/reference/en/language/functions/math/map/
  [3]: https://i.stack.imgur.com/DnoNl.png

title: How to convert a reading to percentage in Arduino

Answers: 1

body:
You wrote:
> ```c++
> 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

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


body:
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:
```cpp
#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
```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?

title: TVout characters don't line up

Answers: 1

body:
I believe your problem is in this line:

```c++
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:

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


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

title: Why are raw data bytes not converting to ASCII, but only in one part of my program?

Answers: 1

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


body:
Does anyone know if the following is possible? Any advice would be much appreciated.

I am programming an Ethernet connected Arduino to be a webserver. What would be ideal is a small portable "router" so I can take the whole test setup and my laptop without depending on my home/company network.

My idea:
- Set up an ESP32 as an access point
- Connect an ENC28J60 module to it

I hope:
- My laptop can connect to the ESP over wifi (status: done)
- My board can connect over UTP
- They both get IP addresses
- I can test the Arduino webserver from my laptop

What I found is that I could use the [Ethercard for ESP32][1] or [EthernetENC][2] libraries

I've been trying with thernetENC, no luck. But is this even possible?

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

This is my minimal code for the ESP32 so far:

```
#include <WiFi.h>
#include <SPI.h>
#include <EthernetENC.h>

const char* ssid = "ESP32router01";
const char* pass = "01234567";          // At least 8 characters

void setup()
{

  WiFi.softAP(ssid, pass);

  Ethernet.init(5);
}

void loop() {
}
```

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

title: ESP32 access point with (ENC28J60) ethernet module

Answers: 0


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

title: How often should we poll the 74HC165 if we wish to detect 'button' presses?

Answers: 2

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

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

  [1]: https://arduino.stackexchange.com/a/89881/55698


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

title: Assign a list of char *

Answers: 1

body:
Just change this:

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

to this:

```c++
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][decay]. In
this case,

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

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

```c++
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.

[decay]: https://stackoverflow.com/questions/1461432/what-is-array-to-pointer-decay