# Question
Title: How to send an email with Arduino and a WiFi shield?
I want to make my Arduino connect via WiFi and then send an email. The idea is very simple, but the problem is that I've never worked with those protocols and other things before. I just wanted something that's already premade, so I would just change the information.

Is there a library or a function that sends the email?

If someone could help me to understand, so I can make it myself, that would be the best.

# Answer
> 5 votes
What you're looking for is a **SMTP (Simple Mail Transport Protocol) library**. A Google search finds 2 for the Arduino:

* SMTPClient

This seems to be a minimal-capability SMTP-only library that piggybacks on top of a connection library.
* FullIP

This seems to be a full IP package for the Arduino that works with select network devices which includes SMTP capability.

# Answer
> 3 votes
You actually present 2 issues here, which can be handled separately:

* You are concerned about having a WiFi, not an Ethernet shield. This doesnt affect at all for sending emails or any other network stuff. When you have internet connection, it is almost transparent from the programming side. So I recommend first to try your wifi shield connection and configuration as a separate problem, with a more simple task, as a simple HTTP\_GET to a known web page. A function like this might help, assuming that you have an instance of WiFiClient (which is a Client), that has been connected (with connect) to the URL and port 80:

```
void http_get(Client& www, char website[], char webpage[], int timeout, Stream& stream) {
    if (www.connected()) {
        int n = www.print("GET ");
        www.print(webpage);
        www.print(" HTTP/1.1\r\n");
        www.print("Host: ");
        www.print(website);
        www.print("\r\n");
        www.print("\r\n");
    } else {
        stream.println(F("Connection failed get"));
        return;
    }

    /* Read data until either the connection is closed, or the idle timeout is reached. */
    unsigned long lastRead = millis();
    while (www.connected() && (millis() - lastRead < timeout)) {
        while (www.available()) {
            char c = www.read();
            stream.print(c);
            lastRead = millis();
        }
    }
}

```
* The second problem is that you want to send an email. One you have a connection, it doesnt matter if it is wifi or wired. The above recommended libraries (SMTPClient, FullIP) will directly connect to your provider (e.g. gmail) and will request your gmail password, something that is not secure over non secure connections (and those libraries do not seem to provide secure layer), so personally I am not comfortable with that option. I have been using the temboo service, that allows to send emails, and I have found it to be quite convenient and simple. Furthermore, they also have many other services. The service stores your gmail or whatever provider credentials, and you access the service via a Secret Key and App Password they provide. While this keys might not be fully secure to be sent via non secure layers, at least it only compromises your app in the cloud application, which you might simply manage, and not your full email account. (Disclaimer: I have no relation with temboo, and there might be other similar services for this task, e.g. Carriots, I simply say that I have used them with success for this task and feel it is relatively simple). Your code using temboo, could be something like:

```
TembooChoreo choreo(client); // your WiFiClient object

// Set Temboo account credentials
choreo.setAccountName(temboo_account);
choreo.setAppKeyName(temboo_app);
choreo.setAppKey(temboo_app_key);

// credential is the name of your gmail profile in temboo
choreo.setCredential(credential);
choreo.addInput("MessageBody", body);
choreo.addInput("Subject", subject);
choreo.addInput("ToAddress", address);

//Identify the Choreo to run
choreo.setChoreo("/Library/Google/Gmail/SendEmail");

choreo.run();
choreo.close();

```

# Answer
> 2 votes
There may be a problem with sending Email from Arduino, but not where you are expecting it. SMTP protocol is super simple, even Arduino can handle it. But you will need SMTP server somewhere that will talk to your Arduino. SSL connections (as on Gmail) are out of consideration (code to handle the encryption would be too much for Arduino) so you'd have to find mail provider that provides plain SMTP - and there aren't many. If you will set up one yourself, say on your home PC with static IP address, it would be an invitation for spammers and a guaranteed way to get your IP blacklisted by Spamhaus. My advice would be to have Python, PHP or Perl script hosted somewhere that will handle HTTP POST requests from your Arduino and do Email sending. It is safer and simpler.

# Answer
> 1 votes
Sending gmail via SMTP from an Arduino is completely feasible. I am doing it from an Arduino MKR WIFI 1010 using the WIFINina library. I'm pretty sure that my solution will work on any of the SAMD based Arduinos.

There is a bit o "setting up" to do, but it's not hard.

Check out my solution on my gitlab repo.

Be sure to do the config BEFORE trying to execute the code... Good luck! GF

# Answer
> 0 votes
The simplest way to send email from Arduino is to make HTTP request to IFTTT. See Arduino - IFTTT

---
Tags: wifi
---


# Question
Title: RFID stops working when I place the servo
I've successfully implemented Door Unlock system described in this tutorial. At first I used Arduino Uno and RFID RC522 Reader and MG90S Micro servo.

When I used Arduino Uno with Arduino Pro Micro for arduino ATmega32U4 5V/16MHz, the RFID reader stops working after plugging the servo. Since Arduino Pro Micro have only 5V output, I used resistors to downgrade 5V to 3V in order to poser the RFID reader. I used same output 'vcc' to select 5V for the servo and 3V converted to the reader.

The problem is that each component works perfectly independent of each other, however, when I place them together they stop working.

# Answer
> 1 votes
Use a 3.3VDC regulator for your RFID board a small boxed DC-DC buck converter will be easiest, if linear use an LDO type. Ideally also use a level shifter on your data lines. This could be a resistor voltage divider or zener diode clamp at the most basic, FETs or a dedicated IC is a bit more involved but gets better results.

# Answer
> 1 votes
The code you are using is not complete. You should check the second code given at Interfacing of RFID RC522 with Arduino UNO. In this second code they have a function:

> void dump\_byte\_array(byte \*buffer, byte bufferSize)

In this funtin place your servo Motor Routines. Like when First card is detected then move serbo in one direction and when second card is detected then move your servo in opposite direction. I have tried it and it works perfectly fine.

# Answer
> 1 votes
The current may be not enough. Try using extra power supply for Servo Motor

---
Tags: servo, rfid, arduino-pro-micro
---


# Question
Title: Arduino Due: JTAG and SWD do not work after pressing erase button
I have an Arduino Due board. I can successfully upload code to it using Arduino upload via USB. However I am also exploring another approach, which is to upload code via Atmel studio using an Atmel ICE and JTAG connection. Usually this works fine (the code uploads, and a simple "blink" sketch makes the onboard LED flash).

However when I press the erase button, and then try to upload the same sketch via Atmel Studio and JTAG, something strange happens. The code uploads fine:

```
Erasing device... OK
Programming Flash...OK
Verifying Flash...OK

```

But then the program on the Due does not actually execute. The LED does not start to 'blink'. If I then again upload via USB (programming port) and the Arduino IDE, the blink program does work. And when I then upload via Atmel Studio and JTAG again without pressing the erase button, everything happens as expected too (LED blinks etc). Does anyone have any idea what might be going on? The reason I ask is because I would like to design a board using only a JTAG connection. Do you think the above problem could cause issues when using a 'blank' factory SAM MCU as well?

EDIT: the same problem applies to SWD.

Blink sketch that i am uploading:

```
#define led LED_BUILTIN

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(600);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(600);               // wait for a second
}

```

# Answer
After uploading via Microchip Studio, go to the GPNVM bits section of "device programming" window. Make sure boot mode is set to "boot from flash". Also check that GPNVMBITS register is set to 0x00000002. Then press "program". The sketch you uploaded to the MCU should now work.

So it seems what happens is that pressing the erase button resets the GPNVM bits so that the MCU boots from ROM, but then Atmel ICE + JTAG/SWD does not set the boot mode back to flash after (succesfully) programming the MCU.
> 1 votes

---
Tags: arduino-due, uploading, programmer
---


# Question
Title: Arduino Leonardo - Setting up bluetooth - AT command from terminal does not return anything
I am trying to setup bluetooth with a board that contains **Arduino Leonardo** chip.

My full setup is:

The main board: https://www.dfrobot.com/product-1148.html

The base shield: https://coolcomponents.co.uk/products/grove-base-shield-for-arduino-v2

The bluetooth module: https://wiki.seeedstudio.com/Grove-Serial\_Bluetooth\_v3.0/

The bluetooth module is connected to D8 port of the base shield. The reason is "not all pins on the Leonardo and Micro support change interrupts, so only the following can be used for RX: 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI)." as explained here: https://www.arduino.cc/en/Reference/SoftwareSerial

Here is the full code.

```
#include <SoftwareSerial.h>   //Software Serial Port

/*Connect your Bluetooth Module to D8 otherwise it will not work due to Arduino Leonardo */

#define RxD         8
#define TxD         9

SoftwareSerial blue(RxD,TxD);

void setup()
{
    Serial.begin(9600);
    blue.begin(9600); //anything other than 9600 will not work

    // wait for serial port to connect. Needed for native USB
    while(!Serial){
    ;
    }

    pinMode(RxD, INPUT);
    pinMode(TxD, OUTPUT);

    Serial.print("Started\n");
    setupBlueToothConnection();

}

void loop() {
char recvChar;
    while(1)
    {
        if(blue.available())
        {//check if there's any data sent from the remote bluetooth shield
            recvChar = blue.read();
            Serial.print(recvChar);

        }
        if(Serial.available())
        {//check if there's any data sent from t he local serial terminal, you can add the other applications here
            recvChar  = Serial.read();
            blue.print(recvChar);
            delay(400);
        }
    }
}

void setupBlueToothConnection()
{
  //blue.begin(9600);

  blue.print("AT");
  delay(400);

  blue.print("AT+ROLES");  // set the role as slave
  delay(400);

  blue.print("AT+NAMESlave");   // set the bluetooth name as "Slave" ,the length of bluetooth name must less than 12 characters.
  delay(400);

  blue.print("AT+AUTH1");
  delay(400);
  blue.flush();
}

```

