title: Digital Sound sensor

text:
# Question
Title: Digital Sound sensor
I am having trouble with my digital sound sensor. My goal: Clap 2 times and a led goes on. So I wrote this code. I don't know if it is correct or not. This happens: If I clap, from the serial monitor I don't get one HIGH, but a few (I tried changing the sensitivity of the soundsensor, but it doesn't help), but in my code I have some conditions where only 1 HIGH at a time is allowed. Thus, I don't know if my code is incorrect, or my sensor isn't working well. Can you guys help me please? This is my code:

```
int soundPin = 13;             // Digital soundPin
int ledPin = 7;
int claps = 0;                 // The amount of times I clapped
int readingState ;             // The first reading from the soundPin
int readingState2 ;            // The second reading from the soundPin
int soundDetectionTime ;       // The time after the first clap
int soundDetectionTime2 ;      // The time after the second clap
int timeBetweenSounds = 1000;  // The time between the sounds I want. There
                                  is an If-statement further on.

void setup(){
  pinMode(soundPin, INPUT);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop(){
  readingState = digitalRead(soundPin);    // The first reading form the
                                              soundPin (digital pin)

  Serial.println(readingState);

  if (readingState == HIGH){               // If the reading from the
                                             soundPin is HIGH, then start
                                             timing. Also claps value
                                             increased by 1 and the
                                             second reading is happening.
    soundDetectionTime = millis();
    claps++ ;
    readingState2 = digitalRead(soundPin);

      if (readingState2 == HIGH){          // If the above statement is
                                              true, then this if-statement
                                              is executed. If the second
                                              reading is HIGH,
                                              soundDetectionTime two will
                                              start counting
    soundDetectionTime2 = millis();    // Also the claps get increased by 1,
                                          so now claps = 2.
        claps++;
   }
   }

   if ((soundDetectionTime - soundDetectionTime2) > timeBetweenSounds &&
claps==2){                            // If there is 1 second between the
                                         two readings and if I clapped
                                         twice, then LED is HIGH.
    digitalWrite(ledPin, HIGH);
   }
   }

```

UPDATE: I managed to get two HIGHs seperate from each other and the led is now on. So the problem must be the sensor giving me too much HIGHs if I clap once, like: 0,0,0,0,1,1,1,0,0. What do you guys think?

# Answer
Here is a "stripped down version" of a sketch I used to replicate the Clap On, Clap Off lamp switch we had in the 1980's. It works with the KY-038 sound sensor module you currently have. You will need to install the VirtualDelay Library.

The sound sensor module is very sensitive. A quarter turn of the potentiometer around the "sweet spot" makes a huge difference. Too sensitive, and the digital output is constantly high. If it's not sensitive enough, then you have to physically "tap" the microphone to get a high/low transition out of it.

Please note: This sketch uses delay() which is "blocking code" and it's use is usually not recommended.

```
#include "avdweb_VirtualDelay.h"
byte clapCounter = 0;
const byte soundSensorPin = 2;
const unsigned long loopDelay = 1;
const unsigned long clapCounterDelay = 400;
unsigned long clapCounterTimerDuration = 1000;
unsigned long previousMillis = 0;

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

void loop(){

  // Timer object.
  static VirtualDelay clapCounterTimer;

  // Get the current time.
  unsigned long currentMillis = millis();

  // Check for a clapping sound (1 ms works good). If too much time
  // elapses here, you could miss the "beginning" of the clap.
  if(myTimer1(loopDelay, currentMillis) == 1){

    // Clap detected.
    if(digitalRead(soundSensorPin) == 1){

      clapCounter += 1;

      // When the first the clap is detected, start a timer
      // to reset the clap counter to 0 after 1 second.
      if(clapCounter == 1){
        clapCounterTimer.start(clapCounterTimerDuration);
      }

      // Delay execution of the loop. 400 ms works good.
      delay(clapCounterDelay);

      // If a second clap is detected, toggle the LED ON/OFF.
      if(clapCounter > 1){
        digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
      }

    }
  }

  // Reset the clap counter to 0 after 1 second. If
  // you don't do this, you could clap once, wait a
  // minute, then clap again and the LED will change state.
  if(clapCounterTimer.elapsed()){
    clapCounter = 0;
  }

}

// Clap loop timer.
byte myTimer1(unsigned long loopDelay, unsigned long currentMillis){
  if(currentMillis - previousMillis >= loopDelay){previousMillis += loopDelay;return 1;}
  else{return 0;}
}

```

**EDIT:** To answer your question regarding the multiple High to Low transitions from the module's digital output, you can use a DSO to look at the relationship between the analog and digital signals it produces.

In the following image, the digital signal (yellow trace) and the analog signal (blue trace) are superimposed over each other. The white dashed line (E), is set to 2.8 VDC which is **approximately** the analog output pin's voltage with ambient room noise. Once you clap in front of the microphone, this wave form is generated.

The entire clap lasts about 5.6 ms and the module gives you 18 High to Low transitions on it's digital output pin. When the analog voltage **drops below** a certain voltage, the digital output goes High. When the analog voltage **goes above** that voltage, the digital output goes Low.

The problem is, the sound of a person clapping generates a noisy signal and the sound sensor module does not know the difference between noise and the sound you want to trigger it.

Instead of using `delay()` like I did, you could increment a "clap counter" to equal "1" on the first Low to High transition of the digital output pin. Next, start a non-blocking `millis()` timer that waits before you read the digital output pin again. If digital out is High after 400 ms, it's your second clap so change the LED state. A second `millis()` timer could reset the "clap counter" to 0 after 1 second.
> 1 votes

# Answer
Your logic is flawed; you don't have any delay between readingState and readingState2 other than a serial.Print() which you shouldn't rely on for a delay.

You need to keep track of state in your loop. You need to capture the time of the first input, see it go low, then record the time of the second input. N.b. time between instructions is blindingly fast even on 'slow' proccessors.

something like:

```
// edit: just gonna refactor a bit
// edit: added debounce
unsigned long start, end, time;
int state = 0;
...
#define BOUNCE 10
int dbounce(unsigned long time, unsigned long start, unsigned long len)
{
    return (time - start) > len;
}
...
void loop()
{
  pin = digitalRead(soundPin);
  time = millis();
  switch(state)
  {
  case 0:
      if (pin == HIGH)
      {
        start = millis();
        state = 1;
      }
      break;
  case 1:
      if dbounce(time,start,BOUNCE)
          break; // one way to debounce
      if( pin == LOW)
          state = 2;
      break;
  case 2:
      if(pin == HIGH)
      {
         end = millis();
         state = 3;
      }
      break;
  case 3:
      if(dbounce(end,start,1000))
      {
         // do stuff
      }
      state = 4;
      break;
  case 4:
      if((pin == LOW) && dbounce(time,end,BOUNCE)) //another way to debounce
         state = 0; // start over
      break;
  }
}

```
> 0 votes

---
Tags: arduino-uno, digital, sound
---


# Question
Title: Measuring lenght of time light levels peak using photoresistor
I'm trying to measure shutter speeds on old cameras. This essentially consists of:

1. Shining a torch at one end of the camera
2. putting the photoresistor at the other end
3. trigger the shutter which temporarily lets in the light from the torch (boosting the photoresistor values temporarily)
4. Recording the duration of the increased spike in light levels

What I have currently records light levels but the variation is massive and typically incorrect in that they change depending on how close the torch is to the shutter and typically records values between 400 and 900 ms which is far too long (should be about 50ms).

This is the key code I have so far:

```
if (shutterbot.opened())
{
    /* Measure length of time it is opened until closure */
    unsigned long previousMillis = millis();

    while(true)
    {
        unsigned long currentMillis = millis();
        unsigned long time_elapsed = currentMillis - previousMillis;

        if (shutterbot.closed())
        {
            finished = true;
            /* Report back to user */
            Serial.println("Shutter speed is: ");
            Serial.println(time_elapsed);
            break;
        }
    }

```

}

The open and close methods in the shutterbot class are:

```
/* If light is 10% higher, set it to start recording */
int Shutterbot::opened()
{
    if (light_level() > 400)
    {
    return true;
    }
    else
    {
    return false;
    }
}

/*
  If light drops to below 10% higher, set it to stop
  recording
 */
 int Shutterbot::closed()
 {
     if (light_level() < 400)
     {
     return true;
     }
     else
     {
     return false;
     }
}

```

The full project code is here and just needs a photoresistor module and an arduino uno to test. I'm not sure I've provided enough information so if there are any questions, please let me know. Any help is greatly appreciated and thanks for reading.

# Answer
> 0 votes
It is unlikely a photo resistor can be used to time an event with sub second granularity. This is because the electrons in such a device have many conductive states which they migrate into when exposed to light and out of when left in the dark. It takes time for the electrons to drift into and out of these conductive bands. In some cases it may take a good portion of a second. As described in the 2nd paragraph in the Design Considerations section of the above wikipedia page:

> Photoresistors also exhibit a certain degree of latency between exposure to light and the subsequent decrease in resistance, usually around 10 milliseconds. The lag time when going from lit to dark environments is even greater, often as long as one second. This property makes them unsuitable for sensing rapidly flashing lights, but is sometimes used to smooth the response of audio signal compression.

---
Tags: arduino-uno, timing, photoresistor
---


title: Wait for ALL serial data to be received

text:
# Question
Title: Wait for ALL serial data to be received
Is there a way to make the Arduino wait until all the serial data has been received? Say I send a 32 byte long string over serial (the length is actually random), how would I make my Arduino wait till all 32 bytes have been received?

If I execute `Serial.readBytes` straight away, it only reads one char. At the moment I'm using delay, but I'm worried that it is wasting time on the Arduino, as I would like it to be processed straight away. What I want to happen is I plug in my Arduino, type in the name of an input and output file, and it will start copying the input file into the output file. I don't want to re-upload every time I want to change files, so I would like to select over serial which ones to use. However, sometimes there will be no `\r` or `\n` sent at the end, which cuts off some of the file name.

Here is my code:

