# Question
Title: Ubuntu Serial Port Briefly showing on arduino IDE
I am using a NodeMcu with Arduino IDE on Ubuntu. I have managed to upload the blink script and it work. Now, when i plug the nodemcu, the serial port /dev/ttyUSB0 is briefly available in the IDE. After 2 seconds, the port menu is grayed out again and I can't use it.

Same with `ls /dev/tty*` `/dev/ttyUSB0` is briefly available.

```
/dev/tty    /dev/tty23  /dev/tty39  /dev/tty54      /dev/ttyS10  /dev/ttyS26
/dev/tty0   /dev/tty24  /dev/tty4   /dev/tty55      /dev/ttyS11  /dev/ttyS27
/dev/tty1   /dev/tty25  /dev/tty40  /dev/tty56      /dev/ttyS12  /dev/ttyS28
/dev/tty10  /dev/tty26  /dev/tty41  /dev/tty57      /dev/ttyS13  /dev/ttyS29
/dev/tty11  /dev/tty27  /dev/tty42  /dev/tty58      /dev/ttyS14  /dev/ttyS3
/dev/tty12  /dev/tty28  /dev/tty43  /dev/tty59      /dev/ttyS15  /dev/ttyS30
/dev/tty13  /dev/tty29  /dev/tty44  /dev/tty6       /dev/ttyS16  /dev/ttyS31
/dev/tty14  /dev/tty3   /dev/tty45  /dev/tty60      /dev/ttyS17  /dev/ttyS4
/dev/tty15  /dev/tty30  /dev/tty46  /dev/tty61      /dev/ttyS18  /dev/ttyS5
/dev/tty16  /dev/tty31  /dev/tty47  /dev/tty62      /dev/ttyS19  /dev/ttyS6
/dev/tty17  /dev/tty32  /dev/tty48  /dev/tty63      /dev/ttyS2   /dev/ttyS7
/dev/tty18  /dev/tty33  /dev/tty49  /dev/tty7       /dev/ttyS20  /dev/ttyS8
/dev/tty19  /dev/tty34  /dev/tty5   /dev/tty8       /dev/ttyS21  /dev/ttyS9
/dev/tty2   /dev/tty35  /dev/tty50  /dev/tty9       /dev/ttyS22  /dev/ttyUSB0
/dev/tty20  /dev/tty36  /dev/tty51  /dev/ttyprintk  /dev/ttyS23
/dev/tty21  /dev/tty37  /dev/tty52  /dev/ttyS0      /dev/ttyS24
/dev/tty22  /dev/tty38  /dev/tty53  /dev/ttyS1      /dev/ttyS25

```

After 2 seconds:

```
/dev/tty    /dev/tty23  /dev/tty39  /dev/tty54      /dev/ttyS10  /dev/ttyS26
/dev/tty0   /dev/tty24  /dev/tty4   /dev/tty55      /dev/ttyS11  /dev/ttyS27
/dev/tty1   /dev/tty25  /dev/tty40  /dev/tty56      /dev/ttyS12  /dev/ttyS28
/dev/tty10  /dev/tty26  /dev/tty41  /dev/tty57      /dev/ttyS13  /dev/ttyS29
/dev/tty11  /dev/tty27  /dev/tty42  /dev/tty58      /dev/ttyS14  /dev/ttyS3
/dev/tty12  /dev/tty28  /dev/tty43  /dev/tty59      /dev/ttyS15  /dev/ttyS30
/dev/tty13  /dev/tty29  /dev/tty44  /dev/tty6       /dev/ttyS16  /dev/ttyS31
/dev/tty14  /dev/tty3   /dev/tty45  /dev/tty60      /dev/ttyS17  /dev/ttyS4
/dev/tty15  /dev/tty30  /dev/tty46  /dev/tty61      /dev/ttyS18  /dev/ttyS5
/dev/tty16  /dev/tty31  /dev/tty47  /dev/tty62      /dev/ttyS19  /dev/ttyS6
/dev/tty17  /dev/tty32  /dev/tty48  /dev/tty63      /dev/ttyS2   /dev/ttyS7
/dev/tty18  /dev/tty33  /dev/tty49  /dev/tty7       /dev/ttyS20  /dev/ttyS8
/dev/tty19  /dev/tty34  /dev/tty5   /dev/tty8       /dev/ttyS21  /dev/ttyS9
/dev/tty2   /dev/tty35  /dev/tty50  /dev/tty9       /dev/ttyS22
/dev/tty20  /dev/tty36  /dev/tty51  /dev/ttyprintk  /dev/ttyS23
/dev/tty21  /dev/tty37  /dev/tty52  /dev/ttyS0      /dev/ttyS24
/dev/tty22  /dev/tty38  /dev/tty53  /dev/ttyS1      /dev/ttyS25

```

How can I fix that? I have try all the usb ports. The NodeMCU settings:

Actually Using Ubuntu 22.04 LTS

EDIT: While running `sudo dmesg -w` and connecting the mcu I get:

```
[ 3726.038486] usb 1-1: new full-speed USB device number 13 using xhci_hcd
[ 3726.220532] usb 1-1: New USB device found, idVendor=10c4, idProduct=ea60, bcdDevice= 1.00
[ 3726.220536] usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 3726.220537] usb 1-1: Product: CP2102 USB to UART Bridge Controller
[ 3726.220538] usb 1-1: Manufacturer: Silicon Labs
[ 3726.220539] usb 1-1: SerialNumber: 0001
[ 3726.229998] cp210x 1-1:1.0: cp210x converter detected
[ 3726.231005] usb 1-1: cp210x converter now attached to ttyUSB0
[ 3727.565688] usb 1-1: usbfs: interface 0 claimed by cp210x while 'brltty' sets config #1
[ 3727.566375] cp210x ttyUSB0: cp210x converter now disconnected from ttyUSB0
[ 3727.566391] cp210x 1-1:1.0: device disconnected

```

# Answer
> 4 votes
This could be happening because `Brltty` application. Remove it and try again.

```
sudo apt remove brltty
sudo apt autoclean && sudo apt autoremove

```

---
Tags: serial, nodemcu, ubuntu
---


# Question
Title: Externally powering Arduino while reading voltage off it via USB
I have an Arduino UNO R3 where I’ve set Pin 13 to “HIGH” (as shown here) and I’ve connected an LED to Pin 13 and GND which glows brightly using a USB attached to my MacBook Air providing (I think) 5V.

Now, I’m powering the Arduino externally using a 3V (1.5+1.5) battery and the 5V/GND connection. The green light blinks showing the Arduino is being powered and the bulb glows since it’s the same circuit.

Now, I wish to connect the USB to the Arduino and basically read the voltage of the LED via Pin 13 and the GND connection. Of course, I could accomplish this by simply attaching a multimeter but that’s not the problem since it’s not the true aim of the project (which I can state if required but it’s more complicated and not too different). But when I connect the USB the LED glows brighter and the voltage across it is around 3.5V (higher than what the battery is supplying). I want the computer to read the voltage of the battery and not supply the arduino with it’s own power. How do I accomplish this (note: I’m allowed to break certain circuitry on the Arduino but I’d prefer to do this as last resort)?

Basically, how do I read voltage readings on a computer off an arduino without powering the arduino i.e. How do I convert the USB port and my computer into a multimeter with the arduino?

(I'm very new to experimenting with this so may have made crushing mistakes. Any help is appreciated)

# Answer
Pin 13 is a digital pin, it does not have the capability to read voltage. You need to use one of the analog pins to read voltage, they are prefixed with the letter "A" (A0 for example). You also need to note the Analog reference (maximum voltage reference point for the A/D) is the Arduino's +5 volt supply so if that changes so will the readings. You will get 0 with zero input and 1023 when the voltage matches the reference voltage. Note this voltage cannot exceed VCC by more than a very small amount (0.6V)or you will damage the Arduino. The USB supplies about 4.5 volts, depending on the protection circuit. If you power it via Vin with the appropriate voltage it will have nominally 5 volts and of course the ever changing battery voltage. All of these change your reference voltage changing your voltage measurement. The best solution is to power it externally and then connect the battery - to ground and the battery + to one of the A/D inputs. With a little math in your code you will have a voltmeter. There are many fine examples on line complete with code for the Arduino.
> 1 votes

---
Tags: arduino-uno, serial, programming
---


# Question
Title: anyone heard of MCUDEV_TFT1.44 display? I can't figure out how to connect it to Arduino
I bought this tft display on Aliexpress: https://www.aliexpress.com/item/1005001579367288.html?spm=a2g0s.9042311.0.0.72164c4doyqAub

it says "MCUDEV\_TFT1.44" below the display.

I can't find online how to connect it to Arduino. The pins are as follows: BLK RS RST CS SC DI GND VCC

on Aliexpress it says "Drive IC: ST7735" but I googled ST7735 displays and they have different pins. Anyone has any idea? Thanks!

# Answer
> 1 votes
If anyone else have the same display and wondering how to make it work, here is how I connected and the script I used.

I couldn't find my display model so I just used this in Fritzing and added the pins names as a note.

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#include <SPI.h>

#define TFT_CS        10
#define TFT_RST        9 // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC         8

#define TFT_MOSI 11  // Data out
#define TFT_SCLK 13  // Clock out

Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

float p = 3.1415926;

void setup(void) {
  Serial.begin(9600);
  Serial.print(F("Hello! ST77xx TFT Test"));

  // OR use this initializer (uncomment) if using a 1.44" TFT:
  tft.initR(INITR_144GREENTAB); // Init ST7735R chip, green tab

  Serial.println(F("Initialized"));

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);
  delay(500);

  // large block of text
  tft.fillScreen(ST77XX_BLACK);
  testdrawtext("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur adipiscing ante sed nibh tincidunt feugiat. Maecenas enim massa, fringilla sed malesuada et, malesuada sit amet turpis. Sed porttitor neque ut ante pretium vitae malesuada nunc bibendum. Nullam aliquet ultrices massa eu hendrerit. Ut sed nisi lorem. In vestibulum purus a tortor imperdiet posuere. ", ST77XX_WHITE);
  delay(1000);

  // tft print function!
  tftPrintTest();
  delay(4000);

  // a single pixel
  tft.drawPixel(tft.width()/2, tft.height()/2, ST77XX_GREEN);
  delay(500);

  // line draw test
  testlines(ST77XX_YELLOW);
  delay(500);

  // optimized lines
  testfastlines(ST77XX_RED, ST77XX_BLUE);
  delay(500);

  testdrawrects(ST77XX_GREEN);
  delay(500);

  testfillrects(ST77XX_YELLOW, ST77XX_MAGENTA);
  delay(500);

  tft.fillScreen(ST77XX_BLACK);
  testfillcircles(10, ST77XX_BLUE);
  testdrawcircles(10, ST77XX_WHITE);
  delay(500);

  testroundrects();
  delay(500);

  testtriangles();
  delay(500);

  mediabuttons();
  delay(500);

  Serial.println("done");
  delay(1000);
}