The output from the Serial Monitor (set as BOTH NL & CR, 9600) as follows:

```
Started
OKOK+Set:SOK+Set:SlaveOK+Set:1

```

The problem is when I send AT commands from terminal I get nothing in return. However if I send AT command from the IDE, I am getting feedback from the bluetooth.

# Answer
The issue is fixed.

**Note:** This is the version includes **Serial1** rather than **SoftwareSerial**. The rest is the same.

**Serial.read()**

> Returns the first byte of incoming serial data available.

So, when I send AT command from terminal, it does send "A" and then "T" rather than "AT" as a string which Bluetooth expects as stated in the product's documentation:

> AT Command format: Uppercase AT command format. string format, without any other symbol. (e.g. \r or \n).

Hence, I have added the following function:

```
String SerialString() {   // Function to generate string from chars sent via Serial Monitor

  String inputString = "";  // to hold the string

  while (Serial.available()) {

    char inputChar = (char)Serial.read(); // get the new byte:
    inputString += inputChar;             // add it to the inputString:
    }

    return inputString;     // returns completed string
}

```

Then inside `void loop():`

```
String WholeCommand = "";
if(Serial.available() > 0){
    WholeCommand = SerialString();
    Serial1.print(WholeCommand);
  }

```

Now, when I send AT from Serial Monitor, I can get OK from Bluetooth.
> 2 votes

---
Tags: bluetooth, arduino-leonardo
---


# Question
Title: Can't get "Burn Bootloader" working - Arduino Nano
This is a follow up from a previous question. I have one Nano working perfectly (I think) (Nano A) and another one (Nano B) which seems to be working but has no bootloader. So I am trying to use Nano-A as an ISP programmer to burn the bootloader into Nano-B. I am pretty confident with my hardware and Arduino IDE setup. See previous question for the details; Problems uploading with a new Nano

I have pasted below two screen sessions. The first shows the Arduino IDE Log when I (unsuccesfully) try to run "Burn Bootloader" - IT *almost* works! (but not quite). - So I beleive that there is not too much wrong with my setup.

The second session is me using running avrdude in "terminal" mode from a Windows command prompt. I have used individual "send" commands to send the ISP instructions required to programme a single word into bootloader flash memory and this all seems to work OK. So I don't understand why avrdude is not working when invoked by the IDE.

**Arduino IDE Log (lengthy)**

```
C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM8 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xFF:m

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM8
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.11s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: erasing chip
avrdude: reading input file "0x3F"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3F:
avrdude: load data lock data from input file 0x3F:
avrdude: input file 0x3F contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of lock verified
avrdude: reading input file "0xFD"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xFD:
avrdude: load data efuse data from input file 0xFD:
avrdude: input file 0xFD contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0xDA"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xDA:
avrdude: load data hfuse data from input file 0xDA:
avrdude: input file 0xDA contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xFF"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xFF:
avrdude: load data lfuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude done.  Thank you.

C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM8 -b19200 -Uflash:w:C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:i -Ulock:w:0x0F:m

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM8
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.11s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex"
avrdude: writing flash (32768 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_cmd(): programmer is out of sync
avrdude: stk500_cmd(): programmer is out of sync
avrdude: 32768 bytes of flash written
avrdude: verifying flash memory against C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:
avrdude: load data flash data from input file C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:
avrdude: input file C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex contains 32768 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.00s

avrdude: loadaddr(): (b) protocol error, expect=0x14, resp=0xc0

avrdude: stk500_paged_load(): (a) protocol error, expect=0x14, resp=0x10
avrdude: stk500_cmd(): protocol error
avr_read(): error reading address 0x7e00
    read operation not supported for memory "flash"
avrdude: failed to read all of flash memory, rc=-2
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0xd1

avrdude done.  Thank you.

Error while burning bootloader.

```

**avrdude session (short)**

Note that when writing to the bootloader flash, using the "send" instruction, you have to supply the address as a "word" - i.e. 16bit address - hence 0x3C00. When usning the "read" instruction, the address is a "byte" (8 bit) address, hence 0x7800 - this is the same address.

Update: I have now managed to upload my original sketch to the application area of flash on this Nano using the "Sketch-\>upload using programmer" menu option of the Arduino IDE. So I do now have a useable Nano but I have still not solved my original problem i.e. this Nano still does not have a bootloader. I would like to fix this problem becaue I am sure that I will want to update/modify my app int the future. So there is now an ancilliary question - i.e. is it possible to burn a bootloader without erasing a pre-existing application? - Answer, I think is no because maybe you have to do a chip erase before writing to the bootloader area?

# Answer
> 1 votes
Yay! - I now have a fully working Nano with new bootloader and application loaded using this.

I have done so much that I'm not sure what the original problem was but the final change was modifying the "programmers.txt" file such that "Arduino as ISP" entry was changed as follows;

```
Original line;
arduinoasisp.protocol=stk500v1

Changed to;
arduinoasisp.protocol=arduino

```

I did this because I noticed that the menu option "Upload using programmer" (which worked) invoked avrdude with the parameter "-c arduino" whereas the "burn bootloader" option used "-c stk500v1" (which was not working).

I can't pretened that I fully understand but I'm happy that this now works and that I have now learnt enough to know where to start looking if I get similar problems in the future.

I should also add that I would never have got here without the help of @timemage - who has helped a lot - many many thanks

---
Tags: arduino-nano, bootloader, avrdude
---


title: Which sensor bus best to use?

text:
# Question
Title: Which sensor bus best to use?
I am working on a project which requires a dozen VL53l0X I2C-TOF sensors to be polled by one master MCU over a few meters of cable.

Thus, I decided to accompany each TOF by an Atmega8 acting as a gateway between the TOF and a Modbus (using a MAX485), which is managed by an ESP32 (the master). Since I require fairly low latency (~10 reads / sensor / second) I am a bit disappointed by the Modbus RTU performance (mostly caused by the forced 1.75ms delay between frames).

My question: Is there any quicker, more suitable, Atmega-bearable bus protocol for long distances? Ethernet is sadly not an option due to the limited slaves computing power and cost...

# Answer
CAN for the Phy (physical) layer would be good for several thousand feet. You can use whatever baud and protocol on the CAN layer you like within reason. I am assuming (maybe in error) that they all communicate on the same bus. This CAN Phy was designed for this. It would be possible for you to write your own protocol and simply address each by a unique number or whatever. There is also the option of using a CAN controller but I think that would be a lot of time not needed to design your solution. By placing a Atmega8 at each sensor opens up a lot of possibilities for you.
> 1 votes

---
Tags: sensors, i2c, modbus, network
---


title: SIM7000E 0 voltage at SIM_VDD

text:
# Question
Title: SIM7000E 0 voltage at SIM_VDD
I have problem with my SIM7000E. My PCB scheme and design is aveliable here https://easyeda.com/jaka87/new-vetercek While sending AT commands I get error as if sim card is not connected.

I also put oscilloscope on SIM\_VDD and did some measurement. To my surprise i always measure 0V even or reset and when changing from `AT+CFUN=0 to AT+CFUN=1`. It should at least send some bursts right ? Any idea why this is happening?

Scheme:

# Answer
After weeks i finally found the source of the issue. It turns out i mixed two labels on the PCB and therefore had wrong capacitors on VCC and data...
> 0 votes

---
Tags: hardware
---


# Question
Title: What is the difference between a motor driver and a motor shield?
what is the difference between a motor driver(like L293D) and a motor shield?

what are the advantage?disadvantages of both?

And which one do you suggest ?

# Answer
> 5 votes
A motor driver is a chip that drives motors. A motor shield is a circuit board with connections on it that contains a motor driver chip that drives motors.

A shield is convenient since you can just plug it in to your Arduino and wire the motors direct to it, but it lacks the flexibility of a raw driver chip which you can wire up precisely as your project demands.

# Answer
> 2 votes
The differrence is usablilty and, in some cases, the protection of your chip; if there is a surge of more than 5V to your driver it will fry, which is why some drivers have onboard voltage regulators and a heatsink for overheating problems. Advantage of motor driver is that you can use it as per your requirements, whereas a shield is fixed and you cannot change any aspects.

# Answer
> 1 votes
*A motor driver is a chip that drives motors. A motor shield is a circuit board with connections on it that contains a motor driver chip that drives motors.*

**A shield is convenient since you can just plug it into your Arduino and wire the motors direct to it, but it lacks the flexibility of a raw driver chip which you can wire up precisely as your project demands**

---
Tags: arduino-uno, arduino-motor-shield
---


title: Problems uploading with a new Nano

text:
# Question
Title: Problems uploading with a new Nano
My first post - I am a relative newbie.

I want to make a smartcontroller for my boat - I have built the electronics and written and tested a sketch for the Nano, all working totally fine. I then decided that I would like to keep my existing Nano (Nano-A) as a development system and buy another one (Nano-B) to actually deploy. Both of these are cheap chinese clones (from different suppliers).

However I cannot upload anything to Nano-B. It seems to be basically working (LEDs flash) but not wishing to accept any sketch uploads. The COM port seems to be working OK and I have tried all the various options available in the Arduino IDE (boards, programmers etc.) without success.

So I came to the conclusion that possibly the bootloader on Nano-B needs to be re-flashed.

So I setup Nano-A as a programmer, loaded up "ArduinoISP", connected up the ISP pins and hit "burn bootloader".

It seems as if this is "nearly working". I have turned on the -v (verbose) option for avrdude and pasted the log below. It looks to me as if the IDE is invoking avrdude twice; (1) To set the Fuses etc, and (2) to upload the actual bootloader. I seems that (1) is working OK but (2) is failing.

I've been tearing my hair out for about 3 weeks with this and would be really keen to get some ideas. Thanks in advance.