```
#include <SoftReset.h>
#include <SPI.h>
#include <SdFat.h>
#define csPin 4

SdFat SD;
File sourceFile;
File outputFile;

int bufSize;
uint32_t lastPos = 0, timeLast, timeNow;
//fix this (error: deprecated conversion from string constant to 'char*')
//char *outputFileName = "output.wav";
#define outputFileName "output.wav"
byte avail;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
  }
  Serial.print(F("Initializing SD card..."));

  // see if the card is present and can be initialized:
  if (!SD.begin(csPin, SPI_FULL_SPEED)) {
    Serial.println(F("Card failed, or not present"));
    soft_restart();
  }
  Serial.println("Card initialized.");
enterInputFileName:
  Serial.println(F("Enter input file name:"));
  while (!Serial.available()); // wait till serial available
  delay(100);
  avail = Serial.available() - 2; // extra '\n' & '\r' that we dont want
  char inbuf[avail];
  Serial.readBytes(inbuf, avail);
  Serial.read(); // remove '\n' from buffer
  Serial.read(); //remove '\r' from buffer
  inbuf[avail] = '\0';

  char inputFileName[avail];
  strcpy(inputFileName, inbuf);
confirmInputFileName:
  Serial.print(F("Select file '"));
  Serial.print(inputFileName);
  Serial.println(F("'? Y/N"));

  while (!Serial.available()); // wait till serial available
  delay(100); //wait for all chars to be recieved
  avail = Serial.available() - 2;
  if (avail > 1) {
    Serial.println(F("Enter 1 character"));
    while (Serial.available()) { //clear serial buffer
      Serial.read();
    }
    goto confirmInputFileName;
  }
  char confirm = Serial.read();
  Serial.read();
  Serial.read();
  switch (confirm) {
    case 'Y': break;
    case 'y': break;
    case 'N': goto enterInputFileName; break;
    case 'n': goto enterInputFileName; break;
    default: Serial.println(F("Enter Y/N")); goto confirmInputFileName; break;
  }
  //up to here works
  Serial.println(SD.exists(inputFileName));

  SD.remove(outputFileName);
  outputFile = SD.open(outputFileName, FILE_WRITE);
  outputFile.close();
  //read source and write to output
  sourceFile = SD.open(inputFileName);
  timeLast = micros();
  if (sourceFile) {
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
    Serial.println(F("Copying"));
    while (sourceFile.available()) {
      //make buffer size 50% of free ram, or amount of bytes left if smaller
      bufSize = min((freeRam() * 0.5 ), sourceFile.available());
      byte data[bufSize];
      sourceFile.readBytes(data, bufSize);
      lastPos = sourceFile.position();
      sourceFile.close();
      outputFile = SD.open(outputFileName, O_APPEND | O_WRITE);
      outputFile.write(data, bufSize);
      printStats();
      outputFile.close();
      sourceFile = SD.open(inputFileName);
      sourceFile.seek(lastPos);
    }
    sourceFile.close();
    outputFile.close();
    Serial.println(F("Finished"));
    unsigned int sec = millis() / 1000;
    unsigned int mins = sec / 60;
    sec -= mins * 60;
    Serial.print(F("Time taken: "));
    Serial.print(mins);
    Serial.print(':');
    Serial.print(sec);
    Serial.print(F("Speed: "));
    Serial.print((sourceFile.size() / 1000) / (millis() / 1000));
    Serial.print(F(" KB/s"));
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.print("error opening files");
    SD.initErrorHalt();
  }
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(200);
  digitalWrite(LED_BUILTIN, LOW);
  delay(200);
}

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}

void printStats() {
  timeNow = micros();
  uint32_t timeTaken = timeNow - timeLast;
  float sent = sourceFile.position() / 1000.0;
  float fileSize = sourceFile.size() / 1000.0;
  float left = fileSize - sent;
  float speed;
  speed = 1000000UL / timeTaken * bufSize;
  speed /= 1000;
  unsigned int sec = millis() / 1000;
  unsigned int mins = sec / 60;
  sec -= mins * 60;
  int estSec = (left / speed);
  int estMin = estSec / 60;
  estSec -= estMin * 60;
  Serial.print(F("\tSent (KB): ")); Serial.print(sent);
  Serial.print(F("\tLeft (KB): ")); Serial.print(left);
  Serial.print(F("\tSize (KB): ")); Serial.print(fileSize);
  Serial.print(F("\tTime: "));      Serial.print(mins); Serial.print(':'); Serial.print(sec);
  Serial.print(F("\tSpeed (KB/sec): "));     Serial.print(speed);
  Serial.print(F("\tFree: "));      Serial.print(freeRam() - bufSize);
  Serial.print(F("\tBuf: "));       Serial.print(bufSize);
  Serial.print(F("\tEST: "));       Serial.print(estMin); Serial.print(':'); Serial.print(estSec);
  //todo fix this line
  //Serial.print(F("\tExists(I,O): ")); Serial.print(SD.exists(inputFileName)); Serial.print(SD.exists(outputFileName));
  Serial.print('\n');
  timeLast = micros();
}

```

# Answer
You need to format the message so that the receiver knows where the message ends and a new one begins.

Then on he receiving end you fill a buffer until a full message is received and then handle the message.

A more advanced tactic is to process the bytes as you receive them. This requires that you build a statemachine but means you don't have to store a copy of the entire message.
> 0 votes

# Answer
after source code was add to the question:

you use the readBytes function wrong. if you set the size parameter to count of available bytes it will read the count of available bytes.

allocate a buffer and set the second parameter as the buffer size. the readBytes will try to fill the buffer, waiting max one second for the next character, which is enough to read the complete line sent from Serial Monitor.

```
if (Serial.available()) {
  char buff[50];
  int length = Serial.readBytes(buff, sizeof(buff) - 1);
  buff[length] = 0; // terminating zero of c-string
  Serial.println(buff);
}

```

note: readBytes will wait one second after the last character received. better is to use readBytesUntil with expected terminator. or you can set smaller timeout on Serial with Serial.setTimeout(200)
> 1 votes

# Answer
I was concerned about the same thing recently when I worked on a project that would read serial data (received on a Bluetooth HC-05).