void loop() {
  tft.invertDisplay(true);
  delay(500);
  tft.invertDisplay(false);
  delay(500);
}

void testlines(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, 0, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, 0, 0, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
    delay(0);
  }
}

void testdrawtext(char *text, uint16_t color) {
  tft.setCursor(0, 0);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t y=0; y < tft.height(); y+=5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x=0; x < tft.width(); x+=5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=radius; x < tft.width(); x+=radius*2) {
    for (int16_t y=radius; y < tft.height(); y+=radius*2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 0xF800;
  int t;
  int w = tft.width()/2;
  int x = tft.height()-1;
  int y = 0;
  int z = tft.width();
  for(t = 0 ; t <= 15; t++) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
    int x = 0;
    int y = 0;
    int w = tft.width()-2;
    int h = tft.height()-2;
    for(i = 0 ; i <= 16; i+=1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x+=2;
      y+=3;
      w-=4;
      h-=6;
      color+=1100;
    }
    color+=100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(ST77XX_WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(ST77XX_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(ST77XX_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(ST77XX_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN);
}```

**LIBRARIES:**

* Go to Sketch -\> Include Library -\> Manage Libraries
* Search for **Adafruit GFX Library** and install the latest version and install all the dependencies as well when it asks
* Search for **Adafruit ST7735 and ST7789 Library** and install the latest version and install all the dependencies as well when it asks

---
Tags: display, tft
---


# Question
Title: I2C sensors not working when I connect to LCD 20X04
I am making a hydroponic nutrient monitoring system using Arduino Uno, Atlas Scientific EC sensor, pH sensor, and RTD (temperature) sensor in I2C mode. I also want to use LCD 20x04 to display the sensor reading so that will display the EC, pH, and temperature values. I connect all the SDA and SCL to pin A4 (SDA) and A5 (SCL), and powered all the sensors and LCD with 3.3 V. Each sensor's SDA and SCL are added with resistor 4.7 kOhm.

I tested the code first by connecting my Arduino Uno to the RTD EZO circuit and sensors, without the LCD. The Serial Monitor successfully displays the data sensor reading of RTD, as well as 'No Data' for EC and pH as I do not connect the EC and pH sensors. But when I connect all the circuits and sensors, it can not detect the pH sensor. The most frustrating part is the LCD. The LCD at first displays the EC and RTD data, but only run for 5 minutes and freeze. The LCD sometimes only shows a "0.00" value for EC and RTD even though the Serial Monitor shows the data sensor reading.

I want to know if there is something wrong with my code or maybe the problem with my own circuit.

Here is the code:

```
#include <Ezo_i2c.h>
#include <Wire.h>                //enable I2C.
#include <LiquidCrystal_I2C.h>

Ezo_board ec = Ezo_board(100, "EC");
Ezo_board ph = Ezo_board(99, "PH");
Ezo_board temp = Ezo_board(102, "RTD");
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 20, 4);

bool reading_request_phase = true;        //selects our phase

uint32_t next_poll_time = 0;              //holds the next time we receive a response, in milliseconds
const unsigned int response_delay = 1000; //how long we wait to receive a response, in milliseconds

void setup()                     //hardware initialization.
{
  Serial.begin(9600);            //enable serial port.
  Wire.begin();                  //enable I2C port.
  Serial.println("ATLAS EZO I2C v2");
  Serial.print("Test date: ");
  lcd.init();
  lcd.backlight();
  lcd.setCursor(1,1);
  lcd.print("ATLAS EZO I2C v2");
  lcd.setCursor(0,2);

  delay(3000);
  lcd.clear();
 }

  void loop() {                                                      //the main loop.
  lcd.setCursor(0,1);
  lcd.print("EC: ");
  lcd.setCursor(4,1);
  lcd.print(ec.get_last_received_reading());
  lcd.setCursor(10,1);
  lcd.print("ppm");
  lcd.setCursor(0,2);
  lcd.print("pH: ");
  lcd.setCursor(4,2);
  lcd.print(ph.get_last_received_reading());
  lcd.setCursor(0,3);
  lcd.print("Temp.: ");
  lcd.setCursor(7,3);
  lcd.print(temp.get_last_received_reading());
  lcd.setCursor(13,3);
  lcd.print("C");

  if (reading_request_phase)             //if were in the phase where we ask for a reading
  {
    //send a read command
    //to let the library know to parse the reading
    ec.send_read_cmd();
    ph.send_read_cmd();
    temp.send_read_cmd();

    next_poll_time = millis() + response_delay;         //set when the response will arrive
    reading_request_phase = false;                      //switch to the receiving phase
  }
  else                                                //if were in the receiving phase
  {
    if (millis() >= next_poll_time)                    //and its time to get the response
  {
    receive_reading(ec);                              //get the reading from the EC circuit
    receive_reading(ph);                              //get the reading from the PH circuit
    receive_reading(temp);                              //get the reading from the RTD circuit

    reading_request_phase = true;                     //switch back to asking for readings
  }
 }
 }

  void receive_reading(Ezo_board &Sensor) {
  Serial.println();
  Serial.print(Sensor.get_name()); //print the name of the EZO circuit
  Serial.print(": ");
  Sensor.receive_read_cmd();

  switch (Sensor.get_error())                          //switch case based on what the response code is.
     {
    case Ezo_board::SUCCESS:
    Serial.print(Sensor.get_last_received_reading());               //the command was successful, print the reading
    break;

    case Ezo_board::FAIL:
    Serial.print("Failed ");                          //means the command has failed.
    break;

    case Ezo_board::NOT_READY:
    Serial.print("Pending ");                         //the command has not yet been finished calculating.
    break;

    case Ezo_board::NO_DATA:
    Serial.print("No Data ");                         //the sensor has no data to send.
    break;
 }
}

```

# Answer
> 5 votes
Welcome to Stack Exchange!

I can spot a few problems with the circuit. As @hcheung said, the I2C pull-up resistors should only be wired between SDA\>3.3V and SCL\>3.3V (in parallel), not in series with the sensors.

Also, another warning: You are powering your sensors with **3.3V**, but the outputs from the Arduino Uno are **5V!** Many boards will not like this and might fry themselves, or at least not function correctly. Their signals will also be 3.3V instead of 5V, potentially causing more weird behavior.

If all your components are compatible with 5 volt power (check their datasheets/guides), I would recommend powering them all with 5 volts.

Otherwise, you will need level shifters to convert between the 5V Arduino signals and the 3.3V board signals.

# Answer
> 2 votes
Thank you for all your help. I now realize that I have made the wrong I2C circuits. Then I modified them and now the program and the sensors work perfectly.

Here is my circuit now.

---
Tags: arduino-uno, sensors, i2c, lcd
---


# Question
Title: Arduino battery capacity selection based on the current measurements
I'm sorry for this stupid question... I'm not an electronic/electric expert.. In order to select the battery capacity as well as the solar panel I'm measuring the Arduino current consumption. So, I connected my multimeter (in line) (I rotated the selector on 200mA) and I'm able to see the values that are:

* around 85mA for few seconds (around 8seconds) when the system works;
* around 0.38 mA during the remaining 52 seconds when the system is in sleep mode. I'll enable my system around 8s for each 15minutes (basically 4 times for hour)

In order to have a general idea, I would like to use a site like this https://www.digikey.it/en/resources/conversion-calculators/conversion-calculator-battery-life

Now, It's not clear for me how can I use the retrieved values: Do I calculate the current consuming in 1h?

The values that I obtained are related to the current consumed for a second?

What I have to punt into the field "Device Consumption" on the linked web-site?

# Answer
You have two current values and the approximate time those currents run for. From that you can calculate the *average* current.

If you have 8 seconds "on" and (15\*60-8) 892 seconds "off" that gives you:

```
(85 * 8) + (0.38 * 892)
------------------------
         900

```

Which comes out as 1.13mA on average at any point in time (that's a simple ratio calculation - the times don't matter, only the ratio between them).

Over the course of 1 hour you will consume around 1.13mA on average, which is 1.13mAh.

To run for 24 hours you will need 1.13*24 = 27.2mAh. To run for a week it's 27.2*7 = 190mAh.

The calculations, as you can see, once you have the average current are pretty simple.

Of course you need to "derate" the results since batteries *never* hold the stated amount - that is both a "theoretical maximum" under ideal conditions, which degrades over time (as you will know when your phone battery starts dying too soon), plus you *never* run a battery completely flat. Personally I like to double the capacity to err on the safe side.

You also know that you need to charge the batteries with at least an average of 1.13mA from your solar cells. That means working out what ratio of the time will be available for actual charging (daylight with good sun brightness) and calculating how much current you will need to generate during that time to allow the system to run in the dark.
> 2 votes

---
Tags: arduino-mega, battery, current, solar
---


title: Ethernet library compilation error

text:
# Question
Title: Ethernet library compilation error
I'm trying to connect my Arduino to the internet, but my Ethernet connection config code fails when I try to verify it, and I'm not sure why.

I'm using an Ethernet shield and have installed the Ethernet library v.2.0.0.

This is the running code:

```
WANStatus initialiseWAN() {
  // Enter a MAC address for your controller below.
  // Newer Ethernet shields have a MAC address printed on a sticker on the shield
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
  WANStatus res;

  Serial.println("[INFO]: Initialising WAN");
  // Try to initialise Ethernet connecion

  if (Ethernet.begin(mac) == 0) {
    res.error = true;
    res.retry = true;

    if (Ethernet.hardwareStatus() == EthernetNoHardware) {
      res.message = "Ethernet shield was not found";
      Serial.print("[ERROR]: "); Serial.println(res.message);
      return res;
    }

    // If all component are present try assigning a static IP address
    IPAddress ip(192, 168, 0, 177);
    IPAddress myDns(192, 168, 0, 1);
    Ethernet.begin(mac, ip, myDns)
    Serial.print("[INFO]: Assigned static IP: "); Serial.println(Ethernet.localIP());

    if (Ethernet.linkStatus() == LinkOFF) {
      res.message = "Ethernet cable is not connected";
      Serial.print("[ERROR]: "); Serial.println(res.message);
      return res;
    }
    if (Ethernet.linkStatus() == Unknown) {
      res.message = "Ethernet link status is 'Unknown' check the cable";
      Serial.print("[ERROR]: "); Serial.println(res.message);
      return res;
    }

    // Static IP assigned
    res.error = false;
    res.retry = false;
    res.message = "Static IP Address";
    return res;
  } else {
    // Received IP address from DHCP
    Serial.print("[INFO]: Received DHCP IP: "); Serial.println(Ethernet.localIP());
    res.error = false;
    res.retry = false;
    res.message = "DHCP IP Address";
    return res;
  }

  // ToDo: check WiFi modules here

}

```

And the error message:

```
[Starting] Verifying sketch 'controller\controller.ino'
[Warning] Output path is not specified. Unable to reuse previously compiled files. Build will be slower. See README.
Loading configuration...
Initialising packages...
Preparing boards...
Verifying...
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp:8:0:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp: In member function 'uint16_t DNSClient::BuildRequest(const char*)':
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\utility/w5100.h:457:25: warning: result of '(256 << 8)' requires 18 bits to represent, but 'int' only has 16 bits [-Wshift-overflow=]
#define htons(x) ( (((x)<<8)&0xFF00) | (((x)>>8)&0xFF) )
                      ~~~^~~
C:\Program Files (x86)\Arduino\libraries\Ethernet\src\Dns.cpp:164:18: note: in expansion of macro 'htons'
twoByteBuffer = htons(QUERY_FLAG | OPCODE_STANDARD_QUERY | RECURSION_DESIRED_FLAG);
^~~~~
Sketch uses 22574 bytes (69%) of program storage space. Maximum is 32256 bytes.
Global variables use 1467 bytes (71%) of dynamic memory, leaving 581 bytes for local variables. Maximum is 2048 bytes.
IntelliSense configuration already up to date. To manually rebuild your IntelliSense configuration run "Ctrl+Alt+I"
[Done] Verifying sketch 'controller\controller.ino'

```

# Answer
> 0 votes
Everything is alright. There is no compiler error and your sketch is ready to upload.

The compiler warning "*result of '(256 \<\< 8)' requires 18 bits to represent, but 'int' only has 16 bits*" from the Ethernet library source code is nothing you have to worry about.

---
Tags: compilation-errors, ethernet-shield
---


title: Connecting various devices to Arduino

text:
# Question
Title: Connecting various devices to Arduino
I need to connect the following devices to an Arduino UNO board. The problem is that I run out of pins to be able to connect them all. Is there any way to do it?

* ultrasonic sensor
* yellow led
* green led
* red led
* buzzer
* keypad 4x4

I'm doing the project in Tinkercad

In the picture below I tried to do it, but I am missing 2 pins for the ultrasonic sensor trig and echo

# Answer
> 3 votes
As cguck70 already stated in the comments: The pins A0 to A5 can be analog input pins, but they can also be normal digital input/output pins. You can use them to your liking, just like any other digital input/output.

So just connect two of these pins to your ultrasonic sensor and use the pin names `A0`, `A1` and so on in your code.

---
Tags: arduino-uno, keypad
---


title: Configure Trinket M0 as I2C peripheral

text:
# Question
Title: Configure Trinket M0 as I2C peripheral
I am trying to use I2C to communicate between my XBee3 (controller) and an adafruit trinket m0 (peripheral). I'm pretty confident I have the modules connected properly (trinket SCL/pin 2 to xbee SCL/pin DIO1 & trinket SDA/pin 0 to xbee SDA/pin DIO11, and both grounds are connected). Here is my arduino code on the trinket:

```
#include <Wire.h>

void setup()
{
Wire.begin(72); // join i2c bus
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
Serial.print("Waiting for data...");
}

void loop()
{
delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
(void)howMany; // avoid compiler warning about unused parameter

while(1 < Wire.available()) // loop through all but the last
{
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}

```

and here is my code on the XBee:

```
from machine import I2C

# Instantiate an I2C peripheral.
i2c = I2C(1)
slave_addr = 72
i2c.writeto(slave_addr, b'123', False)

```

Additionally, when I run an i2c.scan() on the xbee with an ISM330DHCX connected to the xbee's I2C, the address pops right up. But when I use the exact same code with the xbee connected to the trinket m0, the xbee cannot find any devices. (Code pasted below)

```
from machine import I2C

# Instantiate an I2C peripheral.
i2c = I2C(1)

# Scan for I2C slaves connected to the interface and print their address.
for address in i2c.scan():
    print("- I2C device found at address: %s" % hex(address))

```

Does anyone have any ideas what I'm doing wrong with configuring the trinket m0 to be an i2c peripheral? Thank you!

# Answer
I have two Adafruit Trinket M0 arduino boards running on my bench right now talking to each other over I2C. The trick is that you need to install a pull-up resistor between SDA and +3V, and another one between SCL and +3V. Typically it is the peripheral boards that come with those but when you talk between two microcontrollers which are often used as the master controller themselves they are open drain or not powerful enough to drive the bus. Any resistor between 4.7k and 10k ohms should do.

see the following reference doc:

`https://docs.particle.io/cards/firmware/wire-i2c/pull-up-resistors-i2c/`

From the other direction if you have many peripheral boards that all include their own pull up resistors, the combined resistance on the bus may low enough leak enough current to raise "low" state above 0.4v, at which point communication may have errors.

Or if the wires are too long or there are too many devices without enough pull up resistance (thus too much inherent capacitance) it will take too long for the data lines to reach the "high" state, and you will have to slow down the clock rate or add a signal booster like the LTC4311 (e.g. Adafruit product #4756) to get stable results.
> 1 votes

---
Tags: i2c, adafruit, xbee
---


title: Can't get input from 4x4 keyboard

text:
# Question
Title: Can't get input from 4x4 keyboard
I'd like to make some basic calculator. Currently, I'm struggling with inputs. I wanted to get from user some numerical input, then, I'd like to have an information, which type of calculation he is about to do. I'm not sure why, but I can't get any numerical input from user, because the program "jumps" ahead to the operation type. Here's some code:

```
void loop(){
int a = getNumber();

if(a != NO_KEY){
    do{
    operationType = getOperationType();
    }while(!operationType);
  }

```

}

**getNumber**

```
  int getNumber(){
  char userInput = customKeypad.getKey();
  int value;

  if (userInput == '0' || userInput == '1' || userInput == '2' || userInput == '3' || userInput == '4' || userInput == '5' ||
  userInput == '6' || userInput == '7' || userInput == '8' || userInput == '9'){
      value = userInput - '0';
      Serial.println("value");
      Serial.println(value);

    }
  return value;
  }

```

**getOperationType**

```
char getOperationType(){
char userInput = customKeypad.getKey();

  switch (userInput){

      case '+':
//      add(a , b);
        Serial.println("add");
        break;
      case '-':
//      subtract(a , b);
        Serial.println("subtract");
        break;
      case '*':
//      multiply(a , b);
        Serial.println("multiply");
        break;
      case '/':
//      divide(a , b);
        Serial.println("Divide");
        break;
      case 'C':
//      TODO
        break;
    }
    return userInput;
  }

```

Can I have any hint, why I can't just get simple inputs from the keyboard?

# Answer
> 1 votes
You need to watch out for what you return and if your variables are initialized. So, what happens here:

In `loop()` you call `getNumber()`. There you declare two variables:

* `userInput`, which you initialize to the return value of `customKeypad.getKey()`. So this variable will have the value `NO_KEY` if no key is pressed.
* `value`, which you don't initialize. Thus its value is whatever was there in the variables memory space before it was allocated. This can be anything, but it is not random in most cases. It depends on what your program does prior to this, but you don't have any control over it.

Then you check for `userInput` being an ASCI digit. As you didn't press a key this obviously is false, so the variable `value` gets never written. And then you return that variable.

In `loop()` you check if the return value of `getNumber()` is unequal to `NO_KEY`. And since you didn't initialize `value`, it probably is. Thus the program goes directly to the operation type part.

---

**What to do now?**

First: Always initialize every variable that you declare in a function. Global variables get initialized implicitly, but not local variables. To be sure that I don't make an error, I just always initialize ALL my variables when declaring them.

Second: Currently `value` will not be `NO_KEY` since you don't assign that value to the variable. But doing so wouldn't fit with your program logic. `value` is the real numeric value, not the ASCI representation of it. And `NO_KEY` is defined in the `Keypad` library as `\0` (the null character, with numeric value zero). So `NO_KEY` is actually equal to `0`. And zero is also a valid input to your calculator.

Instead I would suggest returning `-1` if no key was pressed and then in `loop()` checking for that. So something like this:

```
int getNumber(){
  char userInput = customKeypad.getKey();
  int value;

  if (userInput == '0' || userInput == '1' || userInput == '2' || userInput == '3' || userInput == '4' || userInput == '5' || userInput == '6' || userInput == '7' || userInput == '8' || userInput == '9'){
    value = userInput - '0';
    Serial.println("value");
    Serial.println(value);
  } else {
    return -1;
  }
  return value;
}

void loop(){
  int a = getNumber();

  if(a != -1){
    do{
      operationType = getOperationType();
    }while(!operationType);
  }
}

```

---

That said, I have some suggestions for you for going further:

* For checking if the returned key is an ASCII digit there is actually a simple function for that: `isDigit()`. So instead of your chained equal conditions you can just use

```
  if(isDigit(userInput))

```
* If you go on in this style you will find yourself wrapping multiple loops in one another as you need to loop for waiting on a keypress. That can get rather messy and it gets difficult to add additional functionality. Instead you could implement a Finite State Machine (FSM). Here the code in `loop()` consists mainly out of a switch case structure, where every case is one state of your program. For example you could have the states NUMBER1\_INPUT, OPERATION\_INPUT, NUMBER2\_INPUT, DISPLAY\_RESULT. The switch structure uses a single int variable as a state marker. For example when you set that state variable to NUMBER1\_INPUT it will stay there and loop. When the user as done the number input you can change the state variable to OPERATION\_INPUT and let it continue there. It is an important concept and it will change your way of Arduino coding for the better.

There are many resource for learning how to program a FSM. I've once written a longer answer about this, but you can search for something like "Finite State Machine" on this site or the web to find out more.

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


# Question
Title: USB-C to USB-C cable Arduino is not responding even not powered by this cable
Hi I want to connect arduino NANO to my laptop with Type-C (USB-C) ports (on below image left side \[4\] and other side ). Now I bought a USB-C to USB-C cable, because it appeared to be the right tool, but the Arduino is not even powered by this cable. if I use regular USB 3.2 Gen 2 Port (on below image \[5\]) everythings for fine. but this usb-c ports not recognize the Arduino NANO even NANO's power LED is not switching ON.

On the other hand If I plug in my phone to this usb-c cable it works both ports. It means that cable is working good. I have changed 2 times cable stil not responding.

On the docs, it look usb-c and regular usb 3.2 ports works same. But why usb-c ports not working with Arduino. also my laptop is MSI GS66

I'd appreciate if anyone has a solution or an idea to fix it. Thanks!

# Answer
That Nano is not USB-C compliant. Yes, it has the connector, but it doesn't do all the required handshaking to put the USB-C port on the laptop into host (and provide power) mode. This is needed because those ports are also power inputs and have to be told to output power - otherwise plug in power to them and bang horrible things happen.

You have to use the larger USB 3.2 ports which are always power providers and never power consumers.
> 3 votes

---
Tags: serial, arduino-nano, power, usb, port-mapping
---


title: Powering LEDs with Arduino uno 5v

text:
# Question
Title: Powering LEDs with Arduino uno 5v
I'm working on the sound reactive led lamp as my first project and have slightly different materials to start with. First I'd like to simply learn to power the LED strip.

from https://www.youtube.com/watch?v=5oRir4dck\_w

I'm attaching pictures so it's as simple as possible, but I'd like to confirm where to attach the wires on the uno and the basic logic behind how to get from the attempt I have now, to actually turning on the LEDs. Thanks so much!

(I think the images show up but please let me know if not)

# Answer
> 0 votes
A good question, best asked as you did before frying something. My Arduino rule #1 A power supply the Arduino is NOT! Connect the ground of the LED power supply to the ground of the arduino. Then connect the data line, as you have it in your picture. If you try to operate as it is in the picture the odds are high that you will fry the regulator on the Arduino depending on the output of the wall wart. You have a 5V power supply connected to the Vin connector, that does not work as it goes through the regulator and protection circuitry before getting to the processor. You need to power via the 5V pin with a 5V power supply. This can also be used to power your LEDs assuming they do not pull much over 1 amp. If you want to power by the connector, my preference, you need about 7.5 to 12 VDC. The additional filtering does not hurt and can only help. It also helps to protect from transients.

---
Tags: arduino-uno, led, led-strip
---


# Question
Title: How do you deal with balancing the limited storage of Arduino with the decrease in speed if you just print everything as it gets measured?
I am working on a simple data acquisition system based on an Arduino Uno. Each run would ideally collect up to 10k data points (all doubles). Obviously, the Arduino doesn't have the capacity to hold all that at once. However, as one would expect, printing out the data as its being acquired significantly slows the process down (by about a factor of 7). I have looked around to find if there's a standard way to deal with this issue in the world of Arduinos, but have come up short. I come from a background where memory is never an issue, so I'm not as well versed in this side of things.

Obviously I don't expect perfection, but any insight or sources would be helpful.

# Answer
This is all about choosing the right tool for the job.

At the moment you're trying to fit 50 clowns into a mini. While there are ways of doing it (by extending the "mini" outwards with extra "room") it's not what you'd normally do.

Instead you'd hire a coach.

If you have a scenario whereby you need to store more data than an Uno can store then you would typically *use a different board with a more powerful chip*.

There's plenty out there, many that are cheaper than the Uno...

If you desperately do want to use the Uno then:

* Reduce your data size: consider using smaller variables, such as 16 bit integers and fixed point arithmetic instead of floating point values.
* Improve your data transmission: send binary data instead of ASCII data, and increase your baud rate to the highest that can be reliably achieved
* Consider adding external storage, such as an SPI SRAM chip or an SD card.
> 3 votes

# Answer
My solution is to use FRAM, it is much faster then printing and has almost unlimited read and write cycles. It is also non volatile so if power fails the data does not. They can be gotten I2C or SPI your preference. I purchased 32K x 8 devices for well under $6.00 last year from my favorite china supplier. You can treat it as one big ring buffer and print from it while you load data into it.
> 0 votes

# Answer
Don't use `String` and others dynamic allocated object in your code. There is not any reason for slow down serial output, only inefficient memory management.
> -1 votes

---
Tags: memory, datalogging, speed
---


# Question
Title: Arduino create Json Array with double values and 2 decimal point
How i can create a Json Array with double values and 2 decimal point using the ArduinoJson Library?

https://arduinojson.org/v6/how-to/configure-the-serialization-of-floats/

In the folowing small example it is possible to write to the Json file a double value with 2 decimal point.

```
#include <ArduinoJson.h>

double round2(double value) {
  return (int)(value * 100 + 0.5) / 100.0;
}

double round3(double value) {
  return (int)(value * 1000 + 0.5) / 1000.0;
}

double var1 = 1.23456789;
double var2 = 5.05599991;

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

  StaticJsonDocument<200> doc;
  doc["hello"] = "world";
  doc["var1"] = round2(var1);
  doc["var2"] = round3(var2);

  serializeJsonPretty(doc, Serial);

}

```

In my sketch right now i am able to create the Json Array with the values read from a Analog input. Only the created Json Array have 9 decimal points. I do not know how to implement in my sketch, folowing the aboth example that the values inside the Json array have only two decimal points.

Follow my sketch.

```
#include <ArduinoJson.h>

#define ADC_Range_Pin  35  // Pin Range Sensor

unsigned long scale_previousMillis = 0;
const long scale_interval = 100; // Interval
const byte NUM_SAMPLES = 20;
double buffer_range [NUM_SAMPLES];

// Range Sensor Instanzen-----------------------------
double Current_range = 0; //4-20 mA
double rawADCValue_range = 0;
double ADCVoltage_range = 0; //0-3,3 V
double range = 0; //0-50mm
unsigned long range_t;

double mapfloat(double x, double in_min, double in_max, double out_min, double out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

double round_range(double value) {
  return (int)(value * 100 + 0.5) / 100.0;
}

void Read_Scale() {

  StaticJsonDocument<1000> doc;

  static int scale_counter = 0;

  if (millis() - scale_previousMillis >= scale_interval) {
    scale_previousMillis = millis();

    rawADCValue_range = 0;
    for (int i = 0; i < 100; ) {
      if (millis() - range_t  >= 1) {
        rawADCValue_range += analogRead(ADC_Range_Pin);
        i++;
        range_t = millis();
      }
    }

    ADCVoltage_range = (double)(rawADCValue_range / 100.0) * (3.3 / 4095.0);
    Current_range = mapfloat(ADCVoltage_range, 0.8, 3.3, 4, 20);
    range = mapfloat(Current_range, 4, 20, 0, 50);

    buffer_range[scale_counter] = range ;

    scale_counter ++;

    JsonArray rangeValues = doc.createNestedArray("Range");

    if (scale_counter >= NUM_SAMPLES)
    {
      for (int i = 0; i < NUM_SAMPLES; i++) {
        rangeValues.add (buffer_range[i]);
      }

      serializeJson(doc, Serial);
      Serial.println();
      scale_counter = 0;
      Serial.println();

    }
  }
}

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

void loop() {
  Read_Scale();
}

```

# Answer
> 2 votes
You defined the rounding function `round_range()`, but never used it. You want to round the numbers that you are putting into the array within the JSON document:

```
rangeValues.add(round_range(buffer_range[i]));

```

---
Tags: programming, esp32, library, json
---


# Question
Title: File include error while using Arduino Nano
I am using the code below to interface the Arduino nano and android cell phone to enable serial communication through the USB port. I downloaded the filter library from GitHub https://github.com/JonHub/Filters

I am getting an error saying thet the library is not found. I would really appreciate some suggestions on this.

Here is my code:

```
 //This code is for arduino communicating to android phone through USb serial port.
 //For arduino nano

 #include <Filters.h>   //implements digital filters which mimic the analog filter, keep track of variable statistics in realtime

char data_read; //character datatype takes up to 1 byte of memory
unsigned int analog_out;
unsigned long time;
float filterFrequency = 10.0;
FilterOnePole lowpassFilter( LOWPASS, filterFrequency );//implements digital RC type filter; both highpass and lowpass

 void setup()
 {
  Serial.begin(115200); //open the serial port and set the baud rate for communication
  // create a one pole (RC) lowpass filter

 }
 void loop()
 {
 }

 void serialEvent() { //Used when data is unavailable yet
 if (Serial.available()) //checks the number of bytes available for reading from the serial port
 {
data_read = Serial.read();

if (data_read == '0') {
  Serial.print("#");

  //Serial.print("10100");
  analog_out = lowpassFilter.input( analogRead(0) );
  Serial.print(analog_out + 10000);

  Serial.print(":");

  //Serial.print("20200");
  analog_out = lowpassFilter.input( analogRead(1) );
  Serial.print(analog_out + 20000);

  Serial.print(":");

  //Serial.print("30300");
  analog_out = lowpassFilter.input( analogRead(2) );
  Serial.print(analog_out + 30000);

  Serial.print("p");
}
/*if(data_read == '0' || data_read == '1' || data_read == '2' || data_read == '3' || data_read == '4' || data_read == '5'){
  analog_out = lowpassFilter.input( analogRead( data_read-48 ) );
  Serial.print((analog_out)+(data_read-48)*10000);
  Serial.print(":");
  }else if(data_read =='p'){
  Serial.print("p");
  }*/
   }
 }

```

Here is my error message:

```
  Arduino: 1.8.5 (Windows 10), Board: "Arduino Nano, ATmega328P"

  C:\Users\daphn\Documents\Arduino\Analog_Serial_out\Analog_Serial_out.ino:4:129: fatal error: Filters.h: No such file or directory

  #include <Filters.h>   //implements digital filters which mimic the analog filter, keep track of variable statistics in realtime

                                                                                ^

  compilation terminated.

  exit status 1
  Error compiling for board Arduino Nano.

  This report would have more information with
  "Show verbose output during compilation"
   option enabled in File -> Preferences.

```

# Answer
You have to put the folder with the library files in the folder `libraries` under your sketchbook folder. Then the IDE should be able to find them.

I think there is also a possibility to save them in the same folder as your `.ino` file, but it I don't know how exactly you have to do this.
> -1 votes

# Answer
Here is your definitive answer.

You have to do the #include like the following (with double-quotes, not \< \> brackets)

`#include "Filters.h"`

This will make Arduino compiler look in the project folder.

Using \< \> brackets tells the compiler that it is in the standard library area.

I just tested this with the following script.

```
#include "mytest.h"
void setup() {
  // put your setup code here, to run once:

}

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

}

```

The `mytest.h` file is blank (has no text in it).

It wouldn't work until I included it using the double-quotes method.
> -1 votes

---
Tags: arduino-nano
---


# Question
Title: Detect the end of playback of a MP3 file with DFPlayerMini / DFRobotDFPlayerMini.h library
For a project I'm doing I've used an ESP8266/12e, a RTC Module DS3231 and a DFplayerMini

Basically it's a caller for birds and it has to play a 12-minute long MP3. The MP3 file should be played for 2 hours at the sunrise and 2 hours before the sunset, so each time it should be played 10 times (*10 × 12 = 120 minutes (2 hours)*)

The code I wrote so far (some parts are omitted for brevity):

```
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
#include <Wire.h>
#include <RtcDS3231.h>

#define DELAY_ONPLAY 1000
#define DELAY_ONPAUSE 20000

// RTC Library (I2C)
RtcDS3231<TwoWire> rtcObject(Wire);

// MP3 Serial communication
SoftwareSerial mySoftwareSerial(14, 12);
DFRobotDFPlayerMini myDFPlayer;

// Variables
int volume, mth, day, h, m;

// State of the playback
int playbackCount = 0;
bool isPlaying = false;

RtcDateTime currentTime;

void setup() {

    mySoftwareSerial.begin(9600);
    // Start serial connection
    Serial.begin(115200);
    // Start I2C
    rtcObject.Begin();

    if (!myDFPlayer.begin(mySoftwareSerial)) {
      while(true){
        delay(10);
      }
    }

    /* Get the value of potentiometer in the range of [3..30] and
     * set the volume
     */
    setVolume();

}

void loop() {

    setVolume();
    currentTime = rtcObject.GetDateTime();    //get the time from the RTC

    mth  = currentTime.Month();
    day  = currentTime.Day();
    h    = currentTime.Hour();
    m    = currentTime.Minute();

    /* The caller is not playing: check if date and time should
     * start the playback
     */
    if (isPlaying == false) {

        if (startSunrise() || startSunset()) {
            isPlaying = true;
        }

        else {
            // Nothing to do for the next 20 seconds
            delay(DELAY_ONPAUSE);
        }
    }

    else {

      // Currently playing
      if (playbackCount < 10) {

          if (/* MP3mini_is_idle */) {

            myDFPlayer.play(1);
            playbackCount = playbackCount + 1;

          }
      }

      else {
        playbackCount = 0;
        isPlaying = false;
        Serial.print("End of playback");
      }

      delay(DELAY_ONPLAY);

    }
}

void setVolume() {

    // Get the value of potentiometer in the range of [3..30]
    volume = map(analogRead(A0), 0, 1023, 2, 30);
    volume = constrain(volume, 3, 30);
    // Set the player volume
    myDFPlayer.volume(volume);
    Serial.println(String(volume));

}

bool startSunrise() {

    /* at the sunrise the call has to be played for 2 hours */

    if (mth == 2) {
        if ((day == 20 && h == 7 && m == 8) ||
            (day == 21 && h == 7 && m == 6) ||
            ...
            (day == 28 && h == 6 && m == 54) ||
            (day == 29 && h == 6 && m == 52)) { return true; }
    }

    if (mth == 3) {
        if ((day == 1  && h == 6 && m >= 49) ||
            (day == 2  && h == 6 && m >= 47) ||
            (day == 3  && h == 6 && m >= 45 ) ||
            (day == 4  && h == 6 && m >= 43) ||
            ...
            (day == 27 && h == 6 && m >= 0) ||
            (day == 28 && h == 5 && m >= 58)) { return true; }
    }

    return false;
}

bool startSunset() {

    /* 2 hours before sunset the call has to be played for 2 hours */

    if (mth == 2) {
        if ((day == 20 && h == 15 && m >= 41) ||
            (day == 21 && h == 15 && m >= 42) ||
            ...
            (day == 28 && h == 15 && m >= 52) ||
            (day == 29 && h == 15 && m >= 54)) { return true; }
    }

    if (mth == 3) {
        if ((day == 1  && h == 15 && m >= 56) ||
            (day == 2  && h == 15 && m >= 58) ||
            (day == 3  && h == 15 && m >= 59) ||
            (day == 4  && h == 16 && m >= 1) ||
            ...
            (day == 27 && h == 16 && m >= 31) ||
            (day == 28 && h == 16 && m >= 33)) { return true; }
    }

    return false;
}

```

The part I'm stuck on is

```
  if (playbackCount < 10) {

      if (/* MP3mini_is_idle */) {

        myDFPlayer.play(1);
        playbackCount = playbackCount + 1;

      }

  }

```

How do I detect in the `if` condition if the MP3 is actually playing before play it again? I think a 12-minute `delay()` is not the right approach.

In the image below the DFPlayerMini pinout: I noticed It has a `BUSY` pin but I haven't found examples so far that uses this pin to detect the playback state.

Thanks for any suggestion.

# Answer
As @chrisl alread said, you could use the busy pin. Or a simple serial query

```
myDFPlayer.readState();

```

If the result is something like `DFPlayerPlayFinishe` the actual track is complete.
> 1 votes

# Answer
The busy pin, means that the flash memory is being accessed. So its not the same as "track being played".
> 1 votes

---
Tags: esp8266, audio, rtc
---


title: Round to first significant digit

text:
# Question
Title: Round to first significant digit
I want to round a decimal number (x), but I need to do it differently depending on how it is. If it has integer significant digits, we round to the nearest integer, and if not, we round to the first significant digit. So the following would happen with these example numbers: 11.871-\>12, 11.177-\>11, 37.233-\>37, 37.779-\>38, 0.578-\>0.6, 0.544-\>0.5, 0.0257-\>0.03, 0.0223-\>0.02... (The numbers could have more or less decimal places than in the examples).

To implement this, I have created a function (type) in which we check if the most significant digit is of type integer or decimal. This function returns this characteristic of the number in the form of a "string". So if the most significant digit is an integer we just use the "round()" function. However, I don't know how to round a number to the first significant digit (roundto\_fsd() function). Does anyone know of any function capable of doing this or any method to do it?

```
float x;

char type(float number) {
  char type[8];
  if (int(number) != 0) {
    type = "integer";
  } else {
    type = "decimal";
  }
  return type;
}

float roundto_fsd(float number) {}

void setup() {
  Serial.begin(9600);
  if (!type(x).compareTo("integer")) {
    Serial.println(round(x));
  } else if (!type(x).compareTo("decimal")) {
    Serial.println(roundto_fsd(x));
  }
}

void loop() {}

```

# Answer
> 1 votes
First of all, let me clarify that there is nothing “decimal” in a `float`: a `float` is a **binary** (not decimal) floating point number. The `Serial.println()` function does a binary-to-decimal conversion for the purpose of representing the number as human-readable text. If you want a specific number of **decimal** digits after the radix point, you should ask `Serial.println()` to provide them. This is done by passing this number as a second parameter:

```
Serial.println(sqrt(2));    // prints "1.41" (2 decimals by default)
Serial.println(sqrt(2), 0); // prints "1"
Serial.println(sqrt(2), 5); // prints "1.41421"

```

Now the question is: how to compute the number of required digits after the radix point? This depends on how big the `float` is. If it is smaller than 1 but larger or equal to 0.1, you want just one digit. If it is ten times smaller than that, you want to digits, and so on:

```
numbers      digits
───────────────────
[1, +∞)        0
[0.1, 1)       1
[0.01, 0.1)    2
[0.001, 0.01)  3

```

I suggest repeatedly multiplying your `float` by 10 until it gets ≥ 1, and count the number of times you had to do so:

```
/* How many decimal places to print. */
int decimal_places(float x)
{
    int i = 0;
    while (x < 1) {
        x *= 10;
        i++;
    }
    return i;
}

```

You would use this function like this:

```
Serial.println(x, decimal_places(x));

```

Note that there is a small issue with this approach. If you try to print 0.97, `decimal_places()` will say you need one decimal, and `Serial.println()` will print “1.0”. If you would rather have it print “1”, then change the loop condition within `decimal_places()` to:

```
while (x < 0.95)

```

**Caveat**: All this assumes that the numbers you want to print are all strictly larger than zero. Otherwise `decimal_places()` would have an infinite loop.

---
Tags: arduino-uno, programming, functions
---


# Question
Title: HM-10 BLE controller is not responding to some AT commands
I have HM-10 BLE controller and it is not responding to some AT commands which I need to use.

AT commands which don't work:

* `AT+TYPE2` returns `+TYPE=0`
* `AT+VERR?` not responding
* `AT+VERS?` not responding
* `AT+RESTART` not responding
* `AT` not responding but `AT+`responds with `OK`
* `AT+VERSION` responding with `MLT-BT05-V4.1`

The most important command for me is `AT+TYPE2` because even if I set pin with command `AT+PIN112233`, in my Android App, `AlertDialog` with `password` field is not activated during connection with `bleGatt = bleDevice.connectGatt(this, true, bleGattCallback)` function.

I even tried to call `createBond()` function on this device, but it is not returning anything. I need to activate pairing with password with `AT+TYPE2` but its always returning 0 which is default connection without password and pairing method.

I'm not sure if I have some bugged HM-10 controller but I cant even reset it to default settings. It is working fine with transfering data by characteristics but other stuff is not working.

I've used some weird iterating function to print out AT+HELP commands for this controller and AT+TYPE is not listed there as a command. That means I cant set pairing method? What kind of BLE device has pairing disabled and there is not option to set up at least password?

Here are my commands

```
21:01:19.739 ->  Command             Description
21:01:19.880 ->  ----------------------------------------------------------------
21:01:19.949 ->  AT                  Check if the command terminal work normally
21:01:20.054 ->  AT+RESET            Software reboot
21:01:20.159 ->  AT+VERSION          Get firmware, bluetooth, HCI and LMP version
21:01:20.271 ->  AT+HELP             List all the commands
21:01:20.365 ->  AT+NAME             Get/Set local device name
21:01:20.459 ->  AT+PIN              Get/Set pin code for pairing
21:01:20.552 ->  AT+PASS             Get/Set pin code for pairing
21:01:20.646 ->  AT+BAUD             Get/Set baud rate
21:01:20.740 ->  AT+LADDR            Get local bluetooth address
21:01:20.880 ->  AT+ADDR             Get local bluetooth address
21:01:20.950 ->  AT+DEFAULT          Restore factory default
21:01:21.054 ->  AT+RENEW            Restore factory default
21:01:21.157 ->  AT+STATE            Get current state
21:01:21.271 ->  AT+PWRM             Get/Set power on mode(low power)
21:01:21.365 ->  AT+POWE             Get/Set RF transmit power
21:01:21.459 ->  AT+SLEEP            Sleep mode
21:01:21.553 ->  AT+ROLE             Get/Set current role.
21:01:21.693 ->  AT+PARI             Get/Set UART parity bit.
21:01:21.787 ->  AT+STOP             Get/Set UART stop bit.
21:01:21.834 ->  AT+START            System start working.
21:01:21.952 ->  AT+IMME             System wait for command when power on.
21:01:22.056 ->  AT+IBEA             Switch iBeacon mode.
21:01:22.161 ->  AT+IBE0             Set iBeacon UUID 0.
21:01:22.264 ->  AT+IBE1             Set iBeacon UUID 1.
21:01:22.381 ->  AT+IBE2             Set iBeacon UUID 2.
21:01:22.475 ->  AT+IBE3             Set iBeacon UUID 3.
21:01:22.569 ->  AT+MARJ             Set iBeacon MARJ .
21:01:22.663 ->  AT+MINO             Set iBeacon MINO .
21:01:22.756 ->  AT+MEA              Set iBeacon MEA .
21:01:22.850 ->  AT+NOTI             Notify connection event .
21:01:22.967 ->  AT+UUID             Get/Set system SERVER_UUID .
21:01:23.071 ->  AT+CHAR             Get/Set system CHAR_UUID .
21:01:23.174 ->  -----------------------------------------------------------------
21:01:23.257 ->  Note: (M) = The command support slave mode only.

```

# Answer
> 1 votes
same as me... clone of a hm10.
not very much info on this board.
at command doesn't works when they are in caps .. no need ? or = after command.
you can paired with at+connX (x is the device number, the first founded is 1. the second is 2, etc etc).
it cannot auto connect even if you paired them before. not much range (7 meter).

---
Tags: arduino-nano, android, ble
---


title: Generalize webserver routing

text:
# Question
Title: Generalize webserver routing
I'm following the examples for ESP32:

```
  AsyncWebServer _server(80);

  _server.on("/", HTTP_GET, [](AsyncWebServerRequest *request)
  {
    request->send(SPIFFS, "/index.html", String(), false);
  });

  _server.on("/css/index.css", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/css/index.css", "text/css");
  });

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

_server.begin();

```

With this approach I have to know in advance each file I store in the `SPIFFS` and add a handler for each one.

Is there a more elegant way to automatically serve any file that exists in the flash?

# Answer
You can tell the webserver to serve the static content from a specific folder:

```
server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html");

```

In this case it serves on the root URL the content from the SPIFFS root. So if I place a file called `image.jpg` in the SPIFFS root it will be served at `/image.jpg`. For more information you can look at the corresponding section of the libraries Readme file.
> 3 votes

---
Tags: esp32, web-server
---


# Question
Title: How often does a mpu6050 gyro sonsor need calibration?
I want to use it in my real car for daily use to measure yaw angle when needed.

Is is ok to only calibrate it once at first then use it every day when driving without any problem? if not, how often should I recalibrate it?

# Answer
Most accelerometers and gyroscopes need little if any calibration. Consult the manufactures specification sheets. If any calibration is made and correction values found, then it is assumed those values may be used in the future for the same accelerometer / gyroscope.

This analog.com document goes into gyroscope calibration details.

Deriving the angle of the car (the "yaw") at any given moment will likely be problematic. Errors from integrating the gyroscope's axis which is perpendicular to the ground will accumulate over time. Which is the main problem when using dead reckoning.

Consider using a magnetometer & accelerometer along with the gyroscope in order to mitigate the accumulated errors from only using the gyroscope.
> 1 votes

---
Tags: sensors, mpu6050, robotics, gyroscope, calibration
---


# Question
Title: Playing Melody with Tone() without using delay()
Is there a method to play a Melody with Tone() without using the delay() function?

```
tone(8, melody[thisNote], noteDuration);
int pauseBetweenNotes = noteDuration;
**delay(pauseBetweenNotes);**

```

# Answer
As others have noted, this can be done using the same method as used in the standard 'BlinkWithoutDelay' example sketch, and combining that with a state-machine type approach. In a simple state machine you'd assume you can be in one of two states: outputting a tone, and not outputting a tone.

Applying these ideas to your code snippet above:

```
// BEFORE SETUP
const int tonePin = 8;
unsigned long previousMillis = 0;
const long interval = pauseBetweenNotes;
const long interval = noteDuration;
boolean outputTone = false;                // Records current state

// IN LOOP
unsigned long currentMillis = millis();

if (outputTone) {
// We are currently outputting a tone
// Check if it's been long enough and turn off if so
    if (currentMillis - previousMillis >= noteDuration) {
        previousMillis = currentMillis;
        noTone(tonePin);
        outputTone = false;
    }
} else {
// We are currently in a pause
// Check if it's been long enough and turn on if so
    if (currentMillis - previousMillis >= pauseBetweenNotes) {
        previousMillis = currentMillis;
        tone(tonePin, melody[thisNote]);
        outputTone = true;
    }
}

```
> 4 votes

# Answer
Adding a bit to kabdulla's great example, to be able to use a MelodyArray

```
// declaring variables
const int tonePin = 10;
unsigned long previousMillis = 0;
const long pauseBetweenNotes = 250;   // interval between notes (ms)
const long noteDuration = 400;        // (ms)
boolean outputTone = false;                // Records current state
const int MelodyLength = 2;
const int Melody[MelodyLength] = {880, 698};
int MelodyIndex = 0;
unsigned long currentMillis;

void setup() {
}

void loop() {
  currentMillis = millis();
  PlayMelody();
}

void PlayMelody() {
  if (outputTone) {
    // We are currently outputting a tone
    // Check if it's been long enough and turn off if so
    if (currentMillis - previousMillis >= noteDuration) {
      previousMillis = currentMillis;
      noTone(tonePin);
      outputTone = false;
    }
  } else {
    // We are currently in a pause
    // Check if it's been long enough and turn on if so
    if (currentMillis - previousMillis >= pauseBetweenNotes) {
      previousMillis = currentMillis;
      tone(tonePin, Melody[MelodyIndex]);
      outputTone = true;
      //Update to play the next tone, next time
      MelodyIndex = MelodyIndex + 1;
      if (MelodyIndex >= MelodyLength) {
        MelodyIndex = 0;
      }
    }
  }
}

```
> 1 votes

# Answer
this is a minimal modification of the basic Arduino toneMelody example to a non-blocking version

```
#include "pitches.h"

// notes in the melody:
int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};

unsigned long previousMillis = 0;
unsigned long pauseBetweenNotes;
int thisNote;

void setup() {
}

void loop() {

  // iterate over the notes of the melody:
  unsigned long currentMillis = millis();
  if (thisNote < 8 && currentMillis - previousMillis >= pauseBetweenNotes) {
    previousMillis = currentMillis;

    // to calculate the note duration, take one second divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000 / noteDurations[thisNote];
    tone(8, melody[thisNote], noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    pauseBetweenNotes = noteDuration * 1.30;

    thisNote++;
  }
}

```
> 1 votes

---
Tags: arduino-uno
---


# Question
Title: Using MCP23017 with 5 rotary encoders, WITHOUT missing a single step from any of them?
I have recently followed the instructions in the answer to this question: Reading several rotary encoders posted by maximilian-gerhardt

I've wired everything up, and am using the interrupts example that can be found here: https://github.com/maxgerhardt/rotary-encoder-over-mcp23017/tree/master/examples/Interrupt

Everything seems to work as expected, except that my assumption was that since this was an interrupt-based solution, that I wouldn't be missing any steps of any of the encoders. There are a total of 5 that will move at the same time, and it is clear that while it *almost* works, there are many steps that are missed.

I'm guessing that is because while one interrupt is being handled, all other interrupts are disabled?

Is there any way where I can ensure that every single motion (step CW or CCW) is registered on all 5 encoders?

Thanks! Brian

# Answer
> 1 votes
I would use a different approach. Consider setting a flag when an interrupt occurs, a different flag for each interrupt then processing that in the main loop rather then the ISR (Interrupt Service Routine). Connecting with the SPI in the 1.7 MHz mode will allow you to get in check the interrupt set the flag and leave the ISR. This will be a bit difficult to write but I think it would work very well. Taking a quick scan of the data sheet the MCP23917 should be the correct part to accomplish this. Also do the debouncing externally, will save a lot of code and speed up the process.

# Answer
> 0 votes
Interrupts don't mean that you can do lots of things at the same time. All they mean is that something can be responded to rapidly, as long as nothing else is being responded to of an equal or higher priority.

And coupling that with an IO expander which will inevitably slow things down means that you really can't do what you are trying to do.

If you want to respond instantly to every single pulse of every single encoder then each encoder has to be attached to something that can itself respond to those pulses.

I would be inclined to have a small microcontroller attached to each individual encoder (or maybe two encoders if you have enough interrupt pins) and deal with each separately - that way one encoder *cannot* interfere with any other. The small MCU can then keep track of position or count (depending on what it is you are trying to do) and you communicate that to a "master" controller (the Arduino for example) over some other bus, asynchronously to the encoder's pulses.

If you want more rapid response to the encoder movements then it could be possible to implement your own interrupt signal from the small MCU to the Arduino to say "My encoder has been moved", at which point the Arduino can collect the data. It won't matter how long that takes to happen as the small MCU will be keeping track of any other changes. The ATTiny85 using Pin Change Interrupts could be a good low-cost choice for this.

---
Tags: arduino-uno, interrupt
---


title: Adjusting Threshold for Digital Pins

text:
# Question
Title: Adjusting Threshold for Digital Pins
I am working on a project using Force Sensors to build a keyboard for MD patients. I have connected the sensors (each with 4 input pins) to **digital pins** to *Arduino Due*. I want to adjust the threshold of the digital pins in order to cancel out the initial weight of a user's hand when using the keyboard. I have read that digital pins have a built-in threshold ("low"\<0.3 Vcc and "high"\>0.6Vcc). I can't connect my sensors to Analog pins (due to needing 20 input pins), and was wondering if adjusting the threshold is possible? I have researched and found one project that used Analog pins and adjusted the threshold, which I am trying to emulate: https://www.instructables.com/Arduino-Programmable-Button-Panel-As-Keyboard/ P.S: I am a beginner at Arduino and would appreciate the help

# Answer
No, you cannot change these threshold. They are set by the digital input hardware (technically a Schmitt trigger) inside the microcontroller. They are not meant to be adjustable, since they are digital input, not analog inputs.

So you either need to build your own adjustable logic (involving opamps and variable resistors), feeding the output of that to the Arduino, or you need to use analog inputs.

I would suggest using the second method. You can extend the number of analog inputs basically by 2 means:

* You can buy analog multiplexers. These are chips that can connect one analog input of the Arduino on one side to X pins on the other side. Most of them are controlled via digital pins. Then you cycle through each setting of the multiplexer to connect one sensor at a time and do a measurement on each of them. Each analog pin can be connected to one analog multiplexer
* You can buy an external ADC board. These are often connected via interfaces like I2C or SPI (for example this one from Adafruit with 4 channels each). You can use multiple of them.
> 1 votes

---
Tags: sensors, arduino-due, digital, keyboard
---


# Question
Title: ESP32 Potentiometer issue: Resolution mismatch of the potentiometer with unlimited resolution and reading the values with Wire.h
I have the problem, that the potentiometer goes from the range of 0 Volts to 3,3 volts. But within this range the measured value goes **from about 0 to 65535 multiple times** (over 10 cycles).

When I change the code from my ADC library to 32 bit I get 32 bit values (0 - 4294967296) but the same error with the beginning at 0 multiple times within the potentiometer range occurs.

**Hardware:**

**Board:** ESP32 **ADC:** MAX11613 (12 bit adc) https://www.mouser.de/datasheet/2/256/MAX11612-MAX11617-1508955.pdf **Potentiometer:** 3046L - 3 - 203 https://www.mouser.de/datasheet/2/54/3046-776396.pdf

Part of the code that reads the adc values:

```
uint8_t MAX11613::MAX11613_ADC_Read(structMAX11613* chip, uint8_t channel, uint16_t* val){

    uint8_t configurationByte = ( (channel<<1) & 0x0e) | 0x61;
    MAX11613_Configuration(chip, configurationByte);

    Wire.beginTransmission(chip->devAddress);
    Wire.requestFrom(chip->devAddress, (byte) 2);    // request 2 bytes from slave device wireIface
    while (Wire.available()) { // slave may send less than requested
    //char c = Wire.read(); // receive a byte as character

    uint16_t value = 0;
    value =  Wire.read();
    value |= Wire.read() << 8;

    //This also works:
    /*uint32_t buf1;
    size_t actually_read = Wire.readBytes((uint8_t*)&buf1, 2);
    *val = actually_read;
    //Serial.println(value);*/

    *val = value;
    }
    if (Wire.endTransmission() != 0){
    return 1;
    }
    return 0;

}

```

# Answer
> 1 votes
The MAX1161x are 12-bit ADCs, so the problem is not related to an uint16 overflow as you seem to assume. The ADC transmits most significant bits (MSB) first as can be seen in figure 10 on page 17. To account for that you need to change

```
value =  Wire.read();
value |= Wire.read() << 8;

```

to

```
value = Wire.read() << 8;
value |=  Wire.read();

```

---
Tags: esp32, adc, potentiometer
---


# Question
Title: Apparently the photoresistors don't pass the input at the leds
I am making a school project where i need to create a parking loot in tinkercad. Me and my mate tried to use a bunch of photoresistor that worked as a sensor. No light = car = red led; light = no car = green led. We can't figure out why the leds dont turn on. We are still on a low level of abilities on this type of work and in class we didn't see a lot of components, so the photoresistor were one of the best choice.

Here is the screenshot of the whole project, it's in italian so if you guys needs a transduction of the variable just tell me. Don't mind the button, we were trying something.

Here is the code: In this line "if(analogRead(fotoresistori\[i\]) \< 300)" we put 300 because with 0 etc. it did not work

```
int fotoresistori[] = {A0, A1, A2, A3, A4};
int verdi[] = {11, 10, 9, 8, 7};
int rossi[] = {6, 5 , 4, 3, 2};

void setup()
{
  pinMode(13, INPUT);
  pinMode(12, INPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(2, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  Serial.println(postiDisponibili);
  if(digitalRead(13) == HIGH){
    postiDisponibili++;
  }
  else if(digitalRead(12) ){
    postiDisponibili--;
  }
  for(int i = 0; i<5; i++){
    if(analogRead(fotoresistori[i]) < 300){
      digitalWrite(rossi[i], HIGH);
      digitalWrite(verdi[i], LOW);
    }else{
      digitalWrite(rossi[i], LOW);
      digitalWrite(verdi[i], HIGH);
    }
  }
  delay(500);
}

```

The value of A0 is always at 0.

# Answer
You're not applying any voltage to the photoresistors and the other end is connected to earth so it will always be zero. You need to connect the analog end to +5v via a suitable current limiting resistor (suggest 10K for a typical photoresistor) then measure the voltage.
> 0 votes

---
Tags: arduino-uno, led, photoresistor
---


# Question
Title: How to append to array of Strings in arduino?
Here is my code:

```
char *StrAB[] = {"29 EC C7 C1", "69 5B C9 C2", "22 3B 83 34",  "12 BF BF 34", "C6 78 8E 2C" };
void setup() {
  Serial.begin(9600);
}
void loop() {
  for (int i = 0; i < sizeof(*StrAB)+1; i++)
  {
    Serial.println(StrAB[i]);
    delay(1000);
  }
  Serial.println(sizeof(*StrAB)+1);
  StrAB[sizeof(*StrAB)+1]= "00 00 00 00";
}

```

I'm trying to append to the end of array of strings but it doesn't work? How can I delete a string from the array?

# Answer
As stated by Sim Son in a comment, an array is a fixed-size data structure in C++. You thus have to choose beforehand a suitable size, and then keep track of how much of the array is actually used. For example:

```
const int AB_max = 10;  // array capacity
const char *AB_str[AB_max] = {"29 EC C7 C1", "69 5B C9 C2",
    "22 3B 83 34",  "12 BF BF 34", "C6 78 8E 2C"};
int AB_count = 5;  // used slots

```

To add a string to this array, you write it to the next available slot. But you have first to make sure there is still room available:

```
void AB_add(const char *s) {
    if (AB_count < AB_max)
        AB_str[AB_count++] = s;
}

```

If you want to remove an item (other than the last one), you will have to shift all the following items down the array. The `memmove()` function comes handy for this:

```
void AB_remove(const char *s) {
    // Find the index of s.
    int i;
    for (i = 0; i < AB_count; i++)
        if (strcmp(s, AB_str[i]) == 0) break;

    // Do nothing if not found.
    if (i == AB_count) return;

    // Move subsequent items down the array.
    memmove(&AB_str[i], &AB_str[i+1],
            (AB_count - (i + 1)) * sizeof *AB_str);
    AB_count--;
}

```

Note that moving these items down can be costly if the array is pretty long. An array may then not be the best data structure for you. I wouldn't worry though if it's just a dozen items or so.

Here is now a small test for all of the above:

```
void AB_print() {
    Serial.print("AB: ");
    Serial.print(AB_count);
    Serial.println(" items");
    for (int i = 0; i < AB_count; i++) {
        Serial.print("    ");
        Serial.println(AB_str[i]);
    }
    Serial.println();
}

void setup() {
    Serial.begin(9600);
    AB_print();
    AB_add("00 00 00 00");
    AB_print();
    AB_remove("12 BF BF 34");
    AB_print();
}

void loop() {}

```

Note that this is a very “C” style of doing things. If you want to go to more idiomatic C++, you can start by putting everything that is named with the prefix `AB_` inside a class.

If you really want an array where you can vary the length, you may allocate it with `malloc()` and resize it with `realloc()`. These functions, however, are not very friendly to memory-constrained devices. They are thus often avoided in the embedded world. They may also not play well with code that uses `new` and `delete`, including library code that you may not be aware of.
> 3 votes

---
Tags: esp8266, array
---


title: How to do multiple serial.read()

text:
# Question
Title: How to do multiple serial.read()
first of all im new here and im really sorry if there's some mistakes when im making this question. So im trying to make a program to calculate using serial read, and im going to input a lot of values.

These are the codes that im trying to upload, but it wont shows the input.

```
int PpmNeed;
int Ppmpertank;
int nyala;
int tangki;
int sensor;
int mlkeluar;
int perlakuan;
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);
}

void loop() {
    Serial.println("Besar Tangki");
    while(Serial.available() == 0){}
    tangki = Serial.parseInt();

    Serial.println("Kadar Dari Sensor");
    while(Serial.available() == 0){}
    sensor = Serial.parseInt();

    Serial.println("Data Perlakuan");
    while(Serial.available() == 0){}
    perlakuan = Serial.parseInt();

    Serial.print("Besar Tangki : ");
    Serial.println(tangki);
    Serial.print("Kadar Dari Sensor : ");
    Serial.println(sensor);
    Serial.print("Data Perlakuan : ");
    Serial.println(perlakuan);
}

```

# Answer
While your way to read the input from user is sub-optimal, to make it work you have to read the new line characters Serial Monitor sends (if line ending are selected in the drop down box).

The new line characters are available on Serial after the digits, so they make

```
while(Serial.available() == 0){}

```

to end immediately.

You can patch it up by reading the trailing line ending characters.

```
int PpmNeed;
int Ppmpertank;
int nyala;
int tangki;
int sensor;
int mlkeluar;
int perlakuan;
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);
}

void loop() {
    Serial.println("Besar Tangki");
    while (Serial.available()) {
      Serial.read();
    }
    while(Serial.available() == 0){}
    tangki = Serial.parseInt();

    Serial.println("Kadar Dari Sensor");
    while (Serial.available()) {
      Serial.read();
    }
    while(Serial.available() == 0){}
    sensor = Serial.parseInt();

    Serial.println("Data Perlakuan");
    while (Serial.available()) {
      Serial.read();
    }
    while(Serial.available() == 0){}
    perlakuan = Serial.parseInt();

    Serial.print("Besar Tangki : ");
    Serial.println(tangki);
    Serial.print("Kadar Dari Sensor : ");
    Serial.println(sensor);
    Serial.print("Data Perlakuan : ");
    Serial.println(perlakuan);
}

```
> 1 votes

# Answer
Your problem is that humans are slow. Very slow.

Functions like `Serial.parseInt()` etc are designed for reading data from sensors. As such they expect data to arrive fast. They have a *timeout* whereby they will abort if data doesn't arrive in a timely fashion.

That's not conducive to interacting with a human that likes to take their time typing in numbers.

Instead you will need to write a routine (or find one online, such as the one I show here) which stops and waits for input to be provided before then parsing the given data and continuing.

If you're interacting with a serial terminal rather than the Arduino IDE's serial "monitor" then it can also be good to echo back the characters as they are received so the person typing can see what they have typed. Line editing (or at least basic backspace handling) would also be useful in that situation too.
> 3 votes

# Answer
a short function to read user Inputs. do not wort if user sends multiple numbers at once

USE ONLY FOR HUMAN INPUT.

```
#define NOP __asm__ __volatile__ ("nop\n\t")

//Read next number
int nextNumber() {
  int input = 0;

  //wait for next Byte
  while (Serial.available() == 0) {NOP;}

  /read number
  input = Serial.parseInt();

  //Give some time for bytes to get over Serial bus, then remove it
  delay(1);
  while (Serial.available() > 0) {
    int incomingByte = Serial.read();
  }
  return input;
}

```
> 0 votes

---
Tags: arduino-uno, arduino-ide
---


# Question
Title: My Atlas Scientific sensors measurement give zero values at first reading
I am still continuing my hydroponic nutrient monitoring project. In short, I made a hydroponic nutrient monitoring system with I2C connection, and decided to do serial communication with Raspberry Pi 3B+ to save sensor reading data in CSV file. I am curious about why after uploading the sketch, the sensors always gives zero values at first reading on Serial Monitor.

This is the screenshot of my Serial Monitor.

From left to right: timestamp, EC, pH, Temperature.

Everytime I reset the Arduino, the Serial Monitor first will show no values. On the second line, it shows only EC value. The third line only EC and pH value, then the fourth line and so on will show all values.

**How to make the Arduino show all sensor values from the start in the Serial Monitor?**

Here is my code that I modified from Atlas Scientific page for my project:

```
#include <Ezo_i2c.h>
#include <Wire.h>

Ezo_board ec = Ezo_board(100, "EC");
Ezo_board ph = Ezo_board(99, "PH");
Ezo_board temp = Ezo_board(102, "RTD");

bool reading_request_phase = true;

uint32_t next_poll_time = 0;
const unsigned int response_delay = 1000;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  delay(1000);

}

void loop() {
  if (reading_request_phase)
  {
    ec.send_read_cmd();
    ph.send_read_cmd();
    temp.send_read_cmd();

    next_poll_time = millis() + response_delay;
    reading_request_phase = false;
  }
  else
  {
    if (millis() >= next_poll_time)
    {
      receive_reading(ec);
      receive_reading(ph);
      receive_reading(temp);

      reading_request_phase = true;
    }
  }
}

void receive_reading(Ezo_board &Sensor) {
  Sensor.receive_read_cmd();
  Serial.println();
  Serial.print(ec.get_last_received_reading()/1000);
  Serial.print(",");
  Serial.print(ph.get_last_received_reading());
  Serial.print(",");
  Serial.print(temp.get_last_received_reading());
  Serial.print("");
  delay(1000);
}

```

# Answer
Each time you call `receive_reading()` you pass it *one* sensor to read the value from. But each time you call `receive_reading()` you print out *all three* sensors.

So you:

1. Read EC and print EC PC TEMP
2. Read PC and print EC PC TEMP
3. Read TEMP and print EC PC TEMP

In step one you only have EC, you haven't read PC or TEMP yet. In step two you have the old reading of EC and a new PC reading but still no TEMP reading. By step three you finally have a TEMP reading but still the old EC and PC readings from earlier.

You should instead put the receiving command (`Sensor.receive_read_cmd()`) once for each sensor as a separate thing to displaying the received values. More like:

```
#include <Ezo_i2c.h>
#include <Wire.h>

Ezo_board ec = Ezo_board(100, "EC");
Ezo_board ph = Ezo_board(99, "PH");
Ezo_board temp = Ezo_board(102, "RTD");

bool reading_request_phase = true;

uint32_t next_poll_time = 0;
const unsigned int response_delay = 1000;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  delay(1000);

}

void loop() {
  if (reading_request_phase)
  {
    ec.send_read_cmd();
    ph.send_read_cmd();
    temp.send_read_cmd();

    next_poll_time = millis() + response_delay;
    reading_request_phase = false;
  }
  else
  {
    if (millis() >= next_poll_time)
    {
      ec.receive_read_cmd();
      ph.receive_read_cmd();
      temp.receive_read_cmd();
      display_reading();

      reading_request_phase = true;
    }
  }
}

void display_reading() {
  Serial.print(ec.get_last_received_reading()/1000);
  Serial.print(",");
  Serial.print(ph.get_last_received_reading());
  Serial.print(",");
  Serial.println(temp.get_last_received_reading());
}

```

Also remove the `delay()` after each printed line, it's just confusing everything and slowing down your reading.
> 5 votes

---
Tags: arduino-uno, sensors, i2c, serial-data
---


# Question
Title: What are these 18 extra ports on the adafruit-gfx 2.8"
I recently got the Adafruit gfx 2.8" display, which works fine.

It's quite obvious that it requires almost all of the pins on the UNO. *However, I don't understand what are the 18 avaliable "soldier ports" are at the bottom of the Adafruit shield.*

Can these ports be used with sensors, ie: push button, so you wouldn't need to plug anything else into the UNO board? What do these holes do? I'm unable to find out, as it doesn't seem to be a common shield, most Adafruit shields don't seem to have those ports.

If these ports do nothing, should I saw them off - save space?

# Answer
> 3 votes
Those are an alternative way of connecting to the screen. Basically they mirror the connections to the "shield" pins.

To save costs the manufacturer will have made a PCB that can be used in multiple different ways just by soldering different connectors. In this case either as an Arduino shield or as a board on the end of a ribbon cable. You have the version with the Arduino shield pins soldered in.

They are of no use to you unless you should want to put the screen on the end of a ribbon cable. Can you remove them? Possibly, possibly not. It depends on how the PCB traces are routed. Cutting the board may cut important PCB traces that connect the screen to the Arduino shield pins.

Only close inspection of the board and understanding the routing of the traces will be able to tell you yes or no. If in doubt, though, no you don't want to be randomly cutting off chunks of the circuit.

---
Tags: arduino-uno, lcd, adafruit
---