Arduino "burn bootloader" IDE Log - follows;

```
Arduino: 1.8.13 (Windows Store 1.8.42.0) (Windows 10), Board: "Arduino Nano, ATmega328P"

C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM8 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xFF:m

avrdude: Version 6.3-20190619

         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM8

         Using Programmer              : stk500v1

         Overriding Baud Rate          : 19200

         AVR Part                      : ATmega328P

         Chip Erase delay              : 9000 us

         PAGEL                         : PD7

         BS2                           : PC2

         RESET disposition             : dedicated

         RETRY pulse                   : SCK

         serial program mode           : yes

         parallel program mode         : yes

         Timeout                       : 200

         StabDelay                     : 100

         CmdexeDelay                   : 25

         SyncLoops                     : 32

         ByteDelay                     : 0

         PollIndex                     : 3

         PollValue                     : 0x53

         Memory Detail                 :

                                  Block Poll               Page                       Polled

           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack

           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------

           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff

           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff

           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500

         Description     : Atmel STK500 Version 1.x firmware

         Hardware Version: 2

         Firmware Version: 1.18

         Topcard         : Unknown

         Vtarget         : 0.0 V

         Varef           : 0.0 V

         Oscillator      : Off

         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.11s

avrdude: Device signature = 0x1e950f (probably m328p)

avrdude: erasing chip

avrdude: reading input file "0x3F"

avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of lock written

avrdude: verifying lock memory against 0x3F:

avrdude: load data lock data from input file 0x3F:

avrdude: input file 0x3F contains 1 bytes

avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...

avrdude: 1 bytes of lock verified

avrdude: reading input file "0xFD"

avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of efuse written

avrdude: verifying efuse memory against 0xFD:

avrdude: load data efuse data from input file 0xFD:

avrdude: input file 0xFD contains 1 bytes

avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...

avrdude: 1 bytes of efuse verified

avrdude: reading input file "0xDA"

avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of hfuse written

avrdude: verifying hfuse memory against 0xDA:

avrdude: load data hfuse data from input file 0xDA:

avrdude: input file 0xDA contains 1 bytes

avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...

avrdude: 1 bytes of hfuse verified

avrdude: reading input file "0xFF"

avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of lfuse written

avrdude: verifying lfuse memory against 0xFF:

avrdude: load data lfuse data from input file 0xFF:

avrdude: input file 0xFF contains 1 bytes

avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...

avrdude: 1 bytes of lfuse verified

avrdude done.  Thank you.

C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM8 -b19200 -Uflash:w:C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:i -Ulock:w:0x0F:m

avrdude: Version 6.3-20190619

         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/

         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

         Using Port                    : COM8

         Using Programmer              : stk500v1

         Overriding Baud Rate          : 19200

         AVR Part                      : ATmega328P

         Chip Erase delay              : 9000 us

         PAGEL                         : PD7

         BS2                           : PC2

         RESET disposition             : dedicated

         RETRY pulse                   : SCK

         serial program mode           : yes

         parallel program mode         : yes

         Timeout                       : 200

         StabDelay                     : 100

         CmdexeDelay                   : 25

         SyncLoops                     : 32

         ByteDelay                     : 0

         PollIndex                     : 3

         PollValue                     : 0x53

         Memory Detail                 :

                                  Block Poll               Page                       Polled

           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack

           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------

           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff

           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff

           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00

           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : STK500

         Description     : Atmel STK500 Version 1.x firmware

         Hardware Version: 2

         Firmware Version: 1.18

         Topcard         : Unknown

         Vtarget         : 0.0 V

         Varef           : 0.0 V

         Oscillator      : Off

         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.11s

avrdude: Device signature = 0x1e950f (probably m328p)

avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed

         To disable this feature, specify the -D option.

avrdude: erasing chip

avrdude: reading input file "C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex"

avrdude: writing flash (32768 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: stk500_recv(): programmer is not responding

avrdude: stk500_recv(): programmer is not responding

avrdude: stk500_cmd(): programmer is out of sync

avrdude: stk500_cmd(): programmer is out of sync

avrdude: stk500_cmd(): programmer is out of sync

avrdude: 32768 bytes of flash written

avrdude: verifying flash memory against C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:

avrdude: load data flash data from input file C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:

avrdude: input file C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex contains 32768 bytes

avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.00s

avrdude: loadaddr(): (b) protocol error, expect=0x14, resp=0x3f

avrdude: stk500_paged_load(): (a) protocol error, expect=0x14, resp=0x10

avrdude: stk500_cmd(): protocol error

avr_read(): error reading address 0x7e01

    read operation not supported for memory "flash"

avrdude: failed to read all of flash memory, rc=-2

avrdude: stk500_disable(): protocol error, expect=0x14, resp=0xff

avrdude done.  Thank you.

Error while burning bootloader.

```

Edit ... Connections between the Arduinos. Nano A is the programmer. Nano B is the target

* Nano A Nano B
* ISP 1 -- ISP 1 (MISO)
* ISP 2 -- ISP 2 (VCC - 5v)
* ISP 3 -- ISP 3 (SCK)
* ISP 4 -- ISP 4 (MOSI)
* ISP 6 -- ISP 6 (GND)
* D10 -- ISP 5 (RESET)