My loop() does a lot of work for my project (Never Type A Password Again (Arduino-driven Touchscreen Device @ CodeProject.com ) but reading the serial data is a big part of the work to do also.

I implemented the following code and it has been literally running for weeks now with no problems.

```
if (Serial1.available() > 0) {
    incomingByte = Serial1.read();
    while (incomingByte > 0){
      if (incomingByte == 0x01){
        Keyboard.press(KEY_LEFT_CTRL);
        Keyboard.press(KEY_LEFT_ALT);
        Keyboard.write(KEY_DELETE);
        Keyboard.release(KEY_LEFT_ALT);
        Keyboard.release(KEY_LEFT_CTRL);
      }
      else{
         Keyboard.write(incomingByte);
      }
      incomingByte = Serial1.read();
    }
  }

```

You can see that it reads bytes while they are available which might lead you to think it might lock up, but it handles it very well.

**Quite A Bit Of Work**

It does quite a bit of work because it is capturing any bytes that come across Bluetooth (and then it types them on the connected computer -- that's a long story, check out the article for more).

**Quite A Few Bytes**

It also reads at least 64 bytes (password length + special Control char bytes) but it handles it quite well.
> -1 votes

---
Tags: serial, arduino-mega
---


title: Which key is KEY_LEFT_GUI?

text:
# Question
Title: Which key is KEY_LEFT_GUI?
This might be a very simple question but I don't know which key represents KEY\_LEFT\_GUI on my keyboard. I thought it was the windows key but when I program Arduino Micro to execute it. Run does not open and it prints powershell on the "Search Programs and Files" section in Windows7 VM.

```
  Keyboard.press(KEY_LEFT_GUI);
  delay(1000);
  Keyboard.press('r');
  delay(1000);
  Keyboard.releaseAll();

  delay(500);

  Keyboard.print("powershell");
  typeKey(KEY_RETURN);

```

# Answer
KEY\_LEFT\_GUI is the left Windows key. I think the problem may be that your code is only holding those keys down for microseconds. You need to give the computer a little bit of time to recognize the keypresses because it's expecting a human using a keyboard, not a microcontroller running at 16MHz. Try adding a delay before `Keyboard.releaseAll();`.
> 0 votes

# Answer
I know it's a late answer, but you can use to open the run window:

Keyboard.press(KEY\_LEFT\_GUI); Keyboard.press(114); Keyboard.releaseAll();

And yes, as per1234 says, KEY\_LEFT\_GUI is the left windows key
> 1 votes

---
Tags: arduino-micro, atmega32u4
---


title: 5v relay module

text:
# Question
Title: 5v relay module
I'm using NodeMCU with 5v relay module. my problem is that when the output of NodeMCU is high the relay is off. Which means that the relay module work in an inverted way so how can I treat this issue while when the output is high the relay become on?

# Answer
try changing the connection in relay module

u can see that there are three pins in a relay. when you connect the output from the NodeMCU between the common and the NC(normally closed) pin of relay, makes the switch close and current flows (when the relay is not powered.) try connecting the output in between common and NO(normally opened). when you connect your output between common and NO the current will only flow when the relay is powered up.
> 2 votes

# Answer
Software solution:

The easiest way is to drive the pin inverted by the NodeMCU, so set it LOW when you want the relay to be activated, otherwise set it HIGH.

Example:

```
void setup()
{
  pinMode(13, OUTPUT);          // sets the digital pin 13 as output
  digitalWrite(13, HIGH);       // switches OFF the relay
}

void loop()
{
  digitalWrite(13, LOW);        // switches ON the relay
  delay(1000);                  // waits for a second
  digitalWrite(13, HIGH);       // switches OFF the relay
  delay(1000);                  // waits for a second
}

```

Hardware solution:

A hardware solution is to use an inverter IC, but since you use a microcontroller it would be only cost space, time and money.
> 0 votes

---
Tags: nodemcu, relay
---


# Question
Title: Trying to read from AD5934 using Arduino on I2C
I'm trying to read a block of bytes from an AD5934 Impedance converter (PDF) using I2C.

This is my code so far

Preamble:

```
#define AD5934_Address                    0xD
#define AD5934_Start_Frequency            0x82
#define AD5934_Block_Read                 0b10100001
#define AD5934_Address_Pointer            0b10110000

```

Loop:

```
void loop() {
  readAD5934(AD5934_Start_Frequency, test, 3);
}

```

Read Function:

```
byte readAD5934 (int address, long int  data, int len) {
  byte err = 0, counter;

  if (len > 32)
    return 0xFF;

  else if (len > 1) {
    // Part ONE
    Wire.beginTransmission(AD5934_Address);
    Wire.write((byte) AD5934_Address_Pointer);
    Wire.write((byte) address);

    err = Wire.endTransmission();

    // Part TWO
    Wire.beginTransmission(AD5934_Address);
    Wire.write((byte) AD5934_Block_Read);
    Wire.write(len);

    // Part THREE
    Wire.requestFrom(AD5934_Address, len);
    StartHigh = Wire.read();
    StartMed = Wire.read();
    StartLow = Wire.read();
    err = Wire.endTransmission();
  }
return err;
}

```

For some reason, the Arduino tries to read the three bytes before Part TWO is executed.

I'm aware that I'm ending the I2C transmission after the requestFrom. The datasheet for AD5934 describes how to read a block of bytes on page 26. It does not show a STOP CONDITION before the end.

The oscilloscope shows

START 0001101 WRITE ACK 10110000 ACK 10000010 ACK STOP **START 0001101 READ ACK 00000001 ACK 11000111 ACK 11111111 NACK STOP** START 0001101 WRITE ACK 10100001 ACK 00000011 ACK STOP

Short: S 0x0D W A 0xB0 A 0x82 A P **S 0x0D R A 0x01 0xC7 0xFF NA P** S 0x0D W A 0xA1 A 0x03 A P

The highlighted part (requestFrom and three Wire.read()) should be at the end.

I've spent a long time trying to figure this out, any help would be very much appreciated.

PS. Working on a Sparkfun Pro Micro 5V

# Answer
I think you should re-see AD5934x datasheet.

To read data from AD5934, we have three ways:

* read single byte
* read block
* using pointer command

---

If you want to read multi byte, you can refer to my way:

```
unsigned long GetRegisterValue(unsigned char regAddr, unsigned char len)
{
    unsigned long regValue = 0;
    unsigned char index;
    unsigned char wrData[2] = {0,0};
    unsigned char rdData[2] = {0,0};

    for (index = 0; index < len; index++)
    {
        wrData[0] = 0xB0; //assign pointer cmd
        wrData[1] = regAddr + index;
        I2C_Write(AD5934_ADDR, wrData, 2);
        rdData[0] = 0xff;
        I2C_Read(AD5934_ADDR, rdData, 1);
        regValue <<= 8;
        regValue += rdData[0];
    }

    return regValue;
}

```
> 1 votes

---
Tags: i2c, arduino-micro
---


title: ESP8266 Arduino and Rotary Encoder

text:
# Question
Title: ESP8266 Arduino and Rotary Encoder
I'm trying to use the sketch bellow to work with my WeMos D1 mini (ESP8266 Arduino platform) together with Rotary Encoder KY-040 or MJKDZ, and it's not working for some reason, but the same sketch is working great on the Arduino Uno (with different pin assignment - 2, 3, 4).

Can someone explain to me what is the issue with the sketch?

```
const int PinA = 14; // Used for generating interrupts using CLK signal
const int PinB = 12; // Used for reading DT signal
const int PinSW = 13; // Used for the push button switch

int lCnt = 0; // Keep track of last rotary value
volatile int vPos = 0; // Updated by the ISR (Interrupt Service Routine)

void isr_event ()  {
  static unsigned long lIsrTmr = 0; // Last Interrupt time
  unsigned long IsrTmr = millis(); // Interrupt time

  // If interrupts come faster than 5ms, assume it's a bounce and ignore
  if (IsrTmr - lIsrTmr > 5) {
    if (digitalRead(PinB) == LOW)
    {
      vPos++ ; // Could be +5 or +10
    }
    else {
      vPos-- ; // Could be -5 or -10
    }

    // Restrict value from 0 to +100
    vPos = min(10, max(0, vPos));

    // Keep track of when we were here last (no more than every 5ms)
    lIsrTmr = IsrTmr;
  }
}

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

  // Rotary pulses are INPUTs
  pinMode(PinA, INPUT);
  pinMode(PinB, INPUT);

  pinMode(PinSW, INPUT_PULLUP); // Switch is floating so use the in-built PULLUP so we don't need a resistor

  attachInterrupt(digitalPinToInterrupt(PinA), isr_event, LOW); // Attach the routine to service the interrupts

  Serial.println(F("Starting..."));  // Ready to go!
}

void loop()
{

  // Is someone pressing the rotary switch?
  if ((!digitalRead(PinSW))) {
    vPos = 0;
    while (!digitalRead(PinSW))
      delay(10);
  }

  // If the current rotary switch position has changed then update everything
  if (vPos != lCnt) {
    // Write out to serial monitor the value and direction
    Serial.println(vPos);
    // Keep track of this new value
    lCnt = vPos ;
  }
}

```

# Answer
The ESP8266 doesn't know what a "LOW" interrupt is. You will have to change your code to use FALLING, RISING or CHANGE interrupts only.
> 1 votes

---
Tags: arduino-uno, esp8266, interrupt, rotary-encoder
---


title: Serial.print only showing "0"

text:
# Question
Title: Serial.print only showing "0"
This is my code for a timer. My goal is to increment the `count` at every 1 sec.

```
unsigned int count = 0;
int wait = 1000;

void setup()
{
  Serial.begin(9600);
}
void loop()
{
  long current = millis();
  if((millis() - current) == wait)
  {
    count++;
  }
  Serial.println(count);
}

```

but the serial monitor is only showing zeroes. what to do?

# Answer
> 3 votes
`millis() - current` will always be `0` because `current` is always set to the value of `millis()` right before you compare it. So it will never equal `wait` (0 is not 1000), so `count` never increments.

---
Tags: arduino-uno
---


title: Testing network of SIM900A

text:
# Question
Title: Testing network of SIM900A
Do I have to connect RX and TX of SIM900A with any pins (say TX, RX of Arduino) for network purpose? Shouldn't the network status LED blink slower after connecting the power sources with SIM900A?

# Answer
> 2 votes
To answer your questions in turn:

* It is not necessary to connect to the Arduino solely for the purpose of making a GSM network connection.
* When the SIM900A is powered on, the Status LED will blink once every second.
* When the GSM connection has been established the Status LED of the SIM900A will blink every 3 seconds.

Follow this guide, from Tutorial to interface GSM SIM900A with Arduino:

> ### Initial startup of SIM900
>
> 1. Insert your SIM card to GSM module and lock it.
> 2. Power up the SIM900A by connecting it to Arduino's 5V and GND pins
> 3. Connect the Antenna
> 4. Now wait for some time (say 1 minute) and make note of the blinking rate of ‘status LED’ or ‘network LED’ (D6). The GSM module will take some time to establish connection with mobile network
> 5. Once the connection is established successfully, the *status/network LED will blink continuously every 3 seconds*. You may try making a call to the mobile number of the sim card inside GSM module. If you hear a ring back, the GSM module has successfully established network connection.
>
> ### Connection to Arduino
>
> The SIM900A has the following pins:
>
> * `3VR`;
> * `3VT`;
> * `5VR`;
> * `5VT`;
> * `VCC`, and;
> * `GND`.
>
> For serial communication between the Arduino and SIM900A module. you have to connect:
>
> * SIM900A `5VT` to Arduino `D9` and;
> * SIM900A `5VR` to Arduino `D10`
>
> ### Basic Communication
>
> 1. To change SMS sending mode: `AT+CMGF=1`
>
> ```
> mySerial.println("AT+CMGF=1");
>
> ```
> 2. To read SMS in text mode: `AT+CNMI=2,2,0,0,0`
>
> ```
> mySerial.println("AT+CNMI=2,2,0,0,0");
>
> ```
> 3. To make a call: `ATD+60XXXXXXXXX` (replace X with number you want to call, change +60 to your country code)
>
> ```
> mySerial.println("ATD+60XXXXXXXXX;");
>
> ```
> 4. To disconnect/hangup call: `ATH`
>
> ```
> mySerial.println("ATH");
>
> ```
> 5. To redial: `ATDL`
>
> ```
> mySerial.println("ATDL");
>
> ```
> 6. To receive a phone call: `ATA`
>
> ```
> mySerial.println("ATA");
>
> ```

---
Tags: arduino-uno, network
---


# Question
Title: Connecting an ESP8266 to WiFi without hardcoding the credentials
I've recently achieved connecting my board, an ESP8266 to my local WiFi, but I've had to hardcode the credentials to the code, just like in 99% of the tutorials online. My code looks somewhat like this:

```
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>

#define USE_SERIAL Serial

ESP8266WiFiMulti WiFiMulti;

void setup() {

    USE_SERIAL.begin(115200);

    WiFi.mode(WIFI_STA);
    WiFiMulti.addAP("SSID", "Password");

}

void loop() {
    // Some more code
}

```

The thing is, I would like to know if there is some way to parametrize the credentials so I don't have to recompile and upload the code to the board everytime my WiFi password changes.

One of my ideas was to connect all the boards to a local router without actual connection to the internet and have a server in that same LAN manage the sensitive information, not the boards. That would allow me to manage credentials properly. Does this even make sense?

# Answer
> 1 votes
The common way to do this is to put the ESP8266 into AP (Access Point) mode and then serve a web page with the configuration interface.

To make it even easier, you can create a captive portal so that the user doesn't need to open a specific IP address in their browser. The captive portal will cause the configuration page to be loaded no matter what address they open.

A popular Arduino library that makes this all very easy is WiFiManager:

https://github.com/tzapu/WiFiManager

---
Tags: esp8266, wifi
---


# Question
Title: Is the SIM900 3G? Or is the SIM900A able to connect to 3G?
I would like to state that I am not familiar with the whole cellular connection thing. But I was wondering if the SIM900/or/SIM900A is 3G and will work with PTel Mobile.

I need this Arduino to be able to travel and needs to connect to every PTel's tower. Will I be able to connect to 3G or only the 2G and the 1G networks?

# Answer
First of all if you are in USA you cannot use SIM 900A since it supports only Dual frequency bands.(900,1800 MHz)it supports only Asian region countries.

According to Wikipedia, PTel Mobile supports only GSM 850/1900 frequencies. so SIM 900 supports( 850,900,1800,1900 MHz ) you must use SIM900

Considering about the speed you cannot obtain 3g, 4g speed since GSM Shield(SIM900) provides maximum of GPRS class 10: max. 85.6 kbps (downlink) so,

It will able to connect but cannot get such speed in 3g and 4g.
> 3 votes

# Answer
It will not be able to connect to a 3G or 4G network. There has to be a 2G network / support and that support is getting less.
> 0 votes

---
Tags: shields, gsm, communication
---


title: SerialPort Node.js stuck in 'Error'

text:
# Question
Title: SerialPort Node.js stuck in 'Error'
I am trying to get my Arduino to send data to my computer using Node.js Serial port. Everything compiles, my Arduino is working well and sending data in the serial monitor, but the program always goes into `myPort.on('close')`, and I can't figure out why.

```
//import serial port js package
const SerialPort = require('serialport');

//opening a port
var myPort = new SerialPort("/dev/ttyS2", {
  baudRate: 9600,
  //parser: SerialPort.parsers.raw
});

//how to pass the readline
const Readline = SerialPort.parsers.Readline;
const parser = new Readline();
myPort.pipe(parser);

myPort.on("open", onPortOpen);
myPort.on("data" , onData);
myPort.on("close" , onClose);
myPort.on("error" , onError);

function onPortOpen(){
    console.log("Port open");
}

function onData(data){
    console.log("data transfer completed..");
    console.log(data);
}
function onError(){
    console.log("Error. something went wrong..")
}
function onClose(){
    console.log("Port is closed. Communication terminated");
}

```

Would anyone know what are the potential reasons? I double checked my port and it really is `COM3`, therefore, `/dev/ttyS2` for Windows 10.

# Answer
I see two issues in your code. I cannot say for sure they are related to the problem you experience, but anyway:

1. The `Readline` parser's line terminator defaults to `"\n"`, whereas Arduino's `Serial.println()` uses `"\r\n"`. In order to get the line terminators match, you should invoke the `Readline` constructor with `{ delimiter: "\r\n" }` as an argument.
2. Piping the flow through the parser returns a new stream. You should watch for data events on *that* stream rather the original port.

Thus I suggest you try:

```
const parser = new Readline({ delimiter: "\r\n" });
const parsedStream = myPort.pipe(parser);

myPort.on("open", onPortOpen);
parsedStream.on("data" , onData);
...

```
> 1 votes

---
Tags: arduino-uno, serial, temperature-sensor, node.js
---


title: How to get PPM value from MQ-3?

text:
# Question
Title: How to get PPM value from MQ-3?
I tried to build project to detect alcohol with Arduino Uno and an MQ-3 Alcohol sensor.

I already have the `R0` value, but I faced problem here: I don't know how to convert it to PPM or BAC. I already tried some code from tutorial for convert it to BAC but when I gave the sensor alcohol the code gives me a value of `0.00`, and I don't know why.

Here is the code to find `R0` value:

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

void loop()
{
    float sensor_volt;
    float RS; //  Get the value of RS via in a clear air
    float R0;  // Get the value of R0 via in Alcohol
    float sensorValue;

    for(int i = 0 ; i < 100 ; i++)
    {
        sensorValue = sensorValue + analogRead(A0);
    }

    sensorValue = sensorValue/100.0;     //get average of reading
    sensor_volt = sensorValue/1024*5.0;
    RS = (5.0-sensor_volt)/sensor_volt; //
    R0 = RS/60.0; // 60 is found using interpolation
    Serial.print("R0 = ");
    Serial.println(R0);
    delay(1000);
}

```

Here is the code to determine `BAC`:

```
float R0= 0.28;
void setup() {
  Serial.begin(9600);
}

void loop() {
  float sensor_volt;
    float RS_gas; // Get value of RS in a GAS
    float ratio; // Get ratio RS_GAS/RS_air
    float BAC;
    int sensorValue = analogRead(A0);
    sensor_volt=(float)sensorValue/1024*5.0;
    RS_gas = (5.0-sensor_volt)/sensor_volt; // omit *RL

   /*-Replace the name "R0" with the value of R0 in the demo of First Test -*/
    ratio = RS_gas/R0;  // ratio = RS/R0
    float a = pow(ratio, 2);
    float b = ratio/10;
    BAC = (0.1896*a) - (8.6178*b) + 1.0792 ;  //BAC in mg/L
    Serial.print("BAC = ");
    Serial.println(BAC*0.0001);  //convert to g/dL
    Serial.print("\n\n");
    delay(1000);
}

```

I would to know what's wrong with the code, and if you know how to convert the `R0` values to PPM, please tell me.

# Answer
A series of `if()` statements and some simple division should be able to provide you with your PPM results.

From the datasheet, Alcohol Gas Sensor（Model：MQ-3), figure 5 shows the *sensitivity curve*:

It can be seen here

that there are three regions that the curve can be broken into:

1. The relationship is linearly proportional between 2.25 V and 3.25 V
2. Between 3.25 V and 3.8 V there is a curve
3. The relationship is linearly proportional between 3.8 V to 4.25 V

The slope of the straight line regions described in points 1 and 3 can be represented by the use of a constant and the PPM value by a simple division of the voltage by the constant.

The curve from the second part could be:

* approximated by a straight line (thus, once again, using a constant), for simplicity, or;
* more accurately, using a lookup table.

Using a straight line approximation for the curve (shown in lurid green), the graph becomes:

To determine the constant for the three lines simply take two points on each line and use:

> (y2 \- y1) / (x2 \- x1)

So for region one, assuming (by approximation, 3 V corresponds to 100 ppm and 2.5 V corresponds to 85 ppm (my eye sight may be slightly off here), the slope is

```
(3 - 2.5)/(100-80) = 0.5/20 = 0.025

```

You can calculate the constants for regions two and three in a similar manner (if using a straight line approximation for region two).

Therefore the code would be alomg the lines of

```
const double kRegionOne = 0.025;   // region one constant
const double kRegionTwo = ???;     // region two constant
const double kRegionThree = ???;   // region three constant

int ppm;                           // ppm result

/*
 * your code here
 * ...
 */

if ((sensor_volt < 3.25) && (sensor_volt >= 2.25)) {
  ppm = sensor_volt/kRegionOne;    // we are in region 1
} else if ((sensor_volt < 3.8) && (sensor_volt >= 3.25)) {
  ppm = sensor_volt/kRegionTwo;    // we are in region 2
} else if (sensor_volt >= 3.8) {
  ppm = sensor_volt/kRegionThree;  // we are in region 3
}

```

If you wish to be more accurate then use a lookup table for region two, as jsotola states in their comment.
> 4 votes

---
Tags: arduino-uno, sensors
---


# Question
Title: C++ Undefined reference to 'Class:Function()'
I have these files:

* `Project.ino`
* `Sensor.h`
* `Sensor.cpp`
* `IMU/L3G.h`
* `IMU/L3G.cpp`

`Sensor.h`

```
#ifndef Sensor_h
#define Sensor_h

#include <EEPROM.h>
#include "IMU/L3G.h"

#define CUTOFF_FREQ 30
#define FREQ 400

class Sensor {
public:
    Sensor();
    ~Sensor();
    void Init(void);

pivate:
    L3G gyro;
};
#endif

```

`Sensor.cpp`

```
#include "Sensor.h"

Sensor::Sensor()
{

}
Sensor::~Sensor()
{

}

void Sensor::Init(void)
{
  if (!gyro.init())
  {
    Serial.println("Failed to autodetect gyro type!");
    while (1);
  }
  gyro.enableDefault();
}

```

`Project.ino`

```
#include <i2c_t3.h>
#include <EEPROM.h>
#include <Servo.h>
#include "Sensor.h"

Sensor sensor = Sensor();

void setup() {

  sensor.Init();
}

```

I got this error

```
/var/folders/8q/rbt7zf3d28b3k9t6d24k5sn00000gn/T/arduino_build_748953/sketch/Sensor.cpp.o: In function `Sensor::Init()':
/var/folders/8q/rbt7zf3d28b3k9t6d24k5sn00000gn/T/arduino_build_748953/sketch/Sensor.cpp:15: undefined reference to `L3G::init(unsigned char, unsigned char)'
/var/folders/8q/rbt7zf3d28b3k9t6d24k5sn00000gn/T/arduino_build_748953/sketch/Sensor.cpp:20: undefined reference to `L3G::enableDefault()'

```

So, what is wrong?

# Answer
As Juraj rightly points out, you have a typo, which should give you the following compile time error:

```
In file included from sketch/Sensor.cpp:1:0:
Sensor.h:17: error: 'pivate' does not name a type
 pivate:
 ^

```

Here is the correct code for `Sensor.h`

```
#ifndef Sensor_h
#define Sensor_h

#include <EEPROM.h>
#include "IMU/L3G.h"

#define CUTOFF_FREQ 30
#define FREQ 400

class Sensor {
public:
    Sensor();
    ~Sensor();
    void Init(void);

private:
    L3G gyro;
};
#endif

```

Using Arduino IDE 1.8.5 with Teensyduino 1.42 with:

However, once the typo has been corrected, as above, then I too can reproduce your problem (sort of), with these link errors:

```
/var/folders/kp/xv3y9k114yq2_64pf8zwh76h0000gp/T/arduino_build_136680/sketch/Sensor.cpp.o: In function `Sensor::Sensor()':
/var/folders/kp/xv3y9k114yq2_64pf8zwh76h0000gp/T/arduino_build_136680/sketch/Sensor.cpp:3: undefined reference to `L3G::L3G()'
/var/folders/kp/xv3y9k114yq2_64pf8zwh76h0000gp/T/arduino_build_136680/sketch/Sensor.cpp.o: In function `Sensor::Init()':
/var/folders/kp/xv3y9k114yq2_64pf8zwh76h0000gp/T/arduino_build_136680/sketch/Sensor.cpp:14: undefined reference to `L3G::init(L3G::deviceType, L3G::sa0State)'
/var/folders/kp/xv3y9k114yq2_64pf8zwh76h0000gp/T/arduino_build_136680/sketch/Sensor.cpp:19: undefined reference to `L3G::enableDefault()'
/var/folders/kp/xv3y9k114yq2_64pf8zwh76h0000gp/T/arduino_build_136680/core/core.a(main.cpp.o): In function `main':
/Volumes/Home/Users/user/Local_Apps/Arduino/Arduino1.8.5-Teensy.app/Contents/Java/hardware/teensy/avr/cores/teensy3/main.cpp:53: undefined reference to `loop'
collect2: error: ld returned 1 exit status
Multiple libraries were found for "Servo.h"
 Used: /Volumes/Home/Users/user/Local_Apps/Arduino/Arduino1.8.5-Teensy.app/Contents/Java/hardware/teensy/avr/libraries/Servo
 Not used: /Volumes/Home/Users/user/Local_Apps/Arduino/Arduino1.8.5-Teensy.app/Contents/Java/libraries/Servo
Error compiling for board Teensy 3.5.

```

You are probably getting this error, because you have placed the files `L3G.cpp` and `L3G.h` in a folder called `IMU` in the same folder as your `.ino` file. This causes the undefined error, as, while the IDE sees the declaration in the `L3G.h` file, the IDE can not find the definition in the `L3G.cpp` file.

This is easy to resolve.

If you download the `l3g-arduino-master.zip` file from https://github.com/pololu/l3g-arduino, and from within the Arduino IDE you then add the zipped up L3G library to the Arduino library, using `Sketch ► Include Library ► Add. ZIP Library...` and then change the line

```
#include "IMU/L3G.h"

```

to

```
#include <L3G.h>

```

Then it should compile and link without a problem
> 2 votes

---
Tags: c++, teensy, class
---


# Question
Title: How to make 1 second delay more accurate?
I have written two (1 second) delay programs.

The first program as follows:

```
void setup()
{
Serial.begin(9600);
TCCR1A = 0;
TCCR1B |= (1<<CS12);
TCCR1B &= ~(1<<CS11);
TCCR1B &= ~(1<<CS10);
TCNT1 = 3036;
TIMSK1 |= (1<<TOIE1);
}

ISR(TIMER1_OVF_vect)
{
  Serial.println(millis());
  TCNT1 = 3036;
}
void loop()
{
}

```

Whose output is as follows:

```
999  // 1 sec
1999 // 2 sec
3000
3999
5000
6000
7001
8000
9000
10001
.
.
.
58012
59013
60013
61012
62013 //60 sec

```

It has an error of around `13 ms` at 1 minute and at 1 hour it will be `780 ms` and in one day it will be around `19 seconds`.

The second program is as follows:

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

void loop() {
  Serial.println(millis());
  delay(1000);
}

```

Whose output is near about as same as the first one's.

Is there any way to decrease the error and make it more precise? So that I can use it in my Arduino based stopwatch?

# Answer
Majenko is perfectly right: you cannot expect much accuracy from an Arduino clocked by a ceramic resonator. Typical drift is of the order of 1,000 ppm, and is affected by temperature and aging. You can, however, get a delay which is pretty close to the CPU's idea of one second. In other words, you can get something that is really close to a perfect period of 16,000,000 CPU cycles. If that is what you want, your best bet is to use a timer.

In your overflow ISR, you wrote:

> `Serial.println(millis());`

There are two issues here. The first is the use of `Serial.println()` within an ISR. This should normally avoided: since `Serial` relies on interrupts, using it with interrupts disabled can lock your program if you ever fill the output buffer. In this particular instance, it happens to be safe, because at this rate you are never going to fill the output buffer anyway. However, while it can be OK to do that in a small test program like yours, I would advise you against doing it in production code.

The other issue is the use of `millis()`. This function does not provide true millisecond resolution: it is a counter that is updated every 1024 µs. Every now a then it is updated by 2 ms at once in order to compensate for the drift. Thus, you should think of `millis()` as being good to within ±2 ms. If you need anything better, use `micros()`.

> `TCNT1 = 3036;`

This should be avoided. Dispatching an interrupt takes time, and this time depends on whether there is already an interrupt handler (or other critical section) running. If the timer happens to increment after the interrupt fires but before you have time to execute the line above, then you miss a timer tic. It has been suggested to you to move this line before the `Serial.println()`. That would certainly reduce the risk, but it will not completely prevent it.

The right thing to do is to *never* reset a timer if you want it to have time continuity. Instead, set it to CTC mode (clear timer on compare match) and let it reset itself when it reaches a value of your choosing. In this case, you would have it repeatedly count from 0 to 62,499 instead of from 3,036 to 65,535.

Here is a modified version of your program illustrating the points above:

```
void setup()
{
    Serial.begin(9600);
    TCCR1A = 0;            // undo the Arduino's timer configuration
    TCCR1B = 0;            // ditto
    TCNT1  = 0;            // reset timer
    OCR1A  = 62500 - 1;    // period = 62500 clock tics
    TCCR1B = _BV(WGM12)    // CTC mode, TOP = OCR1A
           | _BV(CS12);    // clock at F_CPU/256
    TIMSK1 = _BV(OCIE1A);  // interrupt on output compare A
}

ISR(TIMER1_COMPA_vect)
{
    // OK in test code, don't do this in production code.
    Serial.println(micros());
}

void loop(){}

```

The output is as follows;

```
1000048
2000048
3000048
...
58000048
59000048
60000048  // 60 seconds

```
> 5 votes

# Answer
Your biggest problem is that you don't know what a second is. You have no reliable time-base to measure time against.

`millis()` is not accurate. You can't rely on that giving you a precise time - otherwise, something as simple as:

```
uint32_t secs = 0;

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

void loop() {
    if (millis() / 1000 > secs) {
        secs = millis() / 1000;
        Serial.println(millis());
    }
}

```

would give you a precise 1000 millisecond "delay". However, all that gives you is a precise "Arduino 1000 millisecond" delay. That is - it triggers on the rollover between 1000 millisecond blocks where 1 millisecond is whatever the Arduino's `millis()` function thinks 1 millisecond is.

While it may *appear* to be accurate, in that it would give you round numbers "1000, 2000, 3000, 4000" etc, compare that to an external clock and you would find it's actually drifting just as bad (if not worse) than your existing methods.

The problem is, since what you are measuring the drift against is itself drifting, your measurements are completely meaningless.

If you require an exact 1-second pulse with near zero drift you will have to use an external clock source. The most accurate would be GPS. Many GPS modules have the ability to output a 1-second pulse which is synchronised to the GPS clock.

An RTC module would improve accuracy somewhat as well - again most of those have a 1Hz square wave output that can be used to synchronise things - however, even those aren't 100% accurate and rely on the accuracy of the attached crystal. They're more accurate than the Arduino's ceramic resonator, though.
> 3 votes

# Answer
I never would have thought this day would come, but I disagree with @Majenko and @EdgarBonet.

The source of your clock is important. **If** the Arduino resonator is accurate enough, then you can use millis(). If you want more accuracy, then you can use a rtc like the ds3231. The ds3231 is temperature compensated for more accuracy. If you want something even better then you can use gps or a internet time server or even a long wave radio signal time server.

When you need a 1 second timer as the basis for a clock or stopwatch, then you can start by using millis() which is based upon the 16MHz resonator. The millis() is compensated with a offset, it will not drift. It runs 100% perfect with the same accuracy as the resonator. Use the blink without delay example and change the increment of previousMillis to this:

```
if (currentMillis - previousMillis >= interval) {
  // increment the previousMillis with the interval
  previousMillis += interval;

```

That way the one second interval will stay in sync with the time, even when there is a big delay now and then in the sketch.

You will not get more accuracy by using a internal timer.

Some Arduino clones have a crystal instead of a resonator. If you use one of those clones with a crystal and use millis as I mentioned above, then your timing is as accurate as the crystal. When you build a clock with that, it might run a few minutes per year out of sync with the real time.
> 0 votes

---
Tags: arduino-uno, timers
---


title: Power RFID module using GPIO

text:
# Question
Title: Power RFID module using GPIO
I am building an ESP8266 device that uses RFID but need to conserve battery power.

The ESP is a Wemos D1 Mini and the RFID module is a RC522 (still waiting for it to arrive), which needs 3.3 V. I'm powering the ESP with a battery shield and 3.3 V.

But I don't want to connect the RFID module directly to the battery shield because it will be sucking voltage constantly. Instead, I want to be able to control its power using the ESP.

So I thought the easiest would be simply to connect the RC522's 3v3 line to one of the ESP's available GPIO pins, set it to output, and when I need RFID, set the GPIO pin high, to turn on the RFID module.

Is this an acceptable solution, or do I need to wire in a transistor and capacitor somewhere?

# Answer
No, this is not an acceptable solution. The RC522 needs in excess of 100mA to operate, and an ESP8266's GPIO pin can only supply 12mA maximum. You will damage the ESP8266.

You need to use a P-channel MOSFET with the gate pulled HIGH as a high side switch.

simulate this circuit – Schematic created using CircuitLab

Set the GPIO to LOW to turn on the MOSFET. Set it HIGH or to INPUT to turn off the MOSFET.

---

Note 1: Set the communication IO pins to INPUT before powering off otherwise they could back-power the target device through the ESD diodes in the IO pins.
> 2 votes

---
Tags: esp8266, power, rfid
---


title: Arduino UNO And SD Card Custom csPin

text:
# Question
Title: Arduino UNO And SD Card Custom csPin
I've connected SD card module to `Arduino UNO`. I want to use `PIN 10` for `PWM DC motor control` and because of that, I've connected `CS pin` directly to another pin (A3).

SD card is working properly, but after calling `SD.begin(A3)`, it set `PIN 10` to `HIGH`! Immediately after `SD.begin(A3)` and set that pin to `LOW`, but meanwhile the motor took a small rotation.

I've digged into `SD.cpp` and `Sd2Card.cpp`, but couldn't find where this problem occured!

Any help appreciated....

**The Solution:**
Simply call `SD.begin(-1)` and it doesn't touch `PIN10`. Hope helps somebody else!

# Answer
Pin 10 is special. It's the *hardware* chip select pin for SPI. It is integral to the SPI peripheral in the chip.

That pin *must* be an OUTPUT for SPI to operate as master, or INPUT for it to operate as a slave.

It's a stupid design decision by Atmel if you ask me, but there you go. So basically trying to use SPI at the same time as PWM on pin 10 is "undefined" and to be avoided.

Use a different pin for PWM or if you need more than there are PWM pins available then consider an external PWM control chip.

---

Just probing around to get more detail on exactly how it all works, this is what I have found:

* `digitalWrite()` explicitly disables PWM on a pin.
* The direction of pin 10 defines the SPI operation as master or slave.
* `analogWrite()` sets `pinMode(OUTPUT)`.
* The SD library calls `pinMode(OUTPUT)` and `digitalWrite(HIGH)` on pin 10.

This means that:

* `SD.begin()` will terminate any existing PWM on pin 10.
* Using PWM on pin 10 will force the pin to output rendering SPI slave mode impossible

You *should* be able to use PWM on pin 10 if, and only if:

* You use `analogWrite()` *after* using `SD.begin()`, and
* You never want to use SPI slave mode.
> 3 votes

---
Tags: sd-card, sd, custom
---


title: Convert from 3 V to 5 V

text:
# Question
Title: Convert from 3 V to 5 V
I'm new to Arduino, electronics, and this forum.

I have made up a little project that connects an HC-SR04 ultrasonic range detector, and displays the distance on a 4 digit, 7 segment LED display.

When I have it plugged into my laptop for power, it runs beautifully on an Uno board.

But I want to mount all this in a Nerf gun (Nerf N-Strike Elite Firestrike) using a Nano board.

The Nerf gun has a built in "laser" (red light) that is powered by 2 x AAA batteries, which makes 3 V, I think. I want to rig this up so that pulling the laser/light trigger also triggers the range detector and display.

I want to run the range sensor and the display off the Nerf guns batteries, but they both use 5 V. Is there a way to do this? Or do I need a separate 5 V power supply?

# Answer
> 3 votes
You may want to use a boost converter which is a device that can step up voltage.

You can get them from eBay for around $US 2.

---

As Chris Stratton pointed out in a comment, the boost converter may run your batteries down quite quickly. Let's say you need 200 mA for your Uno, sensor and LEDs. At 5V power that is 1W of power (`0.200 * 5`).

However to get 1W from 3V you would consume 333 mA (`0.333 * 3`). Then take into account that the converters are not completely efficient. Let's say the converter has 90% efficiency. Then you need to multiply the current by the inverse of the efficiency, that is: `0.333 mA / 0.9 = 0.37 mA`.

Another factor is the battery type. If you use NiCad batteries their nominal voltage is closer to 1.2V than 1.5V, especially after you have been using them for a bit. Ditto for NiMh batteries.

Reworking the above for 2 * 1.2V (2.4V) we see that the current will be:

```
1W / 2.4V = 0.4167A
0.4167A / 0.9 = 0.463A (allowing for 90% efficiency)

```

Now it potentially draws close to half an amp when active. Your batteries might not be able to handle that for long.

# Answer
> 1 votes
Just to suggest an alternative, and more energy efficient, solution...

There appear to be newer versions of the HC-SR04 on the market that support 3.3V, such as the HC-SR04 v2 - Low Cost Ultrasonic Sensor (3V to 5V Supply).

So you could use an Arduino Pro Mini designed to run at 3V in conjunction with the 3.3 V HC-SR04, and run it straight off your nerf gun's power supply.

---

However, it might be worth taking these new versions with a pinch of salt, as modules seem to vary from one to another, see Re: Do HC-SR04 5V rangefinder sensors work in 3V battery mode?

> I have a MKRFOX1200 working with HC-SR04 and it works fine. It is stated to work only at 5v but its fine with 3V. But I have another one (SF-SR02) with a higher range (6meters) and this one doesnt get any further than 1 or 2 meters under 3V. If I use the 5V for VCC while running on USB, it reaches full range. Digital inputs seem to be more tolerant than they state for 5V signals.. (although I'm not advising to do so!!)

An extremely useful comparison of these modules (the first generation) running at both 3.3 and 5 V can be seen here, Re: Ultra cheap ultrasonics, and a bit of a challenge:

3V3

5V

Notwithstanding, the newer versions of the HC-SR04 may have an improved response.

# Answer
> 0 votes
Arduino nano also have 5v-3.3v voltage regulator so you can power all this with only one power supply (power your arduino nano with 6x AAA batteries) and then just connect your nerf gun power with arduino nano 3.3v pin, it will work just fine............ :)

---
Tags: voltage-level, hc-sr04, voltage, 7-segment
---


# Question
Title: Problem with sending a POST request using the WiFiEsp library
I'm using an ESP8266 version 1 with the WiFiEsp library to connect to WiFi, and that works just fine.

I'm setting up the device using the same code as in the example `WebClientRepeating`.

I need to send a POST request instead of a GET request, but I can't get it to work as I want. If I create my POST request like this, it works just fine:

```
if (client.connect(server, 3005)) {
  Serial.println("Connecting...");

  // send the HTTP POST request
  client.println("POST /open/peripherals HTTP/1.1");
  client.println("Host: 192.168.10.137:3005");
  client.println("User-Agent: Arduino/1.0");
  client.println("Connection: close");
  client.println();

  // note the time that the connection was made
  lastConnectionTime = millis();
}
else {
  // if you couldn't make a connection
  Serial.println("Connection failed");
}

```

I get the response like this:

```
[WiFiEsp] Connecting to 192.168.10.137
Connecting...
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 19
ETag: W/"13-jSAaqMh5E3R94/b2aONzvg"
Date: Sun, 13 Nov 2016 10:20:58 GMT
Connection: close

{"temp":"Testdata"}

```

However, if I try to send some body data in the request it fails:

```
if (client.connect(server, 3005)) {
  Serial.println("Connecting...");

  // send the HTTP POST request
  client.println("POST /open/peripherals HTTP/1.1");
  client.println("Host: 192.168.10.137:3005");
  client.println("User-Agent: Arduino/1.0");
  client.println("Connection: close");
  client.println("Content-Type: application/x-www-form-urlencoded");
  client.println("Content-Length: 16");
  client.println();
  client.println("temperature=22.7");

  // note the time that the connection was made
  lastConnectionTime = millis();
}
else {
  // if you couldn't make a connection
  Serial.println("Connection failed");
}

```

Then the response from serial output is:

```
[WiFiEsp] Connecting to 192.168.10.137
Connecting...
[WiFiEsp] >>> TIMEOUT >>>
[WiFiEsp] Data packet send error (1)
[WiFiEsp] Failed to write to socket 0
[WiFiEsp] Disconnecting  0

```

However, the POST request including the body is received by the Web server just fine, but the response sent to the Arduino I can't read because it shows me an error instead of a proper response. From my webserver the response for the POST call that works and the POST call that fails is the same.

Does anyone knows why this fails when I add `Content-Type`, `Content-Length` and some body data?

Thanks in advance!

# Answer
Your problem is the content you are sending. While this format works well e. g. in Python libraries, this library seems to have a problem with it. I solved it this way, when I happened to face this problem:

```
//all your other code, including the remaining HTTP-Request
String content = "{\"temperature\":\""+String(value)+"\"}";
client.println("Content-Length: 16"); //insert, well, your content length
client.println(content);

```
> 2 votes

# Answer
One major problem seems to exists within the AT firmware of most ESP's. By default, the http headers it sends include **"Connection: close"**. However, the firmware seems to be buggy and unable to cope with the server closing the connection after it sends the response. Thus, in order to be able to get a response back from the target server you need to have **"Connection: keep-alive"** instead. This means you must explicitly add this to your header since **"Connection: close"** will be added if nothing else is said. Also to make life easier for the WifiEsp library you could make sure your server returns an already well-known status string for the library like fx **"SEND OK"**… I'm doing this on a barometer logger that sends data to a MVC Web Api written in C# and it works perfect...

Here's my code:

```
String PostHeader = "POST http://" + server + ":" + String(port) + "/api/values HTTP/1.1\r\n";
PostHeader += "Connection: keep-alive\r\n";
PostHeader += "Content-Type: application/json; charset=utf-8\r\n";
PostHeader += "Host: " + server + ":" + String(port) + "\r\n";
PostHeader += "Content-Length: " + String(jsonString.length()) + "\r\n\r\n";
PostHeader += jsonString;
Serial.println(PostHeader);
client.connect(server.c_str(), port);
client.println(PostHeader);
client.stop();

```

And the full log looks like this:

```
POST http://192.168.10.197:8001/api/values HTTP/1.1
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Host: 192.168.10.197:8001
Content-Length: 144

{"IpAddress":"192.168.10.230","MacAddress":"5c:cf:7f:d9:2f:c8","Temperature":34.6,"Pressure":1007,"Altitude":48.48573,"PressureAtSeaLevel":1007}

[WiFiEsp] Connecting to 192.168.10.197
[WiFiEsp] Disconnecting  3

```

In the file debug.h located in the WifiEsp library source code you could alter a define and get more output to your serial console. Open the file and change

```
#define _ESPLOGLEVEL_ 3

```

to

```
#define _ESPLOGLEVEL_ 4

```

Save the file and recompile/deploy your source code to your Arduino and you will get extensive information about all AT commands the library sends and what the library receives in return.
> 0 votes

---
Tags: arduino-uno, esp8266, web
---


# Question
Title: ESP8266 sends data to the website but doesn't return status
I have problem with my esp8266 it connects to my site and sends 89 bytes of data but does return a confirmation status all i get is SEND OK but i don't get any confirmation from my server

This is my code below

```
 #include <SoftwareSerial.h>
#include<time.h>

SoftwareSerial ESP8266(3, 2); // RX, TX
//DEFINE ALL GLOBAL VAARIABLES HERE
unsigned int timeout_start_val;
char scratch_data_from_ESP[20];//first byte is the length of bytes
char payload[150];
byte payload_size=0, counter=0;
char ip_address[16];
char youtube_subs[10];
char youtube_views[13];
char current_temp[5];
char hi_temp[5];
char lo_temp[5];

//MODES
const char CWMODE = '3';//CWMODE 1=STATION, 2=APMODE, 3=BOTH
const char CIPMUX = '1';//CIPMUX 0=Single Connection, 1=Multiple Connections
//PASS word

const char SSID_ESP[]="Xamel";//"AOTEA TZ";//from constant

const char SSID_KEY[]="cewu5103";//"wyrnC592";

//DEFINE KEYWORDS HERE
const char keyword_OK[]="OK";
const char keyword_FAIL[]="FAIL";
const char keyword_Ready[] = "Ready";
const char keyword_no_change[] = "no change";
const char keyword_blank[] = "#&";
const char keyword_ip[] = "192.";
const char keyword_rn[] = "\r\n";
const char keyword_quote[] = "\"";
const char keyword_carrot[] = ">";
const char keyword_sendok[] = "SEND OK";
const char keyword_linkdisc[] = "Unlink";
const char keyword_CHECKCWMODE[] = "+CWMODE:3";
const char keyword_URL_CONNECTION_ERROR[]="Link typ ERROR";
const char TEST_URL[]="";

const char GET_URL[]="GET /ESP8266_BackEnd/SaveDetail.php?Name=";
int str1=strlen(GET_URL);
const char Name[]="Alex ";
int str2=strlen(Name);

const char TRAILING_URL[]="HTTP/1.1 \\r\\nHost: www.pick2get.com\\r\\n\\r\\n";
int str3=strlen(TRAILING_URL);
int strTotal=str1+str2+str3;

const char AT_CIPSTART[]="AT+CIPSTART=4,\"TCP\",\"pick2get.com\",80 \r\n";
const char AT_CIPSEND[]="AT+CIPSEND=4,";
//function prototype
boolean read_until_ESP(const char keyword1[], int key_size, int timeout_val, byte mode);
void serial_dump_ESP();
boolean setup_ESP(const char SSID_ESP[],const char SSID_KEY);
String url="&School=4D616B6F6E676F";
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  //.print("Total string length");Serial.println(strTotal);

  // set the data rate for the SoftwareSerial port
  ESP8266.begin(9600);
  //

  //Serial.println(read_until_ESP(keyword_URL_CONNECTION_ERROR,sizeof(keyword_URL_CONNECTION_ERROR),5000,0));
  setup_ESP(SSID_ESP,SSID_KEY);

  ESP8266.print(AT_CIPSTART);
  ESP8266.print("");
  delay(1000);

  ESP8266.print(AT_CIPSEND);
  ESP8266.print(strTotal);
  ESP8266.print("\r\n");
  delay(1000);
  ESP8266.print("");
  ESP8266.print(GET_URL);
  ESP8266.print(Name);
  ESP8266.print(TRAILING_URL);
  delay(1000);
  ESP8266.print("");
  //ESP8266.println("&Grade=466F726D204F6E65");
  //ESP8266.println("&DeviceIP=3139322E3136382E302E31");
  //ESP8266.println(TRAILING_URL);

}

void loop() { // run over and over
  byte buffer[300];
  if (ESP8266.available()) {
   Serial.write(ESP8266.read());
  }
  if (Serial.available()) {
    ESP8266.write(Serial.read());
  }
}

```

This is the output generated on the serial monitor

```
ESP CHECK OK
ESP RESET OK
ESP RESET OK
timeout
ESP CWMODE SET FAILED
CWMODE ALREADY SET
SETTING SSID_ESP: Xamel
SETTING SSID_KEY: cewu5103
ESP SSID SET OK DEVICE CONNECTED
CHECKING FOR AN IP ADDRESS
IP ADDRESS = 192.168.4.1
ESP CIPMUX SET
AT+CIPSTART=4,"TCP","pick2get.com",80

OK
Linked
AT+CIPSEND=4,89

> GET /ESP8266_BackEnd/SaveDetail.php?Name=Alex HTTP/1.1 \r\nHost: www.pick2get.com\r\n\r\n
SEND OK

OK
Unlink

```

Can any one please help here.

When adding ESP8266.print("+IPD\r\n"); this is the output i get

```
    ESP CHECK OK
ESP RESET OK
ESP RESET OK
timeout
ESP CWMODE SET FAILED
CWMODE ALREADY SET
SETTING SSID_ESP: Xamel
SETTING SSID_KEY: cewu5103
ESP SSID SET OK DEVICE CONNECTED
CHECKING FOR AN IP ADDRESS
IP ADDRESS = 192.168.4.1
ESP CIPMUX SET
AT+CIPSTART=4,"TCP","pick2get.com",80

AT+CIPSEND=4,89

busy p...

OK
Linked
GET /ESP8266_BackEnd/SaveDetail.php?Name=Alex HTTP/1.1 \r\nHost: www.pick2get.com\r\n\r\n

wrong syntax

ERROR
AT+IPD

ERROR

```

I have managed to fix the lack of server response by removing the \r\n \nd replacing them with regular \r\n\r\n

```
enter code here
const char TRAILING_URL[]="HTTP/1.1 \r\nHost: www.pick2get.com \r\n\r\n";
int str3=strlen(TRAILING_URL);
int strTotal=str1+str2+str3;

const char AT_CIPSTART[]="AT+CIPSTART=4,\"TCP\",\"pick2get.com\",80 \r\n";
const char AT_CIPSEND[]="AT+CIPSEND=4,";

```

At this lines and was able to get a server response

+IPD,4,392:HTTP/1.1 400 Bad Request Date: Tue, 15 May 2018 12:07:08 GMT Server: Apache Content-Length: 226 Connection: close Content-Type: text/html; charset=iso-8859-1

400 Bad Request Bad Request

Your browser sent a request that this server could not understand.

finally i have debugged and fixed all the errors and the code works just fine This and server returns a status 200

turns out it was just me pointing GET request in the wrong folder path with this line code at in the GET\_URL variable

const char GET\_URL\[\]="GET pick2get.com/ESP8266\_BackEnd/SaveDetail.php?Name=";

I replaced with this

const char GET\_URL\[\]="GET /ESP8266\_BackEnd/SaveDetail.php?Name=";

And got the desired result

+IPD,4,166:HTTP/1.1 200 OK Date: Tue, 15 May 2018 12:2249 GMT Server: Apache Upgrade: h2 Connection: Upgrade Transfer-Encoding: chunked Content-Type: text/html

2

OK

+IPD,4,191:16 Connected successfully 5c DATA TRANSMITTED SUCSSEFULLYSTUDENT NAME RECIVED: Alex
STUDENT SCHOOL NAME RECIVED:
3b STUDENT GRADE RECIVED:
DEVICE IP ADDREESS RECIVED:

OK

+IPD,4,42:1f New record created successfully 0 Thanks a lot guys below is the complete working code

```
    /*
  Software serial multple serial test

 Receives from the hardware serial, sends to software serial.
 Receives from software serial, sends to hardware serial.

 The circuit:
 * RX is digital pin 10 (connect to TX of other device)
 * TX is digital pin 11 (connect to RX of other device)

 Note:
 Not all pins on the Mega and Mega 2560 support change interrupts,
 so only the following can be used for RX:
 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69

 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).

 created back in the mists of time
 modified 25 May 2012
 by Nolawi solomon

 */
#include <SoftwareSerial.h>
#include<time.h>

SoftwareSerial ESP8266(3, 2); // RX, TX
//DEFINE ALL GLOBAL VAARIABLES HERE
unsigned int timeout_start_val;
char scratch_data_from_ESP[20];//first byte is the length of bytes
char payload[150];
byte payload_size=0, counter=0;
char ip_address[16];

//MODES
const char CWMODE = '3';//CWMODE 1=STATION, 2=APMODE, 3=BOTH
const char CIPMUX = '1';//CIPMUX 0=Single Connection, 1=Multiple Connections
//PASS word

const char SSID_ESP[]="Xamel";//"AOTEA TZ";//from constant

const char SSID_KEY[]="cewu5103";//"wyrnC592";

//DEFINE KEYWORDS HERE
const char keyword_OK[]="OK";
const char keyword_FAIL[]="FAIL";
const char keyword_Ready[] = "Ready";
const char keyword_no_change[] = "no change";
const char keyword_blank[] = "#&";
const char keyword_ip[] = "192.";
const char keyword_rn[] = "\r\n";
const char keyword_quote[] = "\"";
const char keyword_carrot[] = ">";
const char keyword_sendok[] = "SEND OK";
const char keyword_linkdisc[] = "Unlink";
const char keyword_CHECKCWMODE[] = "+CWMODE:3";
const char keyword_URL_CONNECTION_ERROR[]="Link typ ERROR";
//const char TEST_URL[]="";

const char GET_URL[]="GET /ESP8266_BackEnd/SaveDetail.php?Name=";
int str1=strlen(GET_URL);
const char Name[]="Alex ";
int str2=strlen(Name);

const char TRAILING_URL[]="HTTP/1.1\r\nHost: www.pick2get.com \r\n\r\n";
int str3=strlen(TRAILING_URL);
int strTotal=str1+str2+str3;

const char AT_CIPSTART[]="AT+CIPSTART=4,\"TCP\",\"pick2get.com\",80 \r\n";
const char AT_CIPSEND[]="AT+CIPSEND=4,";
//function prototype
boolean read_until_ESP(const char keyword1[], int key_size, int timeout_val, byte mode);
void serial_dump_ESP();
boolean setup_ESP(const char SSID_ESP[],const char SSID_KEY);
//String url="&School=4D616B6F6E676F";
void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  //.print("Total string length");Serial.println(strTotal);

  // set the data rate for the SoftwareSerial port
  ESP8266.begin(9600);
  //

  //Serial.println(read_until_ESP(keyword_URL_CONNECTION_ERROR,sizeof(keyword_URL_CONNECTION_ERROR),5000,0));
  setup_ESP(SSID_ESP,SSID_KEY);

  ESP8266.print(AT_CIPSTART);
  ESP8266.print("");
  delay(1000);

  ESP8266.print(AT_CIPSEND);
  ESP8266.print(strTotal);
  ESP8266.print("\r\n");
  delay(1000);
  ESP8266.print("");
  ESP8266.print(GET_URL);
  ESP8266.print(Name);
  ESP8266.print(TRAILING_URL);
  //delay(3000);
  //ESP8266.print("");
  //delay(2000);
  //ESP8266.print("\r\n");
  //delay(2000);
  //ESP8266.print("");
  //ESP8266.print("AT+IPD\r\n");
  //ESP8266.println("&Grade=466F726D204F6E65");
  //ESP8266.println("&DeviceIP=3139322E3136382E302E31");
  //ESP8266.println(TRAILING_URL);

}

void loop() { // run over and over
  byte buffer[300];
  if (ESP8266.available()) {
   Serial.write(ESP8266.read());
  }
  if (Serial.available()) {
    ESP8266.write(Serial.read());
  }
}

boolean read_until_ESP(const char keyword1[], int key_size, int timeout_val, byte mode){
  timeout_start_val=millis();//for the timeout
  char data_in[20];//this is the buffer - if keyword is longer than 20, then increase this
  int scratch_length=1;//the length of the scratch data array
  key_size--;//since we're going to get an extra charachter from the sizeof()

 //FILL UP THE BUFFER
 for(byte i=0; i<key_size; i++){//we only need a buffer as long as the keyword

            //timing control
            while(!ESP8266.available()){//wait until a new byte is sent down from the ESP - good way to keep in lock-step with the serial port
              if((millis()-timeout_start_val)>timeout_val){//if nothing happens within the timeout period, get out of here
                Serial.println("timeout");
                return 0;//this will end the function
              }//timeout
            }// while !avail

    data_in[i]=ESP8266.read();// save the byte to the buffer 'data_in[]

    if(mode==1){//this will save all of the data to the scratch_data_from
      scratch_data_from_ESP[scratch_length]=data_in[i];//starts at 1
      scratch_data_from_ESP[0]=scratch_length;// [0] is used to hold the length of the array
      scratch_length++;//increment the length
    }//mode 1

  }//for i

//THE BUFFER IS FULL, SO START ROLLING NEW DATA IN AND OLD DATA OUT
  while(1){//stay in here until the keyword found or a timeout occurs

     //run through the entire buffer and look for the keyword
     //this check is here, just in case the first thing out of the ESP was the keyword, meaning the buffer was actually filled with the keyword
     for(byte i=0; i<key_size; i++){
       if(keyword1[i]!=data_in[i])//if it doesn't match, break out of the search now
       break;//get outta here
       if(i==(key_size-1)){//we got all the way through the keyword without breaking, must be a match!
       return 1; //return a 1 and get outta here!
       }//if
     }//for byte i

    //start rolling the buffer
    for(byte i=0; i<(key_size-1); i++){// keysize-1 because everthing is shifted over - see next line
      data_in[i]=data_in[i+1];// so the data at 0 becomes the data at 1, and so on.... the last value is where we'll put the new data
    }//for

           //timing control
            while(!ESP8266.available()){// same thing as done in the buffer
              if((millis()-timeout_start_val)>timeout_val){
                Serial.println("timeout");
                return 0;
              }//timeout
            }// while !avail

    data_in[key_size-1]=ESP8266.read();//save the new data in the last position in the buffer

      if(mode==1){//continue to save everything if thsi is set
      scratch_data_from_ESP[scratch_length]=data_in[key_size-1];
      scratch_data_from_ESP[0]=scratch_length;
      scratch_length++;
    }//mode 1

    /*  JUST FOR DEBUGGING
    if(ESP8266.overflow())
    Serial.println("*OVER");
    */

  }//while 1

}//read until ESP

boolean setup_ESP(const char SSID_ESP[],const char SSID_KEY[]){//returns a '1' if successful

  ESP8266.print("AT\r\n");// Send just 'AT' to make sure the ESP is responding
  //this read_until_... function is used to find a keyword in the ESP response - more on this later and in the function itself
  if(read_until_ESP(keyword_OK,sizeof(keyword_OK),5000,0))//go look for keyword "OK" with a 5sec timeout
    Serial.println("ESP CHECK OK");
  else
    Serial.println("ESP CHECK FAILED");
  serial_dump_ESP();//this just reads everything in the buffer and what's still coming from the ESP

   ESP8266.print("AT+RST\r\n");// Give it a reset - who knows what condition it was in, better to start fresh
  if(read_until_ESP(keyword_Ready,sizeof(keyword_Ready),5000,0))//go look for keyword "Ready" - takes a few seconds longer to complete
    Serial.println("ESP RESET OK");//depneding on the FW version on the ESP, sometimes the Ready is with a lowercase r - ready
  else
    Serial.println("ESP RESET FAILED");
  serial_dump_ESP();
  ESP8266.print("AT+RST\r\n");// Give it a reset - who knows what condition it was in, better to start fresh
  if(read_until_ESP(keyword_Ready,sizeof(keyword_Ready),5000,0))//go look for keyword "Ready" - takes a few seconds longer to complete
    Serial.println("ESP RESET OK");//depneding on the FW version on the ESP, sometimes the Ready is with a lowercase r - ready
  else
    Serial.println("ESP RESET FAILED");
  serial_dump_ESP();

   ESP8266.print("AT+CWMODE=");// set the CWMODE
   ESP8266.print(CWMODE);//just send what is set in the constant
   ESP8266.print("\r\n");
  if(read_until_ESP(keyword_OK,sizeof(keyword_OK),1000,0))//go look for keyword "OK"
    Serial.println("ESP CWMODE SET");
  else

    Serial.println("ESP CWMODE SET FAILED");//probably going to fail, since a 'no change' is returned if already set - would be nice to check for two words
    ESP8266.println("AT+CWMODE?");
    if(read_until_ESP(keyword_CHECKCWMODE,sizeof(keyword_CHECKCWMODE),1000,0))
    {
      Serial.println("CWMODE ALREADY SET");
      serial_dump_ESP();
    }
    serial_dump_ESP();

   //Here's where the SSID and PW are set
   Serial.print("SETTING SSID_ESP: ");
   Serial.println(SSID_ESP);
   Serial.print("SETTING SSID_KEY: ");
   Serial.println(SSID_KEY);
   //DEbug poin

   ESP8266.print("AT+CWJAP=");//
   ESP8266.print("\"");
   ESP8266.print(SSID_ESP);//
   ESP8266.print("\",\"");
   ESP8266.print(SSID_KEY);//
   ESP8266.print("\"\r\n");
  if(read_until_ESP(keyword_OK,sizeof(keyword_OK),5000,0)==1)//go look for keyword "OK"
    Serial.println("ESP SSID SET OK DEVICE CONNECTED");
  else if(read_until_ESP(keyword_FAIL,sizeof(keyword_FAIL),5000,0)==1)
    Serial.println("ESP SSID SET FAILED");
  serial_dump_ESP();

  //This checks for and stores the IP address
  Serial.println("CHECKING FOR AN IP ADDRESS");
  ESP8266.print("AT+CIFSR\r\n");//command to retrieve IP address from ESP
  if(read_until_ESP(keyword_rn,sizeof(keyword_rn),10000,0)){//look for first \r\n after AT+CIFSR echo - note mode is '0', the ip address is right after this
  if(read_until_ESP(keyword_rn,sizeof(keyword_rn),1000,1)){//look for second \r\n, and store everything it receives, mode='1'
    //store the ip adress in its variable, ip_address[]
    for(int i=1; i<=(scratch_data_from_ESP[0]-sizeof(keyword_rn)+1); i++)//that i<=... is going to take some explaining, see next lines
       ip_address[i] = scratch_data_from_ESP[i];//fill up ip_address with the scratch data received
//i=1 because i=0 is the length of the data found between the two keywords, BUT this includes the length of the second keyword, so i<= to the length minus
//size of teh keyword, but remember, sizeof() will return one extra, which is going to be subtracted, so I just added it back in +1
    ip_address[0] = (scratch_data_from_ESP[0]-sizeof(keyword_rn)+1);//store the length of ip_address in [0], same thing as before
    Serial.print("IP ADDRESS = ");//print it off to verify
    for(int i=1; i<=ip_address[0]; i++)//send out the ip address
    Serial.print(ip_address[i]);
    Serial.println("");
  }}//if first \r\n
  else
  Serial.print("IP ADDRESS FAIL");
  serial_dump_ESP();

   ESP8266.print("AT+CIPMUX=");// set the CIPMUX
   ESP8266.print(CIPMUX);//from constant
   ESP8266.print("\r\n");
  if(read_until_ESP(keyword_OK,sizeof(keyword_OK),5000,0))//go look for keyword "OK" or "no change
    Serial.println("ESP CIPMUX SET");
  else
    Serial.println("ESP CIPMUX SET FAILED");
  serial_dump_ESP();

 //that's it!  Could be done by nesting everything together, so if one thing fails, it returns '0', and if it gets all the way through it returns '1'...oh well

}//setup ESP

//pretty simple function - read everything out of the serial buffer and whats coming and get rid of it
void serial_dump_ESP(){
  char temp;
  while(ESP8266.available()){
    temp =ESP8266.read();
    delay(1);//could play around with this value if buffer overflows are occuring
  }//while

}//serial dump

```

# Answer
You need to have "Connection: keep-alive" in your http header, default is "Connection: close" and that's why you never get anything in return from the server.

I have described it all together with a code sample in https://arduino.stackexchange.com/a/54558/48149

The code sample uses the library WifiEsp to connect to ESP8266.
> 1 votes

---
Tags: arduino-uno, esp8266, iot
---


# Question
Title: Replying with a html page in HTTP Web Server using esp01 and ArduinoIDE
Now there are many ways to reply with a webpage content to a user who is accessing the web server, But Keeping in mind to use as less space as possible, I was trying something new, Since i didnt got compilation error, I am a little confused as to what might be the error,

in `void data()` I am storing the html page and saving it in ROM,

```
void data()
{
  if(SPIFFS.exists("/login.html"))
  {
    Serial.println();
  }
  else{
    SPIFFS.begin();
    File f=SPIFFS.open("/login.html","w");
    String s="<html><head><title>AP</title><h1>Welcome to AP page</h1>\n";
    s+="</head><body><form name=\"/myform\" action=\"/login\" method=\"POST\">\n";
    s+="<input type=\"text\" name=\"username\" placeholder=\"username\"><br/>\n";
    s+="<input type=\"password\" name=\"password\" placeholder=\"password\"><br/>\n";
    s+="<input type=\"submit\" value=\"login\"></form></body></html>";
    f.println(s);
    f.close();
  }

}

```

Please correct the above lines if I wrote it wrong, After that, I wrote some lines in `void setup()`

```
WiFi.mode(WIFI_AP_STA);//Only Access point
  WiFi.softAP(ssid, password);  //Start HOTspot removing password will disable security

  IPAddress myIP = WiFi.softAPIP(); //Get IP address
  Serial.print("HotSpt IP:");
  Serial.println(myIP);

  server.on("/", HTTP_GET, handleRoot);      //Which routine to handle at root location
  server.on("/",HTTP_POST,handlelogin);
  server.onNotFound(handleerror);

  server.begin();

```

Now I am calling `void handleRoot()` I want to send the page that I wrote and saved in the `/login.html` file.

so for that,

```
void handleRoot()
  {
    SPIFFS.begin();
    File f=SPIFFS.open("/login.html","r");
    server.send(200, "text/html",f.readStringUntil('EOF'));
  }

```

Now once I do this and execute and load the program in ESP01, it shows me nothing, I have also tried sending `(String)f`, anything else I write is giving me an error, This is compiling fine, but when I connect to the AP and open 192.168.4.1 in the browser i am not seeing anything, But when I wrote `server.send(200,"text/html",(String)f)` I was getting 0, Any idea on what mistake I am making.

# Answer
> 1 votes
Small update, I used the same code for ESP8266 NodeMCU.

Sorry If I am posting this with wrong device number. But I tried that same code and uploaded it to ESP8266, it worked, and I am getting the AP webpage, that I am storing and sending the file. I will post it as an answer as I need to post an image.

The is the page that I get when using the HTML that I wrote:

>

So, this happened. I am confused as to why it didn't work with ESP01, plus I have to load the code every time I plug in the ESP01.

---
Tags: arduino-ide, web-server, http
---


# Question
Title: Control multiple LEDs with multiple buttons
Problem 1: LED1 needs to be on only when button1 is held down. Right now it takes several presses to turn on and off and stays on. Problem 1: LEDs 2,3,4 do not turn off with buttons 2,3,4. They are all turned off by button1, which is what I want, but I also need them to turn of with their respective button presses.

I need buttons 2,3,4 to light up LEDs 2,3,4 and stay lit until I press the respective buttons again OR button1 which turns off all lights, and the LED for button1 must only stay on when button1 is held down.

I am half way there with just a few minor problems. The first is LED1 stays on rather than when I hold the button1 down only. And the other problem is, it takes many presses to turn the LEDs on or off. I fixed this on 2,3,4 by removing the following code for each pin:

```
if (digitalRead(buttonPin2) == HIGH) { // check if buttonPin2 was pressed (be sure to use a resistor?)
  { digitalWrite(ledPin2, LOW);       // turn ledPin2 on
    ledPin2_status = 1;                // 1 = on, set ledPin2_status to 1
  }

```

After I remove that code the LEDs light straight away and stay on until I press button 1 which is what I want. But I would also like LEDs 2,3,4 to turn off with their respective button press. With that code removed LEDs 2,3,4 no longer work independently of button1.

Full Code:

```
// set pins
const int buttonPin1 = 2;                 // Pin1's pushbutton
const int buttonPin2 = 4;                 // Pin2's pushbutton
const int buttonPin3 = 6;                 // Pin3's pushbutton
const int buttonPin4 = 8;                 // Pin4's pushbutton
const int ledPin1 = 3;                    // Pin1's LED
const int ledPin2 = 5;                    // Pin2's LED
const int ledPin3 = 7;                    // Pin3's LED
const int ledPin4 = 9;                    // Pin4's LED

// set variables
int ledPin1_status = 0;
int ledPin2_status = 0;
int ledPin3_status = 0;
int ledPin4_status = 0;

void setup() {  //initialize pins
  pinMode(buttonPin1, INPUT); // set PINn as INPUT
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(ledPin1, OUTPUT);   // set LEDn as OUTPUT
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
  pinMode(ledPin4, OUTPUT);
}

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void loop() {
  if (digitalRead(buttonPin1) == HIGH) { // check if buttonPin1 was pressed (be sure to use a resistor?)
    if (ledPin1_status == 0) {           // check if ledPin1 was not already pressed
      digitalWrite(ledPin1, HIGH);       // turn ledPin1 on
      ledPin1_status = 1;                // 1 = on, set ledPin1_status to 1
    }
    else {
      digitalWrite(ledPin1, LOW);        // turn ledPin1 off
      ledPin1_status = 0;                // 0 = off, set Pin1_status to 0
      digitalWrite(ledPin2, LOW);        // turn ledPin2 off
      ledPin2_status = 0;                // 0 = off, set Pin2_status to 0
      digitalWrite(ledPin3, LOW);        // turn ledPin3 off
      ledPin3_status = 0;                // 0 = off, set Pin2_status to 0
      digitalWrite(ledPin4, LOW);        // turn ledPin4 off
      ledPin3_status = 0;                // 0 = off, set Pin2_status to 0
    }
  }

  if (digitalRead(buttonPin2) == HIGH) { // check if buttonPin2 was pressed (be sure to use a resistor?)
    { digitalWrite(ledPin2, HIGH);       // turn ledPin2 on
      ledPin2_status = 1;                // 1 = on, set ledPin2_status to 1
    }
  }

  if (digitalRead(buttonPin2) == HIGH) { // check if buttonPin2 was pressed (be sure to use a resistor?)
    { digitalWrite(ledPin2, LOW);       // turn ledPin2 on
      ledPin2_status = 1;                // 1 = on, set ledPin2_status to 1
    }
  }

  if (digitalRead(buttonPin3) == HIGH) { // check if buttonPin3 was pressed (be sure to use a resistor?)
    { digitalWrite(ledPin3, HIGH);       // turn ledPin3 on
      ledPin3_status = 1;                // 1 = on, set ledPin3_status to 1
    }
  }

  if (digitalRead(buttonPin3) == HIGH) { // check if buttonPin2 was pressed (be sure to use a resistor?)
    { digitalWrite(ledPin3, LOW);       // turn ledPin3 on
      ledPin2_status = 1;                // 1 = on, set ledPin2_status to 1
    }
  }

  if (digitalRead(buttonPin4) == HIGH) { // check if buttonPin2 was pressed (be sure to use a resistor?)
    { digitalWrite(ledPin4, HIGH);       // turn ledPin4 on
      ledPin2_status = 1;                // 1 = on, set ledPin2_status to 1
    }
  }

  if (digitalRead(buttonPin4) == HIGH) { // check if buttonPin2 was pressed (be sure to use a resistor?)
    { digitalWrite(ledPin4, LOW);       // turn ledPin4 on
      ledPin2_status = 1;                // 1 = on, set ledPin2_status to 1
    }
  }

```

# Answer
First thing, you need to debounce your buttons. The fact that you declared the (unused) variable `debounceDelay` suggests you have though about debouncing, but you did not implement it.

Next thing, you should look for button *press* and *release* events. That's when the button pin changes state from `LOW` to `HIGH` or vice versa. It is not enough to check whether the pin is `HIGH` or `LOW`, you have to check for the *changes* in state. This is usually called *edge detection*.

With enough effort, you could probably do that yourself. However, to make your life easier, you can use a debouncing library that does edge detection, such as the quite popular Bounce2. This library provides, for each button it debounces, a `rose()` method that tells you when the input signal rose (i.e. transitioned from `LOW` to `HIGH`) and a `fell()` method that tells you when it fell (transitioned `HIGH` → `LOW`). Using these methods, your problem can be coded in a fair natural way. For example (not tested):

```
#include <Bounce2.h>

const int     BUTTON_COUNT = 4;
const int16_t DEBOUNCE_DELAY = 50;
const uint8_t buttonPins[BUTTON_COUNT] = {2, 4, 6, 8};
const uint8_t ledPins[BUTTON_COUNT] = {3, 5, 7, 9};

Bounce buttons[BUTTON_COUNT];
uint8_t ledStates[BUTTON_COUNT];

void setup() {
    for (int i = 0; i < BUTTON_COUNT; i++) {
        buttons[i].attach(buttonPins[i], INPUT);
        buttons[i].interval(DEBOUNCE_DELAY);
        pinMode(ledPins[i], OUTPUT);
        ledStates[i] = LOW;
        digitalWrite(ledPins[i], ledStates[i]);
    }
}

void loop() {

    // Update the debouncers.
    for (int i = 0; i < BUTTON_COUNT; i++)
        buttons[i].update();

    // When the first button is pressed:
    if (buttons[0].rose()) {

        // Light up the first LED.
        digitalWrite(ledPins[0], HIGH);

        // and turn off all the others.
        for (int i = 1; i < BUTTON_COUNT; i++) {
            ledStates[i] = LOW;
            digitalWrite(ledPins[i], ledStates[i]);
        }
    }

    // When the first button is released:
    if (buttons[0].fell()) {

        // turn off the first LED.
        digitalWrite(ledPins[0], LOW);
    }

    // When any other button is pressed:
    for (int i = 1; i < BUTTON_COUNT; i++) if (buttons[i].rose()) {

        // Toggle its state.
        ledStates[i] = !ledStates[i];
        digitalWrite(ledPins[i], ledStates[i]);
    }
}

```

**Edit**: In order for the first button to only turn off LEDs 1 and 2, the lines

```
// and turn off all the others.
for (int i = 1; i < BUTTON_COUNT; i++) {
    ledStates[i] = LOW;
    digitalWrite(ledPins[i], ledStates[i]);
}

```

should be replaced by:

```
// and turn off LEDs 1 and 2.
for (int i = 1; i <= 2; i++) {
    ledStates[i] = LOW;
    digitalWrite(ledPins[i], ledStates[i]);
}

```
> 0 votes

---
Tags: led, sketch, debounce
---


# Question
Title: Is there a real alternative now to using GSM for data sending?
I would like to create an Arduino system that sends the temperature in a place outdoors to a server.

I've read in Internet forums that there might be alternatives to GSM and GPRS technology for sending data remotely, but I'm not sure about them. In absence of WiFi, is GSM the best technology today, even that you have to use the SIM plan to use it?

# Answer
> 0 votes
GSM (or more realistically now, LTE) is really the only option.

Simply put: you need some method of accessing the internet, and unless you create your own local infrastructure that means using the mobile phone system. It's the only system that is virtually everywhere and doesn't require you to install your own communication system.

So that means some modem device that can communicate with the mobile phone system. GSM is what it used to be, although some mobile companies are now deprecating the GSM system and only really providing UMTS (3G) and LTE (what will eventually be 4G), but LTE modems are quite expensive still.

So yes, you need a SIM to do it. You can't access a mobile phone network without one.

One option that could be a cheaper possibility would be to get a cheap second hand smartphone off eBay (or dig out your old one from the bottom of the desk drawer) and use that as your own mobile WiFi hotspot. Your Arduino device connects to the phone with WiFi, and the phone connects to the UMTS or LTE network using a cheap PayG SIM.

---

LoRA is a technology that is gradually becoming more popular and allows long range wireless communications at low power and low cost. There are areas where LoRA is becoming available, such as in Munich. Should LoRA become available in your area, or should you invest in your own infrastructure, that could become a viable alternative to using the mobile phone network.

---
Tags: temperature-sensor, web-server, remote-control
---


# Question
Title: How do I include a file that is not a .h, .c or .cpp file?
I am using the ADF7030 on the breakout board (not motherboard) and I am trying to interface it with an Arduino Uno. I want to load the transceivers configuration file onto the chip using SPI. To do this, I need to include the ".cfg" file but when I use the C style array (as in the datasheet - code below) it says that it can't find the file in the .ino sketch.

`const unit8_t Radio_Memory_Configuration [ ] = {
 #include "Settings_ADF7030-1.cfg"
}`

How could I include this file?

# Answer
From looking at the arduino-builder source only files with the following extensions are copied to the build directory: .ino .pde .h .c .hpp .hh .cpp .s

So you will need to use one of those extensions.
> 2 votes

---
Tags: spi
---


# Question
Title: The Arduino IDE can’t find my Arduino Uno
My Arduino has all of its LEDs on. The `Rx`, `Tx` and `L` LEDs are all on and my computer can’t see it (it's an SMD edition).

# Answer
> 1 votes
It can have many reasons, but you can try the following:

**First time use?**

* Check if you need to install a special driver for CH340

**Environment/Software problems**

* Try another USB port
* Change USB cable
* Restart Arduino IDE
* Restart computer
* Reinstall Arduino IDE

**Hardware problems**

* Test using another Arduino
* Test using another computer/laptop
* Replace USB cable
* The Arduino is (partly) broken, nothing much to do here

# Answer
> 0 votes
The USB interface chip controls the Rx & Tx lights. I suspect you fried it. Does the '328P feel warm or hot to the touch? That's usually a sign that it has been damaged.

# Answer
> 0 votes
Is it an "official" Arduino purchased from their website? If it isn't, chances are you need to install CH340 drivers for your computer before the Arduino will be recognized. Drivers can be found here Have you successfully used this device with your computer before?

---
Tags: arduino-uno, arduino-ide, led, arduino-uno-smd
---


title: Flashing NodeMCU with .ino file?

text:
# Question
Title: Flashing NodeMCU with .ino file?
I'm brand new to the Arduino world. I recently purchased a NodeMCU in order to have it act as a sort of foothold to get into Arduinos as it's something I've always wanted to do. However, it was only after I had received the NodeMCU that I realised that there was no default option in the Arduino IDE to flash to a NodeMCU and soon found out that this is because the NodeMCU is in fact not an Arduino and therefore has its own proprietary flashing software for .bin files. This initially confused me as an outsider as I assumed all devices of that nature must be Arduinos.

I recently came across a Homebridge plugin by affix called homebridge-mcu-lamp which uses a NodeMCU running an HTTP server to control a relay. Interestingly, the script he has included in the repository which he claims to have running on his NodeMCU is a .ino file which really confused me.

My question is: how would I flash a `.ino` file to a NodeMCU like the one mentioned above as I have no experience with `.bin` files and would much more value to treat the NodeMCU as an Arduino instead (i.e. programming in C++)?

I understand this may sound like a very simple/dumb question for most of you on this forum but it is something that has had me stumped for days and would really appreciate some guidance on.

I would also find it useful if someone could explain to me the difference between a NodeMCU and an ESP8266 as I see the two words being used interchangeably when referring to the same looking board.

This is what my NodeMCU looks like:

# Answer
> 1 votes
Last question first: The ESP8266 is the main IC on the NodeMCU board.

This is similar to the idea that an ATMega328 is the IC on Arduino Uno.

A normal 'clean' Arduino IDE install can work with an Uno ('flash with an INO'), but not with an ESP8266 based board. For this, you will need the ESP8266 addon for the Arduino IDE, after which, the NodeMCU board is available as an option.

This page documents the ESP8266 addon: https://github.com/esp8266/Arduino

Long story short, open preferences (File -\> Preferences) , under Additional Board Manager URLs, add http://arduino.esp8266.com/stable/package\_esp8266com\_index.json

Click on Tools\>Board\>Board Manager (assuming you have Arduino IDE 1.6.4 or later) and search for ESP8266 and install the option that includes NodeMCU.

---
Tags: esp8266, arduino-ide, c++, nodemcu
---