I have also now added a 60ohm resistor between RESET and +5V on Nano A
I have also tried connecting a capacitor between RESET and GND. (2uF and 100uF - I didn't have a 10uF) - but it made no difference

Further investigations.

I have tried running avrdude in "terminal" mode and can confirm that I can do all of the usual read/write operations except writing to anywhere in flash memory. This seems to be the only operation that does not work. I will now try breaking down the flash write operation into the individual SPI programming instructions to see if I can work out where it is failing. I suspect that my MCU is a "brick" but I have learned loads!

Another edit; I have now been using the avrdude terminal mode "send" command to step throuh the individual SPI operations one at a time to write flash memory and hey! it works! (see below)

So, if this works, why does ArduinoISP fail to load the bootloader? I will set this up as another/new question

# Answer
> 0 votes
I have now fixed this problem, but still do not fully understand what the original problem was.

Please see my other post on this qusetion to see what I did Link to other post

# Answer
> 0 votes
Perhaps this isn't the answer to the bootloader issue but I went through the same thing recently, I realized a little late about what was exactly the problem, so I checked the uC on the Nano Board and it has an ATMega168 instead of the normal ATMega328p.

So if you are using ArduinoIDE you need to check the ATMega168 option while you are selecting your uC chip (as in the picture above)... Sometimes (as it happened to me, just going for the basics solve all the problems)

Hope this could help you mate

# Answer
> 0 votes
There is more then one bootloader in the Nano's, a new one and the old one. I had the same problem so I simply went to tools in the IDE and switched from the new to the old, it solved my problems.

---
Tags: arduino-nano, bootloader
---


# Question
Title: How to add two assembly arrays in arduino
Hey guys what I'm trying to do is to sum two arrays and return a new array; for example if given

```
  uint8_t a[] = {2, 4, 6};
  uint8_t b[] = {1, 2, 3};

```

I should get `{ 3, 6, 9}` What I'm trying to do is have a .ino file call on an assembly file that will do this in assembly and not in C and this is what I currently have in assembly:

```
// mimics void sumArrays(uint8_t *a, uint8_t *b, uint8_t *c, byte length){} method
    .global sumArrays
    sumArrays:
      //r18 is the byte length
      //r24 and r25 first  array 31,30
      //r23 and r22 second array 29,28
      //r21 and r20 third  array 27,26

      mov r30, r24
      mov r31, r25
      mov r28, r22
      mov r29, r23
      mov r26, r20
      mov r27, r21
      ldi r17, 0 //counter variable
      ldi r19, 1
      call printRegs
      //jmp sumLoop

      ret

    sumLoop:
      cp r17, r18
      brge endSumLoop
      ldi r16, 0
      add r16, Z+
      add r16, Y+
      st X+, r16
      add r17, r23
      jmp sumLoop:

    endSumLoop:
      ret

```

However, I get `sketch/assignment13.S:65: Error: constant value required` which is most likely from the

```
add r16, Z+
add r16, Y+

```

Lines but otherwise, how would I add it to a temporary variable while progressing the pointer?

# Answer
> ```
> add r16, Z+
>
> ```

You probably meant something like

```
add r16, memory[Z+]

```

However, the AVR is a RISC processor. It has instructions to address the memory, and instructions to do arithmetics, but it has no “complex” instructions that both address the memory *and* do arithmetics with the addressed data. So you have to use separate instructions to:

1. Load (`ld`) the data from RAM
2. do the arithmetics
3. store (`st`) the result in RAM

Now, looking at your assemble code, I have a few comments:

1. If you are mixing assembly and C/C++, you should pay attention to the ABI conventions. Specifically, some registers, like r28 and r29, “belong” to the caller. If your function needs to use them, it should save their contents (typically by `push`ing them to the stack) before clobbering them, and restore them (`pop`) before returning.
2. For adding two 8-bit numbers (a + b), a single addition is enough. There is no point in starting the addition with zero (i.e. computing 0 + a + b).
3. For managing the counter, it can be more convenient to decrement the initial count you where given (like in C: `if (--length) return;`) rather than using an extra variable that is incremented.
4. There is no need to split such a simple function into smaller functions.
> 2 votes

---
Tags: arduino-uno, avr, array, code-review, assembly
---


# Question
Title: Code Optimization: Interrupt when a value reaches 0
I have a working program and I wish to improve its efficiency as much as possible.

It will blink slow, then faster and faster until it restarts.

It works, but my main concern is, currently, I am using a `if` statement in the `void loop()`, and I am certain that, using an interrupt when a specific variable has reached 0, would improve efficiency.

```
byte amp = 0;

void setup() {
  pinMode(13, OUTPUT);
  reset();
}

void loop() {            // The following
  digitalWrite(13,HIGH); // code is for the sake of example
  delay(amp*100);        // Simplified to focus on the loop
  digitalWrite(13, LOW);
  delay(amp*100);
  amp--;
  if (!amp) {reset();}     // <-This right here
}

void reset() {amp = 10;}

```

My understanding is, the `if` statement is called every time the loop restarts.

* Is it possible to set up an interrupt for when a certain variable reaches 0?
* Which option would require less computing power, a continually called if loop, or an interrupt?

# Answer
You did not specify the kind of Arduino you are using but, based on another recent question of yours, I will assume it is an AVR-based Arduino.

You cannot have an interrupt automatically triggered by a variable reaching zero. What you can do, instead, is trigger an interrupt by software, by toggling a pin that is configured both as an output and as an interrupt source:

```
const uint8_t int_pin = 2;  // pin used for interrupt

void setup() {
    digitalWrite(int_pin, LOW);
    pinMode(int_pin, OUTPUT);
    attachInterrupt(digitalPinToInterrupt(int_pin, reset, RISING));
}

static inline void trigger_interrupt() {
    digitalWrite(int_pin, HIGH);
    digitalWrite(int_pin, LOW);
}

// Within loop():
if (!amp) trigger_interrupt();

```

However, if you do that, you will discover that interrupts are slow; **awfully slow** compared with a simple `if` test:

1. `digitalWrite()` itself is awfully slow. This can be overcome by using direct port access, but that is still two cycles for toggling the pin in each direction.
2. You will lose an extra cycle in the pin synchronizer.
3. Once the IRQ is raised, the CPU needs four cycles to prepare itself for servicing it.
4. The interrupt vector is a `jmp` instruction, which takes 3 cycles.
5. The ISR then has to save every single register it is going to use, including the status register. That takes two cycles per register. And there are quite a lot of registers to save...
6. This ISR, which is provided by the Arduino core, will then look for the interrupt handler you provided with `attachInterrupt()`. This also involves checking that the pointer to the handler is not zero (the kind of test you seem to be worried about). It then has to `call` (4 cycles) your handler, which will have to `ret`urn (4 cycles) to the ISR. You could avoid this indirection by defining the ISR yourself instead of relying on `attachInterrupt()`.
7. Once the job is done, all the saved registers have to be restored (2 cycles times many register), and the `reti` instruction (4 cycles) is issued in order to restore control to the interrupted program.
8. Last but not least, since `amp` will be modified in interrupt context, you will have to qualify it as `volatile`. This keyword prevents the compiler from perform optimizations that are unsafe in this situation, and you will loose *a lot* of time to these missed optimization opportunities.

In contrast, this line:

```
if (--amp == 0) amp = 10;

```

would be translated by the compiler into something like this:

```
   dec  amp     ; --amp, as amp is likely already in a register
   brne 1f      ; if (amp != 0) skip the following
   ldi  amp, 10 ; amp = 10
1:

```

The whole sequence takes 3 cycles, irrespective of whether the `if` condition was true or false. That is at least one order of magnitude faster than the interrupt-based solution.
> 1 votes

# Answer
Simple `if` statements are very fast and won't affect performance much even when used in every looping of the loop.

Using an interrupt to implement something simple like `if (!amp) amp = 10;` will probably make things slower:

* something will have to keep track of the counter to generate an interrupt, and this "something" takes MCU time, unless it is a peripheral;
* interrupts have overhead;
* on single-thread MCUs, interrupts stop regular code execution until they are done;
* `amp = 10;` will still have to be executed, in the regular code, or, if you must, in the interrupt.

You would gain more by getting rid of the function call to `reset()`, but the compiler probably does that for you.

Also, I wouldn't know how to replace a regular `if` with an interrupt, unless the counter is kept by a (timer) peripheral.
> 1 votes

---
Tags: interrupt, code-optimization
---


# Question
Title: Changing address of MPU 9250 connected to ESP32
Can I change the I2C address of a device (MPU9250) connected to ESP 32 using int pin. I understand that in arduino board if we connect the int pin to A0 the default I2C address of MPU 9250 changes from 0x68 to 0x69. Is something similar possible with ESP 32? Which Pin I should connect to?

# Answer
You have only two choices with this device on an I2C bus. As stated in the datasheet:

So it's either:

1. 0b1101000
2. 0b1101001

The AD0 pin selects which of these two addresses are used.

The complete datasheet can be viewed at the following link as well as other places:

Datasheet
> 1 votes

---
Tags: esp32, imu
---


# Question
Title: Programming Questions / Capacitive Soil Moisture Sensor
Good day All,

This is my first time posting to this forum and kind off my last resort as I would've liked to figure it out myself. I am trying to create a soil moisture probe which can be used on farms to determine soil moisture at different depths. The project consists of a Arduino Nano, a DIY capacitive moisture reading setup (schematic attached- My setup is the same except for the LED moisture indicator)) and an LCD screen to display the required value.

My initial setup was a Arduino Nano (328P Old Bootloader) with a resistive soil moisture sensor. However, these sensors (as they are resistive) do not give reliable readings when measuring at different spots in a field. I believe it is largely influenced by pH, salt content etc.

My next approach was to build a DIY capacitive soil moisture sensor. After searching the web I came across a setup on hackster.io ( https://www.hackster.io/Pedro52/arduino-capacitive-soil-moisture-sensor-diy-with-esp32-d7ad72 ) where a signal is sent via a ESP 32 microcontroller to a probe in the soil and a signal is returned. I implemented the same setup with the same components however I only used optimization of the timers on the Nano to generate the PWM wave (Once again this code was also obtained from another website and I am still a bit confused on how the code works).

I seem to get a reading from the sensor but the zero value seems to very volatile. Even if the wire is only picked up, the output reading changes. Is there a way to get around this and can someone please help me to get my system working optimally.

It would be highly appreciated.

```
 /

    /The setup uses a Chinese Arduino Nano, a 10M ohm, a 10k ohm, a 1N4007 diode and a 1 microfarrad capacitor as shown in the schematic.
    //The LED moisture indicator in the schematic can be ignored

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

    //LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
    //LcdBarGraphRobojax lbg(&lcd, 16, 0, 0);

    float Moistlevel = 0;
    float Moistpin = A1;
    float Moisture = 0;
    float RESET;
    float factor;
    const byte CLOCKOUT = 9;

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

  TCCR1A = bit (COM1A0);                  //Code which I obtained to initiate the onboard timer 1 to give a signal through D9
  TCCR1B = bit (WGM12) | bit (CS10);
  OCR1A =  0;                             // Apparently this should be changed for prescaling. Is it necessary?

  RESET = analogRead(Moistpin);           // Take a initial reading to zero the setup

  for (int j = 1; j < 5 ; j++)            // Take another 5 readings of which the average will be determined
  {
    RESET = RESET + analogRead(Moistpin);
    delay(200);
  };

  RESET = RESET / 6;

  Serial.print(RESET);
  Serial.println();

  Serial.print("Moistlevel");
  Serial.print("\t");
  Serial.print("\t");
  Serial.print("Moisture");
  Serial.println();
}

void loop() {

  Moistlevel = analogRead(Moistpin);                  //Take an average reading every second

  for (int i = 1; i < 5 ; i++)
  {
    Moistlevel = Moistlevel + analogRead(Moistpin);
    delay(200);
  };

  Moistlevel = Moistlevel / 6;
  Moisture = (RESET - Moistlevel) / (RESET / 100);    //Conversion to go from a voltage reading to a percentage reading

  if (Moisture < 0)                                   //Moves the initial if a negative moisture is obtained.
  {
    RESET = Moistlevel;
  };

  Moisture = (RESET - Moistlevel) / (RESET / 100);    //Obtains the new moisture value and prints it.

  Serial.println(Moistlevel);
  Serial.print("\t");
  Serial.print("\t");
  Serial.print("\t");
  Serial.print(Moisture);
  Serial.println();
  delay (500);
}

```

# Answer
Thanks to all for the advice,

I have chosen to divert the whole system and rather make use of a 555 timer to sent a frequency to the measuring pins. It has been tested and seems to resolve the issue completely.
> 1 votes

# Answer
Calling this a `capacitive` sensor may be inaccurate. And that could be the least of its problems. The "fritzing" schematic is unclear, and seems to be at odds with the explanation in Step 4 of the description. Fortunately, a legible schematic was derived here.

The author of the hackster.io article cites Andreas Speiss' well-known YouTube video on "Why Most Moisture Sensors Suck"... and then proceeds to design a moisture sensor that... sucks! This design seems to "miss the point": ***dc current causes an electrolytic reaction when the conductor is in direct contact with an electrolyte (like water and damp soil).***

Wrt the OP's comment that touching the wire changes the output reading: It's almost certain that there is more capacitance in the lead wire than there is in the "fondue forks". According to the article, audio cable was the author's choice for transfer of a 600 kHz signal from his breadboard to the sensor. The *long-ish* lead wires to the sensor strike me as an odd choice.

I've been more than a little critical of this hackster.io project. But of course I may have overlooked something important - I make mistakes each and every day. If someone cares to point out any mistakes I've made here, I'll be glad to revise or delete this post. Until then, ***my proposed answer is to find a better DIY project.***

Nevertheless - you **are** on the right track by deciding to build a ***capacitive*** moisture sensor. Unless the "fondue forks" are insulated to render them non-conductive when immersed in the soil/water electrolyte, this is not a capacitive sensor - it is resistive. And its flaws may go even deeper. Another DIY guide may yield better results.

For anyone interested, an LTspice simulation of the sensor circuitry may provide insights into its operation. In one case, the sensor is modeled as a purely capacitive device (i.e. the "Fondue Forks" are insulated to prevent dc current from flowing through the soil), and in the second case as an R-C circuit (i.e. the "Fondue Forks" are un-insulated, and dc current flows through the soil). The values for Rw2 and C2/C1 were based on measurements I made with a similar sensor:

I made the following observations using this model of the sensor:

1. the time constant for the RC filter on the sensor output may be substantially longer than necessary.
2. Note the dc current flow through Rw2 averages ~ 0.18mA. Knowledge of this value will allow use of Faraday's Law of Electrolysis to estimate how much of the chrome plating will be dissolved in your soil over time.
3. The value of Rw2 largely determines the value of the output voltage; the value of the capacitance plays a much smaller role. Thus, this sensor is mostly *resistive* rather than *capacitive*.

The LTspice `.asc` file follows; all feedback welcomed:

```
Version 4
SHEET 1 908 720
WIRE 336 32 288 32
WIRE 352 32 336 32
WIRE 512 32 432 32
WIRE 288 80 288 32
WIRE 336 80 336 32
WIRE 416 80 336 80
WIRE 512 80 512 32
WIRE 512 80 480 80
WIRE 512 96 512 80
WIRE 160 208 128 208
WIRE 288 208 288 144
WIRE 288 208 240 208
WIRE 480 208 288 208
WIRE 288 288 288 272
WIRE 288 288 128 288
WIRE 480 288 288 288
WIRE 288 304 288 288
WIRE 320 368 272 368
WIRE 336 368 320 368
WIRE 512 368 416 368
WIRE 272 400 272 368
WIRE 320 416 320 368
WIRE 416 416 320 416
WIRE 512 416 512 368
WIRE 512 416 480 416
WIRE 512 432 512 416
WIRE 160 528 128 528
WIRE 272 528 272 464
WIRE 272 528 240 528
WIRE 384 528 272 528
WIRE 464 528 384 528
WIRE 272 608 272 592
WIRE 272 608 128 608
WIRE 384 608 272 608
WIRE 464 608 384 608
WIRE 272 624 272 608
FLAG 288 304 0
FLAG 272 624 0
FLAG 480 208 Vsensor1
FLAG 464 528 Vsensor2
FLAG 512 96 0
FLAG 512 432 0
FLAG 288 32 Vout-insul
FLAG 272 368 Vout-unins
SYMBOL voltage 128 192 M0
WINDOW 3 -172 139 Left 0
SYMATTR Value PULSE(0 3.3 0 20n 20n 833.5n 1667.0n)
SYMATTR InstName V1
SYMBOL voltage 128 512 M0
WINDOW 3 -140 138 Left 0
SYMATTR Value PULSE(0 3.3 0 20n 20n 833.5n 1667.0n)
SYMATTR InstName V2
SYMBOL cap 256 528 R0
SYMATTR InstName C2
SYMATTR Value 80.0p
SYMBOL res 368 512 R0
SYMATTR InstName Rw2
SYMATTR Value 5000
SYMBOL res 256 192 R90
WINDOW 0 0 56 VBottom 2
WINDOW 3 32 56 VTop 2
SYMATTR InstName Rs1
SYMATTR Value 10k
SYMBOL res 256 512 R90
WINDOW 0 0 56 VBottom 2
WINDOW 3 32 56 VTop 2
SYMATTR InstName Rs2
SYMATTR Value 10k
SYMBOL cap 272 208 R0
SYMATTR InstName C1
SYMATTR Value 80.0p
SYMBOL diode 304 144 R180
WINDOW 0 24 64 Left 2
WINDOW 3 24 0 Left 2
SYMATTR InstName D1
SYMATTR Value 1N4007
SYMBOL diode 288 464 R180
WINDOW 0 24 64 Left 2
WINDOW 3 24 0 Left 2
SYMATTR InstName D2
SYMATTR Value 1N4007
SYMBOL res 448 16 R90
WINDOW 0 0 56 VBottom 2
WINDOW 3 32 56 VTop 2
SYMATTR InstName R1
SYMATTR Value 1Meg
SYMBOL res 432 352 R90
WINDOW 0 0 56 VBottom 2
WINDOW 3 32 56 VTop 2
SYMATTR InstName R2
SYMATTR Value 1Meg
SYMBOL cap 480 64 R90
WINDOW 0 0 32 VBottom 2
WINDOW 3 32 32 VTop 2
SYMATTR InstName C3
SYMATTR Value 10.0n
SYMBOL cap 480 400 R90
WINDOW 0 0 32 VBottom 2
WINDOW 3 32 32 VTop 2
SYMATTR InstName C4
SYMATTR Value 10.0n
TEXT 96 696 Left 1 !* .tran 0 2m 1.99m\n.tran 0 50.0m 49.99m
TEXT 312 168 Left 2 ;Insulated "Fondue Forks"
TEXT 288 488 Left 2 ;Non-insulated "Fondue Forks"
RECTANGLE Normal 256 184 640 316 2
RECTANGLE Normal 256 508 640 628 2

```
> 0 votes

---
Tags: arduino-ide, arduino-nano
---


# Question
Title: How the light brightness stays constant when we increase the frequency of stroboscope
Well I am trying to make a Stroboscop. I found this code at blow: and tried. It works normally. But if I increase the RPM so decrease the "strobeDelay" time, the brightness of the LEDs goes out. Even if I try the GreatScott code. The same problem persists at high RPM. I am using power LED.

On the other hand there is a stroboscop which is Fluke 820, it says

> Features high-intensity 7-LED array—4,800 Lux @ 6,000 FPM/30cm

How they achieve that constant brightness under the high frequency?

```
    // Gray text are just helpful comments, you don’t need to type them. :)

/******* -----=====!! EASY STUFF TO MESS WITH !!=====------ ******/

  // What analog pin should we use to read the value from the potentiometer?
  int analogPin = 2; // Yep, you heard right: The coolest of the Analog pins...

  // What pin is the LED connected to?
  int ledPin = 13; // Contains a built in resistor!

  // How much time should the light stay on between delays, in Microseconds (millionths of a second)?
    /* Big number = more blur, more perceived brightness
     * Small number = less blur, less perceived brightness  */
  long onTime = 250;

  // What should the minimum delay be in milliseconds (thousandths of a second)?
  // This sets the bottom delay range of the strobe, as a delay of 0 doesn't actually flash =P
  // The strobe starts with this as the "fastest" mode, and goes slower from there, adding to the delay
  int minDelay = 1; // 1 is the lowest we can actually do without a better delay function

  // What should the maximum delay be in milliseconds?
  // This is the longest time that the biggest potentiometer value will be mapped to, and longest
  // time between strobe flashes.
  int maxDelay = 100;

/******* -----=====^^ EASY STUFF TO MESS WITH ^^=====------ ******/

// Initialize the number to hold our strobe delay. Isn't used till we get to the main loop
long strobeDelay = 0;

void setup() {
 pinMode(ledPin, OUTPUT); // Setup ledPin as an output.
}

void loop() {
  // To make the math easier, we use map(value, fromMin, fromMax, toMin, toMax) to convert the
  // 0 to 1023 range we get from analogRead, into our strobe delay range of 1 to 100 :D
  strobeDelay = map(analogRead(analogPin), 0, 1023, minDelay, maxDelay);

  digitalWrite(ledPin, HIGH); // Switch the ledPin to HIGH, turn it on!
  delayMicroseconds(onTime); // Delay while on, for the given onTime.
  digitalWrite(ledPin, LOW); // Switch the ledPin to LOW, turn if off!
  delay(strobeDelay); // Delay while off, for given strobeDelay.
}

```

For those who wonder there is a video, but another brand same result, brightness constant even if RPM changes. I tried 2 different power LED. on of them is this, the other LED is I found in a broken projector, I used them 2 working strip. No doubt in your mind, this led strip is very bright at low frequency. Both of them same result like this:

# Answer
To keep the same brightness, you have to keep the same duty cycle (percent of on time over off time). So to change the rate without changing the brightness, you have to increase delayMicroseconds(onTime) by the same percent you increase delay(strobeDelay). But note that as you go slower, the on time will be too long to freeze the motion you are trying to study. (If it's just for a party effect this may not matter.)
> 3 votes

---
Tags: arduino-nano, power, led, pwm, frequency
---


# Question
Title: ESP-01 wakes up from deep sleep and then hangs
I have found a number of other posts from people with the same problem but I can't find an answer.

I have a small batch of ESP-01 boards, sold by Inland, and I wish to use deep sleep mode on them.

I soldered a small copper wire from pin 8 (i.e. GPIO 16) to RST. On one board I soldered it directly, on another I soldered pin 8 and RST to two sides of a 2 pin header so I could use jumper in case I wanted to disconnet GPIO 16 from RST.

I am flashing the following simple code (using Arduino IDE 1.8.12), which is about the simplest test of the deep sleep mode that I can think of.

```
void setup()
{
   Serial.begin(74880);
   Serial.setTimeout(2000);

   while(!Serial) { }

   Serial.println(
     "I'm awake, but I'm going into deep sleep mode for 15 seconds");

   ESP.deepSleep(15e6);
}

void loop() {
}

```

On starting the serial monitor shows

```
ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 3664, room 16
tail 0
chksum 0xee
csum 0xee
v39c79d9b
~ld
I'm awake, but I'm going into deep sleep mode for 15 seconds

```

After 15 seconds the serial monitor shows

```
ets Jan  8 2013,rst cause:2, boot mode:(3,6)

```

and nothing else. After that the thing hangs and nothing further happens.

So, it appears that the setup runs, the serial monitor prints the message, the mc goes into deep sleep, after 15 seconds it wakes up by a reset, but doesn't go through set up again, hence doesn't print the message or go back sleep.

Here are some comments. The problem has nothing to do with Wifi, MQTT etc, I have tried many fancy sketches using all of these, I have same problem no matter what, the above sketched is my distillation to the simplest demonstration of the deep sleep problem.

I have flashed the program with Arduino IDE, Platform IO, and esptool.py from a command line. It doesn't make a difference.

There may be a problem with my soldering job, but I'm pretty good at soldering and SMD rework, and I have repeated the job on a number of these ESP-01 modules, inspected and tested with multimeter, etc. all with the same outcome.

I don't see a problem with my code or IDE, I have a batch of Lolin Nodemcu boards, and this sketch works perfectly on all of those. In that case I simply connect GPIO 16 to RST with a jumper wire, the program prints the message, sleeps for 15s, wakes up, prints it again, goes back to sleep for 15s more, etc. etc.

Are these just bad boards? I have read some things that say the flash chips might be lousy, and if I replace those it might help? I'm tempted to trash these boards and buy some D1 mini's, but I've seen a number of posts from people who say they've had the same problem with D1 minis. If the board is the problem, are there any recommendations for manufacturers or vendors that sell better quality?

# Answer
> 3 votes
Not necessarily an answer, but something to look at: check the Manufacturer ID of the Flash on your board. My suspicion is that when some Flash chips come out of suspend, they're in lower drive mode than on initial power-up. At least one person fixed his 'zombie mode' by replacing the Flash with a different vendor. Nobody else has attempted it yet.

I have an Inland ESP-01S that's reporting MID = 0x5E (supposedly Zbit) and it comes out of Deep Sleep repeatedly. Here's all of the Manufacturer IDs I know of or have seen:

Winbond EF GigaDevice C8 Puya 85 Bright Moon 53 BergMicro E0 XMC 20 XTX 0B Eon 1C Shanghai Fundan A1 Macronix C2 Hua Hong Zhixin 68 ISSI 9D Paragon E0 (same as Berg - oopsie or clone?) Zbit 5E Zetta BA

esptool.py --port /dev/ttyUSB0 flash\_id (linux) esptool.py -p COMx flash\_id (Windoze)

Note: the cheap D1 Mini boards with no-name ESP-12F modules flooding eBay, Aliexpress and other places report XTX Flash, and they have a 5.6K pull-up on EXT\_RSTB which will shorten the RST pulse from GPIO16, as well as making it hard to hit the level to be detected as a LOW due to the series 470 ohm resistor. We're unsure whether it's the Flash or the low value pull-up (typically 10 or 12K on other boards/modules) that's causing issues with those boards. Normally if RST isn't seen as LOW after Deep Sleep then you'll get an "ets\_main.c" message at boot before it hangs.

I have a clone D1 Mini Pro that has a Flash that reports MID = EF (Winbond), although the marking on the Flash is nothing I can find on Winbond's site, only on places selling cheap Flash. Luckily the D1 Mini Pro also exits Deep Sleep successfully.

# Answer
> 1 votes
I have come to the conclusion that these boards are bad. I wrote a simple sketch that turns an LED on for 3 seconds, then goes into deep sleep for 12 seconds, then wakes up. I have a batch of 3 Lolin ESP8266 nodemcu boards and the sketch works fine on all of them. The LED goes on for 3s, then goes off for 12s, then goes back on, etc. Furthermore using an ammeter I measure a current draw of around 80 mA while the LED is on, and around 4 mA while it's off, repeatedly.

However --- I have another batch of five ESP-01 boards. I soldered a fine copper wire to GPIO 16 and to the reset pin, used the same code, same set up, power supply, LED, etc. The light goes on for 3s then goes off for 12s, then comes back on and stays on and then there is no further change. Furthermore, the current draw during the first 3s is around 80 mA, but when the light comes back on and the controller hangs, the current draw is around 40mA.

Incidentally, I tested the nodemcu boards,the ones that work fine, with this sketch but disconnecting the jumper from GPIO 16 or RST, and it behaves exactly the same as the ESP-01 boards, including the 40mA current draw in the zombie state. So it would appear that the problem on the ESP-01 boards is that the GPIO 16 pin is just not connected to RST. However I have soldered all five of these things multiple times, and I have become pretty darned proficient at soldering that little pin, and I am 99.999999% sure that I have the wire soldered to the pin, with no bridges, didn't fry anything, etc.

---
Tags: esp8266
---


# Question
Title: Connect 12V 38A battery to SIM800C GSM Module
I have a gsm module that is rated for 12V and 1A. And I also have a drone Battery that is 12V and 38A. Would it hurt the gsm module If I connect it to this high power Battery?

I heard It's voltage that goes through forcefully, but current doesn't force it self through. So would it be safe to connect?

# Answer
When choosing a battery there are three basic parameters that need to be considered:

1. Voltage
2. Capacity
3. Max. current draw

In your case you have listed the requirement as 12V 1A which means you need 12V and the maximum current need is 1 Amp. You have said nothing about capacity, which is how much energy is stored in the battery so I assume it's not important here.

Your proposed 12V 38A battery will work just fine since it's still 12V and the 38A is simply the maximum current draw, not the minimum. The battery will provide up to 38A but will also source less.

Be careful, though. If you create an accidental short circuit there is a large amount of energy stored in a 38A type battery and it will be discharged very quickly indeed, possibly causing a fire. Be sure to properly insulate your wires and connections.
> 0 votes

# Answer
I looked up the SIM800C GSM Module, and it seems it requires a Lithium Ion or Lithium polymer battery, and has a built-in charging circuit in it. (It sounds like it uses the battery to manage peak current demands.) Thus you MUST use a rechargeable lithium battery for it. Having a higher current battery should be fine as long as the voltage is correct.
> 0 votes

---
Tags: power, gsm, current, voltage
---


# Question
Title: How to read an analog value on ESP32-CAM with the SD card reader enabled?
I use an ESP32-Cam module for a project for which I need both the SD card and the cam. According to this page, the only pins that are not in use by either the camera or the SD card reader are GPIO0, GPIO2 and GPIO16. However, I need to read an analog value, which is only possible with the pins 12-15, 2 and 4, as the Arduino forums state, which are all in use by the SD card reader.

However, I came across a way to make the SD reader leave the GPIO4 pin out, namely by initializing it with

```
SD_MMC.begin("/sdcard", true);

```

Now the flashlight does not light up anymore when accessing the SD card, which means that there is no output anymore to GPIO4. However, it still does not allow me to read the pin after the SD card has been initialized. I also tried "converting" the pin to a GPIO through

```
pinMode(4, FUNCTION_3);

```

but it did not make a difference.

So my question is: How can pin 4 be used to read analog values while still keeping the SD card reader functional? And if this is not possible, is there any other way to read an analog value into the ESP32-CAM?

# Answer
According to the schematic and pin notes, I don't think you can use GPIO4 as an ADC input (it can be used as a GPIO pin and technically it can be configured as an ADC pin), but it has a 47k pull-up resistor on it, making it not possible to be used as an ADC input.

Depend on your hardware wiring skill, one alternative is to use an external ADC chip with i2c interface (such as an MCP3221) and connect it to TWI\_SCL and TWI\_SDA, but those pins are only available on cam-connector, not on the header pins.
> 1 votes

---
Tags: esp32, sd-card, analogread, camera, analog
---


# Question
Title: How to prevent flickering relay upon waking from deep sleep using ESP01 board?
I have a cheap ESP01 relay module and am using it with ESPEasy. I soldered the GPIO pin 16 to RST to allow deep sleep and that all works great.

However when the unit wakes up the relay flickers quite a bit. The application I had in mind was for a 12v fridge which draws quite a bit of current on start up. I think this flickering would damage the fridge compressor or controller pretty quickly, not to mention wearing out the relay itself.

I need the unit to wake up from deep sleep, and keep the relay in the off position, unless triggered by some external criteria.

Perhaps a capacitor would absorb the pin high voltage for a short period until it's booted? Trouble is that I don't really want to hack the module, I'll probably break something.

# Answer
> 2 votes
The only two pins that don't glitch or change state during reset and boot are GPIO4 and GPIO5, and neither of them are brought out to the 2x4 header on an ESP-01. https://rabbithole.wwwdotorg.org/2017/03/28/esp8266-gpio.html

All of the other pins will make your relay click or chatter. Pick a different module, or try soldering a wire onto GPIO4 or 5. The boot time is ~ 150ms long, so it'd take a long time constant R-C circuit to filter it out, on the order of 1/2 second or more.

# Answer
> 2 votes
Apparently it's a pretty common issue for people using this board. There are a couple of solutions here that I will try: https://github.com/IOT-MCU/ESP-01S-Relay-v4.0/issues/1

The most non invasive one with Tasmoto firmware didn't work in my case. So I will try another pin and if that fails, bite the bullet and introduce a capacitor.

---
Tags: esp8266, relay, sleep, esp
---


# Question
Title: ESP-01 does not run code after Deep Sleep
When using the deep sleep functionality on several ESP-01 boards, the boards require two resets in order to wake up properly (regardless of whether the resets are done by manually bridging the rst pin or by soldering a wire to do it from an interrupt). The boards do wake up and print some text automatically, but they do not run their firmware/code.

```
#include <ESP8266WiFi.h>
void setup() {
    Serial.begin(74880);
    Serial.print("\n--------------STARTING----------------\n");

    //pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
    //digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off (gpio @ high= off)

    delay(500);
    ESP.deepSleep(2000000, WAKE_RF_DEFAULT );
}

void loop() {
}

```

I have not been able to just wake the board and run the code like most examples on the web intend to work, so I suppose the problem is not with this code.

On a successful wake up, the serial output looks like this:

```
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld

--------------STARTING---------------

```

After the first reset, the board does indeed wake up, but it does not run it's code. It only prints this

```
 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

```

And then hangs there. After another reset, it successfully runs it's code.

This issue persists across all the esp 01 boards i own, and i have tried pulling UP and DOWN almost every combination of pins recommended. The line that is printed in the fauly cases does indeed say it is booting in the right mode, but still the code does not run, nor mine nor the one that runs before mine

# Answer
What sasso is describing is classic Deep Sleep Zombie mode. There's someone else here with ESP-01 boards with the same issue. I'd bet you got your boards in blister packs from Inland. I didn't see any ESP-01 boards from Inland at my local computer store, only ESP-01S, and that one works with Deep Sleep just fine. I only bought the one for a test. I believe it's the Flash chip, but we haven't proven that yet. I have plenty of Winbond flash in case I find a board that goes zombie, and can prove or disprove my theory. I have 8 different types of boards and modules, and all come out of Deep Sleep correctly.

edit: If the pic at Ali is correct, the Puya Flash shouldn't be causing an issue, presuming it's real and not a clone. Half the time the pics are only 'representative examples' of what they ship. The ESP8266 Arduino core has supported Puya for a while now. Also, on sober reflection the Inland package I bought said ESP-01S, and it's actually an ESP-01 (false advertising). I looked closer and didn't see the pull-up resistors. :-(

If you're powering it from that USB programmer board, it should work. If you have a separate 3.3V supply, I'd be suspicious of the supply. The current spikes as the ESP is booting will cause many switching supplies to drop below 2V briefly, and the ESP goes insane. Without having a zombie in front of me, I'm at a loss to go a lot further as my 'scope leads aren't that long.
> 3 votes

---
Tags: esp8266
---


# Question
Title: Is there any better choice other than using delay() for a 6-hours delay?
I am designing an incubator system and I need to drive a motor forward and reverse every 6 hours. Is there any better choice other than using `delay()`? A 6-hours delay seems a little unprofessional.

# Answer
Several options here, and a couple folks have pointed out some challenges.

"Best" answer -- probably to use a real-time clock (RTC) board to assist your timing, and effectively set a target time (next motor run is at 23:14...) each time the cycle restarts. By saving this target off (to the EEPROM or an SD card for instance), you'd protect against a potential shutdown and reset of the arduino in the middle.

Secondary answer; set your loop() to include a relatively short delay() statement, then check the elapsed time since the last motor engagement. This would allow you to have other items processing, as someone else noted in this thread. This I've pseudocoded below.

```
unsigned long lastMotorRunTime;

void loop()
{
    /*
     * do whatever
     */
    if(millis()-lastMotorRunTime > 21600000)  // 6 hours have passed
    {
         runTheMotor(); // placeholder for the motor movements you need
         lastMotorRunTime = millis();
    }
   /*
    * do other stuff
    */
   delay(100); // loop about every 1/10 second, or whatever works
}

```

Given you don't seem to need detailed precision -- a few seconds either way wouldn't matter -- this should work reasonably. Note it WILL fail if the Ardiuno is reset -- then it will only (in my pseudocode) rotate the motor 6 hours after the last Arduino reset. Probably better to assume that an arduino reset means move the motor 'now', if the point is to ensure periodic motion rather than precise timing.

For precise timing, as noted, the RTC would be required.

(Updated: Changed lastMotorRunTime to unsigned long)
> 9 votes

# Answer
Using `delay()` for a 6-hour delay is a bit awkward, but perfectly doable. It will, however, not be very accurate, because the accuracy depends on the accuracy of the Arduino's clock, and it will block all other code you may wish to run.

Using timing with `millis()` would allow your Arduino to do other things while waiting. It will be just as inaccurate, though.

For long periods, and especially if you want things to be more accurate, you could use an external Real Time Clock, like the DS3231. You can get these as modules on break-out boards, and libraries are also available.

These RTCs have a backup battery, so they also keep running a while without external power, and will also keep time when the Arduino resets. Most also have settable alarm times you could use.

For your application, I would also implement a simple *watchdog timer* to make sure the Arduino is still waiting and working, and hasn't crashed. Note that a watchdog timer won't play nice with `delay()`; a simple 6-hour delay will always trigger it, and timing with `millis()` or an external RTC is the way to go here.
> 3 votes

# Answer
Since this is for an incubator, I suspect that you don't need high precision. So delay() will work perfectly well, if you don't want to do anything else in the meantime (like maybe monitor temperature, control a heater, and/or light LEDs for over/under temperature). In that case you could use a loop that handled all those operations at some convenient rate like once per second or once per minute, using delay() in the loop. (I assume that your incubator is slow to respond to the heater, so slow sampling will be fine.) Then let the loop run for 6 hours, which you can determine by simple count of the 1-minute (or whatever) loop delays. And if you find that your 6-hour time is consistently high or low, adjust the count limit to compensate.
> 3 votes

# Answer
I have an automatic watering system that (among other things) trigger on time. I use the excellent Timer Library for this. It allows several useful timed interactions such as `Pulse` or `Oscillate` in addition to `After` which would solve your issue - or `Every` if you want a recurring 6 hour code block to execute

In the end - behind the screen - it is just as unprofessional as `millis()` \- the library itself uses `millis()` and a scheduler. But the code looks cleaner and is easier to write and update.
> 2 votes

# Answer
There's nothing wrong with using delay here.

There is only a problem if you want to make the Arduino do something else as well. I that case you'd want to use `millis`, and use that to calculate how much time has passed (see blink without delay).
> 0 votes

---
Tags: programming, motor, time
---


# Question
Title: Relays just switch ON and OFF on delay(), not on millis()
I use fuzzy logic for the running time of relays, but the relays just switch ON and OFF at the interval of the `delay()` I put at the end of loop.

This is my code:

```
void loop () {
  ph = -180/100.0;
  hasilec = -1.2;
  unsigned long now = millis();

  Serial.print("pH    ");
  Serial.print(ph);
  Serial.print("  ");
  Serial.print("EC ");
  Serial.print(hasilec);
  Serial.println("");
  Serial.print(ph);
  Serial.print(" ");
  Serial.print(hasilec);
  Serial.print(" ");
  Serial.println(" ");

  fuzzy->setInput(2, hasilec);
  fuzzy->setInput(1, ph);
  fuzzy->fuzzify();

  float pompa01 = fuzzy->defuzzify(1); //pHDOWN
  float pompa02 = fuzzy->defuzzify(2); //pHUP
  float pompa03 = fuzzy->defuzzify(3); //ABMIX

  long int pompa1 = pompa01 * 1000;
  long int pompa2 = pompa02 * 1000;
  long int pompa3 = pompa03 * 1000;

  Serial.println("Result= ");
  Serial.println("");
  Serial.print(" Pompa1 pHDOWN: ");
  Serial.println(pompa1);
  Serial.print(" pompa2 phUP  : ");
  Serial.println(pompa2);
  Serial.print(" pompa3 ABMIX : ");
  Serial.println(pompa3);
  Serial.println("");
  Serial.println("");
  Serial.println("");

  pump_periods[0] = pompa1;
  pump_periods[1] = pompa2;
  pump_periods[2] = pompa3;

  for (int i = 0; i < jml_pump; i++) {
    if (now - pump_last_actuations[i] >= pump_periods[i]) {
      pump_states[i] = (pump_states[i] == LOW) ? HIGH : LOW;
      digitalWrite(pump_pins[i], pump_states[i]);
      pump_last_actuations[i] = now;
    }
  }
  delay (20000);
}

```

The relay just switch ON and OFF on this delay `delay (20000);`.

What should I do?

# Answer
Check the values of `pompa1`, `pompa2`, and `pompa3` to see if they are always smaller than 20000 (I suspect they are).

The `delay(20000)` (why is it there anyway?) could well be messing up your timing of the toggling of the `pump_states` by always delaying longer than the values in `pompa1`, `pompa2`, and `pompa3`.

This would make the relays toggle every 20 s (on every loop).
> 1 votes

---
Tags: relay, millis, timing
---


# Question
Title: How can I have different routines fire off at different intervals
I'm making an interface that will have a digital clock....once a second..

I'd like to do other things at different intervals but if I `delay(1000)` then I have to wait that second which is now the minimum other things have to run at.

# Answer
> 1 votes
As said in the comments: you should read up on State Machines and have a close look at the Blink Without Delay example.

To get you started with an example closer to what you want to achieve, have a look at the code below; it will count seconds without blocking the loop.

```
unsigned long int secondsTimerMillis;
int seconds, minutes, hours = 0;
int secondsInterval = 1000; //ms

void setup() {
  Serial.begin(9600);
  // More setup() stuff goes here
  secondsTimerMillis = 0;
}

void loop() {
  if ((millis() - secondsTimerMillis) >= secondsInterval) {
    seconds++;
    secondsTimerMillis = millis();
    Serial.println(seconds);
    // More stuff you want to do every second goes here
  }
  // More loop() stuff goes here
}

```

This is just the basic mechanism, and it won't be very accurate without some way of adjusting the clock every now and again.

You will also have to add code for checking `seconds == 60` and increase `minutes` / reset `seconds` when needed; the same goes for hours.

Having/handling other events at other intervals is just more of the same.

Note that using a Real Time Clock as the basis for your timing would make your life programming much easier, and your clock more accurate, but I am assuming you want to do this "by hand".

# Answer
> 0 votes
If you want a clock, your best option is... to buy a clock. Or, more precisely, an RTC module. Not only will it be way more accurate than your Arduino, it will also be able to keep the time off battery when your project is powered off.

If you really want to rely on the (unreliable) timing capabilities of your Arduino, you may want to try the `millis()`-based fake RTC provided by the Adafruit RTClib library: RTC\_Millis. Example usage:

```
#include <RTClib.h>

RTC_Millis clock;

void setup() {
    Serial.begin(9600);
    clock.begin(DateTime(F(__DATE__), F(__TIME__)));
}

void loop() {
    static DateTime last_time;
    DateTime now = clock.now();
    if (now != last_time) {
        char buffer[] = "hh:mm:ss";
        Serial.println(now.toString(buffer));
        last_time = now;
    }
}

```

Note the test `if (now != last_time)`, which is equivalent to the test `if (currentMillis - previousMillis >= interval)` of the Blink Without Delay tutorial (the RTC has a resolution of one second). It allows the code to be non-blocking.

Note also that, if you are willing to measure you clock's drift rate, you could calibrate-out that drift by using RTC\_micros instead, and calling the `adjustDrift()` method in `setup()`.

---
Tags: esp32, loop
---


title: Question about button circuit

text:
# Question
Title: Question about button circuit
I'm quite a beginner at electronics, but thought I would try venture into it. Currently I'm working on a project where I need to reuse a button module salvaged from some old hardware, but I can't figure out the wiring. The attached image is what I was able to track down on how the circuit is built. I'm not really sure how to wire it? Would it be possible to use this with an ESP32 and differentiate all the buttons?

# Answer
Sure. Take a multimeter and measure the resistance between the left-most pin and each of the other pins with all the different combinations of button pairs pressed. Write down the results.

Then build a voltage divider for each output (Connect a resistor to ground on each output, and then connect that pin to an analog input on the Arduino. The resistor value to use will depend on the readings you get, but a 1K ohm resistor would be a good starting point.)

Then set up the 2 input pins on your Arduino as analog inputs and measure the voltage with no buttons, top button, bottom button, and both buttons pressed for each pair. Write those values down. Then write code that checks for voltages *roughly* equal to your measurements for each button press combo (You will need check for ranges of values, since the values will vary some.)
> 0 votes

---
Tags: esp32, button
---


# Question
Title: Millis() does not back to zero after woke up from deep sleep mode
I am going to make a project that needs four boards of Arduino which synchronization in time is needed. The project is about capturing the timestamp (in ms resolution) whenever something is crossing ultrasonic proximity sensor. The following are the modules I am going to use:

1. Arduino Uno R3 4 units
2. Ultrasonic Proximity sensor 4 units
3. DS1302 RTC modules 4 units
4. Micro SD Card modules 4 units

The boards will be placed in 4 different places which it is quite far from each other that makes it is hard to make wired connection. The detecting object will move back and forth during a certain interval of time, so that is why the time synchronization is needed.

My idea is, by using the timestamp from RTC modules, I turn all the boards together into deep sleep mode at the time I have set in the code and wake them up together after 10 seconds. I don't have any problem with RTC modules, but my problem lies in the millis() function which did not back to zero after woke up from deep sleep mode. I need this function since the DS1302 RTC does not provide ms resolution, yet I can not achieve sync if the millis() function does not back to zero.

I tried the code (edited with millis() added in the loop) from here: https://www.youtube.com/watch?v=8fiYvnBDsDE

Do you have any solutions? Or another RTC module which provides ms resolution instead. Thank you

# Answer
Store millis() at boot, and if (resetCause == "Deep-Sleep Wake") zero out the stored copy of millis().
> 2 votes

# Answer
I do not understand how you will get them to sync with each other. The RTC modules work great but there is no communications to set or update them and they do drift. With the RTC it will be easy to generate a timestamp using Unix time. There is a lot of information posted on how to do this. syncing (making all the clocks the same) is where I believe your problem is. Consider adding WiFi to each and use NTP to sync everything, it would be automatic.
> 0 votes

---
Tags: millis, sleep
---


title: ATTiny13 Interrupt Issue

text:
# Question
Title: ATTiny13 Interrupt Issue
I have recently been working on a project that I had initially been designing with an Arduino Nano, and I was able to create functioning code for my application, but for cost / space reduction I decided to port the application to an ATTiny13 (because I had a few on hand). The problem is that for some reason, I cannot get the interrupt on the device to behave properly, and I was wondering if anybody could possibly give me a hand. I already performed a few experiments to narrow the problem down, and I think I understand the nature of the problem, but I have no idea on how to mitigate it.

Here is a rough schematic of my setup:

And here is the code I started with:

```
// Pin defines
#define ALERT_LED 4

// Variables
bool LED_STATE = false;

ISR(PCINT0_vect) {
  LED_STATE = true;
}

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

  // Configure the button-pin to have a pull-up
  DDRB |= (1<<DDB3);
  PORTB |= (1<<PORTB3);

  // Enable a pin-change interrupt on the PCINT3 (falling-edge)
  MCUCR |= (1 << ISC01);  // This and following line setup for falling-edge
  MCUCR &= ~(1 << ISC00);
  GIMSK |= (1 << PCIE);   // Enable pin-change interrupts
  PCMSK |= (1 << PCINT3); // Setup the pin-mask so that PB3 triggers the interrupt
  sei();                  // enable all interrupts

}

void loop() {
  if(LED_STATE == true) {
    digitalWrite(ALERT_LED, HIGH);
    delay(2000);
    digitalWrite(ALERT_LED, LOW);
    delay(2000);
    LED_STATE = false;
  }
}

```

In theory, this should setup the pin that the button is on to have a pull-up resistor internally, and when the button is pressed, it should trigger a falling-edge interrupt which would thus set "LED\_STATE" equal to 1. When the code returns to the main loop, it should see the flag and blink the LED before clearing the flag.

Now before I go any further, here is what I validated up to this point:

1.) The LED circuit is definitely wired up properly because I can manually set the "LED\_STATE" flag to true in the main loop, and it will constantly blink at a rate of about once a second (given the clock frequency of 600kHz)

2.) The pull-up is definitely being configured properly, as I can see the voltage sitting at 5V until I press the button at which point the voltage falls to 0V.

So I decided to experiment a bit, and I set the LED high inside the interrupt, and removed that line from the main loop to see if the interrupt was even working, and to my surprise the LED was actually turning on, but it was not turning off:

```
// Pin defines
#define ALERT_LED 4

// Variables
bool LED_STATE = false;

ISR(PCINT0_vect) {
  LED_STATE = true;
  digitalWrite(ALERT_LED, HIGH);
}

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

  // Configure the button-pin to have a pull-up
  DDRB |= (1<<DDB3);
  PORTB |= (1<<PORTB3);

  // Enable a pin-change interrupt on the PCINT3 (falling-edge)
  MCUCR |= (1 << ISC01);  // This and following line setup for falling-edge
  MCUCR &= ~(1 << ISC00);
  GIMSK |= (1 << PCIE);   // Enable pin-change interrupts
  PCMSK |= (1 << PCINT3); // Setup the pin-mask so that PB3 triggers the interrupt
  sei();                  // enable all interrupts

}

void loop() {
  if(LED_STATE == true) {
    //digitalWrite(ALERT_LED, HIGH);
    delay(2000);
    digitalWrite(ALERT_LED, LOW);
    delay(2000);
    LED_STATE = false;
  }
}

```

At this point, I started to think that the ISR was not returning to the main loop or something, but by adding an 'else' case to shut the LED off in the main loop, I could see that the loop was definitely running after the ISR, because the LED would not turn on (implying that the main loop had to be shutting it off the moment the ISR returned to the loop).

```
// Pin defines
#define ALERT_LED 4

// Variables
bool LED_STATE = false;

ISR(PCINT0_vect) {
  LED_STATE = true;
  digitalWrite(ALERT_LED, HIGH);
}

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

  // Configure the button-pin to have a pull-up
  DDRB |= (1<<DDB3);
  PORTB |= (1<<PORTB3);

  // Enable a pin-change interrupt on the PCINT3 (falling-edge)
  MCUCR |= (1 << ISC01);  // This and following line setup for falling-edge
  MCUCR &= ~(1 << ISC00);
  GIMSK |= (1 << PCIE);   // Enable pin-change interrupts
  PCMSK |= (1 << PCINT3); // Setup the pin-mask so that PB3 triggers the interrupt
  sei();                  // enable all interrupts

}

void loop() {
  if(LED_STATE == true) {
    //digitalWrite(ALERT_LED, HIGH);
    delay(2000);
    digitalWrite(ALERT_LED, LOW);
    delay(2000);
    LED_STATE = false;
  }
  else {
    digitalWrite(ALER_LED, LOW);
  }
}

```

At this point, I can really only think that there must be a problem with how I am defining the "LED\_STATE" parameter, because all signs point towards this variable not actually holding the information properly when traversing from the ISR back to the loop. I don't see what would be the problem though since I defined the parameter globally. Can anybody lend a hand here, this is honestly the last thing I need to finish this part of the project, and I am honestly at a bit of a loss at this point.

# Answer
You would want your `bool LED_STATE = false;` to be volatile qualified like `volatile bool LED_STATE = false;` otherwise the compiler's optimizer may assume that the value cannot be changing between loads and this can cause bugs in the generated code. This sounds like the principal problem you're having.

The `ISC01` and `ISC00` in `MCUCR` are for controlling edges detected on the "external interrupt" INT0 pin, which is PB1, package pin 6. This is essentially what `attachInterrupt()` does, which should be available to you in your board support package. If you can, it's probably best to just use that. In the case of using `attachInterrupt()` the use of `volatile` would still apply.

The other pins, like the one you've chosen, only only do **P**in **C**hange interrupts, hence PCINTn rather than INTn. Pin change interrupts only fire to tell that a pin changed, but not which pin (out of the group) or in what direction it changed. That is, it's ignoring what you've set in `MCUCR`.

If you want an external interrupt's ability to detect falling or rising edges using PCINTn interrupts, you must effectively synthesize this in software by tracking the old and new states of the pins, XORing them to determine what changed, and then either looking at the old or new state to determine what direction. NicoHood's PinChangeInterrupt library does this for you, and appears to support the ATTiny13. Likewise, `volatile` usage applies here as well.
> 7 votes

---
Tags: interrupt, memory-usage, attiny13
---