title: Dealing with noise in arduino interrupt

text:
# Question
Title: Dealing with noise in arduino interrupt
I'm makeing two modules, module2 gets sensor signal, and send wireless message to module1, with HC-12. Then module1 is going to do some work it is supposed to do. Circuit configuration is in the picture.

I tested HC-12 communication, and they send, receive well. But my problem is that, when module1 gets turned ON, Interrupt gets activated (LOW) and module2 sends signal that's not supposed to send. It seems it is because of electromagnetic wave noise, from HC-12.

How can I filter this noise, using code ? Now I'm stuck for the last 3 days.

`code` Module1

```
#include <SimpleTimer.h>

#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

// #define IDlen 4
#define maxID 5

SoftwareSerial mySerial(2,3);
LiquidCrystal_I2C lcd(0x27, 16, 2);
int upButtonPin = 7;
int selectButtonPin = 6;
int downButtonPin = 5;
int sensors[maxID] = {1001,9999,9999,9999,9999};
int receivedID = 0;
int currentPos = 0;
String rcvMsg = "xxxx";

//void printSensor(int intID);
void menu();
void showAllSensors();
int removeID(int senNumInt);

void setup()
{
  Serial.begin(9600);
  Serial.println("Serial began.");

  mySerial.begin(9600);
//  mySerial.println("0000");

  lcd.begin();
  pinMode(upButtonPin,  INPUT_PULLUP);
  pinMode(selectButtonPin, INPUT_PULLUP);
  pinMode(downButtonPin, INPUT_PULLUP);
}

void loop()
{
  rcvMsg = "xxxx";
  lcd.setCursor(1,1);
  lcd.clear();
  lcd.print("Ready");
  if(digitalRead(upButtonPin)==LOW){
    lcd.clear();
    lcd.print("Up btn pressed!");
  }
  if(digitalRead(downButtonPin)==LOW){
    lcd.clear();
    lcd.print("Down btn pressed!");
  }
  if(digitalRead(selectButtonPin)==LOW){
    lcd.clear();
    lcd.print("Registered sensors:");
    delay(1000);
    lcd.clear();
    showAllSensors();
    menu();
  }
  if(mySerial.available()>0){

//    String rcvMsg = mySerial.readStringUntil('\n');
    rcvMsg = mySerial.readStringUntil('\n');
    Serial.print("Received msg: ");
    Serial.print(rcvMsg);
    Serial.print('\n');
    receivedID = rcvMsg.substring(0,4).toInt();
    Serial.println(receivedID);
    delay(50);

    for (int i=0;i<maxID;i++){
      if(sensors[i] == receivedID){
        String temp = String(receivedID);
        String ack = String(temp + "01"); // 01: success 02: reject (ID does not exist)
        mySerial.println(ack);
        Serial.print("Ack sent: ");
        Serial.print(ack);
      }
    }
  }
}

void menu(){
  lcd.print("UP: add sensor");
  lcd.setCursor(0,1);
  lcd.print("DOWN: del sensor");
  lcd.setCursor(0,0);

  while(1){
    if(digitalRead(upButtonPin)==LOW){
      lcd.clear();
      lcd.print("Add sensor:");
      delay(1500);
      lcd.clear();
      int senNumInt = 1000;
      char senNum[IDlen];
      sprintf(senNum, "%d", senNumInt);

      while(1){
        lcd.print(senNum);
        if(digitalRead(upButtonPin)==LOW){
          senNumInt++;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(downButtonPin)==LOW){
          senNumInt--;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(selectButtonPin)==LOW){
          lcd.clear();
          lcd.print(senNum);
          lcd.setCursor(0,1);
          lcd.print("Menu: OK, Down: Cancel");
          //센서 입력값을 받아서, 리스트에 넣어 놓기
          sensors[currentPos] = senNumInt;
          lcd.clear();
          showAllSensors();
          delay(1500);
          break; // 값 입력 후 저장한 것 보여주고... 나가기.
        }
        delay(200);
        lcd.clear();
      }
      delay(200);
      break;
    } // up button 누름 메뉴 끝

    if(digitalRead(downButtonPin)==LOW){
      lcd.clear();
      lcd.print("Remove sensor:");
      delay(1500);
      lcd.clear();
      int senNumInt = 1000;
      char senNum[IDlen];
      sprintf(senNum, "%d", senNumInt);

      while(1){
        lcd.print(senNum);
        if(digitalRead(upButtonPin)==LOW){
          senNumInt++;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(downButtonPin)==LOW){
          senNumInt--;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(selectButtonPin)==LOW){
          lcd.clear();
          lcd.print(senNum);
          lcd.setCursor(0,1);
          lcd.print("Delete sensor");
          delay(600);
          lcd.clear();

          //센서 입력값을 받아서, 리스트에서 찾은 후 삭제
          int result = removeID(senNumInt);
          if(result==1){
            lcd.print("Deleted.");
            showAllSensors();
          }else{
            lcd.print("No such ID!!");
          };
          delay(1500);
          break; // 값 입력 후 저장한 것 보여주고... 나가기.
        }
        delay(200);
        lcd.clear();
      }
      delay(200);
      break;
    } // down button 누름 메뉴 끝

    delay(200);
  }
  return;
}

void showAllSensors(){
  char imsi[IDlen];
  for(int i=0;i<maxID;i++){
    Serial.println(sensors[i]);
    sprintf(imsi, "%d", sensors[i]);
    lcd.print(imsi);
    delay(800);
    lcd.clear();
  }
  return;
}

int removeID(int senNumInt){
  int isFound = 0;
  for(int i=0;i<maxID;i++){
    if(sensors[i] == senNumInt){
      sensors[i] = 9999;
      isFound = 1;
    }
  }
  return isFound;
}

```

`code`Module2

```
#include <SoftwareSerial.h>
#include <avr/sleep.h>
#include <SimpleTimer.h>

SimpleTimer timer;
const int wakeUpPin = 2; // pin of interrupt 0
const int LED = 8;
const int numMsg = 1; // For the safety, send multiple messages, everytime.
boolean armed = false;
SoftwareSerial mySerial(4,5);
String ID = "1001";
String code = "01";
String msg = "xxxx";
String rcvMsg = "xxxx";
int timerID = 0;
boolean isWaked = false;
int pulseWidth = 0;

/*
  Communication protocol
  01: powered on
  02: Sensor touched (Feed is full)
  03: alive
*/

void setup()
{
  String msg = String(ID + code);
  pinMode(wakeUpPin, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  timerID = timer.setInterval(1000, sendMsg);

  Serial.begin(9600);
  mySerial.begin(9600);
  Serial.println(msg);
  delay(100);
}

void loop() // 반복
{
  pulseWidth = pulseIn(wakeUpPin, LOW, 100000);
  Serial.println("start loop.");
  armed = true;
  delay(100);
  Serial.println("Now sleeping..");
  delay(200);
  sleepNow();

  Serial.println(pulseWidth);
  if(armed){
    Serial.println("Waked up. Send Feed full msg.");

    delay(200);
    code = "02";
    msg = String(ID + code);
    sendMsg();
    int count = 0;
    while(1){
      count++;
      if(count>200){      //prevent infinite loop
        count = 0;
        break;
      }
      Serial.print('*');
      if(mySerial.available()>0){
        Serial.println("RECEIVED!!!!");
        rcvMsg = mySerial.readStringUntil('\n');
        if(rcvMsg.substring(0,4).equals(ID)){
//          timer.deleteTimer(timerID);
          Serial.println("My msg is received successfully. Now sleep again..\n");
          break;
        }
      }
      delay(50);
    }
    armed = false;
  }
}

void wakeUpNow(){
  isWaked = true;
  return;
}

void sleepNow(){
  Serial.println("Entered sleep now()");
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  attachInterrupt(0,wakeUpNow, LOW);
  sleep_mode();
  // When wakes up, resume codes from here.
  sleep_disable();

  detachInterrupt(0);
  return;
}

void sendMsg(){
  for (int i=0;i<numMsg;i++){
    mySerial.println(msg);
  }
  return;
}

```

# Answer
I know, it is not exactly what you asked for, but I recommend hardware filtering. I had problems with noise on interrupts and I was able to solve that with this component: https://www.st.com/content/st\_com/en/products/emi-filtering-and-signal-conditioning/integrated-emi-filtering-and-esd-protection/computer-legacy-port-ipad/kbmf.html#overview

It is not expensive and saves you a lot of headache. If you can't use SMD components, you can rebuild the circuit of that filter with capacitors and resistors, just be sure, that you put the filter as close as possible to the interrupt pin.
> 1 votes

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


title: strange strings

text:
# Question
Title: strange strings
```

#include "Keypad.h"

char Incoming_value = 0;
String password = "123456";
String input = "";
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6,7,8,9}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop()
{
  if (Serial.available() > 0)
  {
    Incoming_value = Serial.read();
    Serial.print(Incoming_value);
    Serial.print("enter value");
    if (Incoming_value == '1') {
      digitalWrite(13, HIGH);
      Serial.print("ON");
    }
    else if (Incoming_value == '0') {
      Serial.print("OFF");
      digitalWrite(13, LOW);
    }
  }
  // Read the pushed button
  char key = keypad.getKey();
  input = input + key;
  // just print the pressed key
  if (key) {
    Serial.println(key);
  }
  if(key == '*' ){
    Serial.println(input);
    if( input == password){
      digitalWrite(13, HIGH);
    }
  }
  if(key == '#'){
    digitalWrite(13, LOW);
    input = "";
  }

/*
  // this checkes if 4 is pressed, then do something. Here  we print the text but you can control something.
  if (key == '4') {
    Serial.println("Key 4 is pressed");
          digitalWrite(13, HIGH);
      Serial.print("ON");
  }
    if (key == '5') {
    Serial.println("Key 5 is pressed");
          digitalWrite(13, LOW);
      Serial.print("ON");
  }
  */
}

```

when print input variable i get strange text like

> ⸮⸮⸮⸮⸮⸮⸮;⸮⸮ߵ⸮⸮⸮⸮u⸮⸮⸮⸮⸮⸮?/}⸮⸮⸮⸮⸮⸮~⸮⸮⸮⸮⸮-d

what i can do ?

# Answer
> 3 votes
First of all you have to make sure, that you select the same baudrate in the Serial Monitor, that you used in your sketch with `Serial.begin()`. This error is very common and garbage values is the symptom of this.

But your code also has problems. You have the `input` variable of type `String`, which should hold the user input for comparison with the password. Directly after getting the key, you are appending this key to the string. You are assuming here, that `keypad.getKey()` is waiting for the user to actually press a key and then return that. But this is not the case. `keypad.getKey()` will return `NO_KEY`, when the user currently isn't pressing a key. This is defined in the `Keypad` library as `'\0'` (the null character), which marks the end of a string. Your code runs very fast, so you are adding more and more null characters to your string. Your strings gets bigger and bigger, filling your RAM very fast.

**How to solve this:** You should only use the return value of `keypad.getKey()`, if a key was actually pressed. Put all the code after it in an if statement, checking for `NO_KEY`:

```
// Read the pushed button
char key = keypad.getKey();
if(key != NO_KEY){
    input = input + key;
    // just print the pressed key
    if (key) {
        Serial.println(key);
    }
    if(key == '*' ){
        Serial.println(input);
        if( input == password){
            digitalWrite(13, HIGH);
        }
    }
    if(key == '#'){
        digitalWrite(13, LOW);
        input = "";
    }
}

```

# Answer
> 1 votes
**PS**: @lurker's suggestion in the comments - check the baud rate setting in your serial monitor as well.

**EDIT**: I admit that the code in the previous version of this answer was foolishly typed out by me due to lack of patience, so I'll make up for my mistake(not in code, but as a full answer).

First of all, I didn't understand what you wanted to do with the `Incoming_value` variable in your sketch, so I'm not gonna talk about it; I'd suggest adding a sufficiently small delay at the end of the code in the loop. This should provide the serial port some time to handle the incoming data and stop printing the confusing output (perhaps; just because delays make your microcontroller wait for a while to get things done elsewhere , especially where the reception of data is slow and thus avoid collisions)

Also note that I am not a CS student or an electronics geek, but I am speaking from my guesswork. Any correction is accepted.

---
Tags: arduino-mega
---


# Question
Title: arduino leonardo stops transmitting once hdmi cable is connected to a screen
I am using arduino leonardo for moving mouse pointer with head tracking using MPU6050. It works fine in general. But as soon as I connect an external lcd screen to my laptop via hdmi cable, it stops transmitting. (that is the TX led goes off altogether and the mouse stops moving) I am not able to figure out what the issue is here Will using a teensy 3.0 instead of leonardo solve this problem?

# Answer
> 1 votes
The issue is that the mouse coordinates are being set by the display device that it's attached to.

The computer sends a descriptor about the display to the HID device ( the mouse ) the mouse then uses the information about the logical size of the screen to co-ordinate the movements.

For example, to move with `Mouse.move(100,100,0);` you are not actually moving by 100 pixels, but by 100/(127-((-127)).

The only option is can suggest is to STOP the mouse and Restart it again - this will be easier to restart calculations again.

Heres my Logic Function to convert Percentage to appropriate values for Mouse.move();
`int percentToLogic(int percent) { return percent*254/100; }`

---
Tags: lcd, arduino-leonardo, mpu6050, gyroscope
---


title: Arduino nano digital I/O overload

text:
# Question
Title: Arduino nano digital I/O overload
Is it possible to kill arduino nano with overload?

I wanted to drive a relay with arduino, and I used a BC547 to switch 12V for the relay. But in the relay there was a diode, which sorted out the circuit (thats why I drawed in the wrong orientation)

I know it was a mistake to not use current limiting resistor on Base of the transistor.

Is it possible that this shorted circuit made too much current on the transistor base which killed my arduino?

I made this circuit:

# Answer
Short answer is probably. There is a voltage drop from base to emitter that is about .7 volts. But something still has to contend with the rest of the energy. You might try a different Arduino digital output on the chance that the balance of the processor is working as expected.

I say probably because several things might have happened if the transistor actually turned on. For instance the forward biased (backwards) diode may have allowed so much current to flow through the relay and transistor that the transistor failed first. Or, if the power supply had a low current rating, it may not have had the capacity to burn anything out. As you can see, it is difficult to say what exactly happened with out testing each part individually.
> 2 votes

---
Tags: arduino-uno
---


# Question
Title: Arduino code not working properly (Please Help)
I am having some trouble getting my board to perform the function I want it to perform. This is a project I have due in a few days, and I have hit a wall I just can't seem to get past. Now, I will say the issue is definitely in the way I coded the program, but I don't really know enough about Arduino (and coding) to understand why it is not working. My board is properly hooked up to use 3LEDs, a speaker, a photoresistor, and an ultrasonic sensor (detects distances). My Arduino program takes serial input from a GUI that I created in MATLAB. I have verified the MATLAB code is good, and the serial port is communicating properly. I have made an alarm that goes off when light or motion is detected. It has 3 basic functions:

1. Set the alarm
2. Turn off the alarm
3. "snooze" which just delays for 5 minutes and then the alarm goes off

The snooze and turn off alarm parts of my code are working great, but the set alarm is where I am having trouble. The snooze option sets off the yellow LED to verify it is on "snooze". The red LED comes on when the alarm is currently going off. The green LED comes on when the alarm is set. When I try to activate the "Set Alarm" function, which is case 'O' in a switch case, the light does come on, but the sensors are not picking up any input as far as I can tell. Again I have verified the pins and everything are set up correctly as I have isolated those and verified they work. I have a suspicion that the problem is because I have the sensors initialed within the switch case of the "Set Alarm" (case 'O', not 0). I don't really know how to get the sensors to run continually within that switch case until the "turn alarm off" case is activated. I need the sensors to be activated/reset by "Set Alarm" case.

\**I am also new to this forum so please let me know if I am missing anything!

here is my code:

```
void setup()
{
  Serial.begin(115200);
  pinMode(12,OUTPUT); //RED
  pinMode(13,OUTPUT); //GREEN
  pinMode(14,OUTPUT); //YELLOW
  pinMode(16,OUTPUT); //SPEAKER
  pinMode(4,INPUT); //Echo
  pinMode(2,OUTPUT); //Trig
}

void loop()
{
 if(Serial.available() >0)
 {
 char b = Serial.read();

  switch(b)
  {
    //Turn Alarm off
    case 'A' :
    {
    digitalWrite(12,LOW);//red off
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    noTone(16);
    delay(500);
    }
    break;

    // Set alarm
    case 'O' :
    {
      int light;
  light = analogRead(0);
  unsigned long distance;
    digitalWrite(2,LOW);
  delayMicroseconds(2);
  digitalWrite(2,HIGH);
  delayMicroseconds(10);
  digitalWrite(2,LOW);
  distance = pulseIn(4,HIGH);
  distance = distance/58; //centimeters
  delay(500);

    digitalWrite(12,LOW); //red off
    digitalWrite(14,LOW); //yellow off
    digitalWrite(13,HIGH); //green on

  if (light < 400)
    {
     digitalWrite(12,HIGH);//red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500);
    }

  if (distance < 50)
    {
     digitalWrite(12,HIGH);//red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500);
    }

    }
    break;

    // snooze option
    case 'Z' :
    {
    digitalWrite(14,HIGH); //yellow on
    digitalWrite(12,LOW); //red off
    digitalWrite(13,LOW); // green off
    noTone(16);
    delay(300000UL);
    digitalWrite(12,HIGH); //red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500);
    }
    break;
   }

  }
}

```

Any help would be very much appreciated!

# Answer
The most simplest way to troubleshoot a program is to add `Serial.println();` statements everywhere. For example you could add `Serial.println("Setting Alarm");` in the first line of the case for setting the alarm.

You will notice that the set alarm code only runs once through, instead of continously. You should use the case to set a mode or a state in where the sensors are checked continously.

First I would create a variable called `setAlarmMode` and set it to `false`.

```
setAlarmMode = false;

```

Then I would remove the reading of sensors from the case statement and instead set `setAlarmMode` to `true`.

```
// Set alarm
case 'O' :
  {
    Serial.println("Setting Alarm");

    // Set the LEDs for the mode
    digitalWrite(12, LOW); //red off
    digitalWrite(14, LOW); //yellow off
    digitalWrite(13, HIGH); //green on

    setAlarmMode = true;
  }
  break;

```

Now I would insert this code outside of the `if (Serial.available() > 0)` code block:

```
// Read sensors
if (setAlarmMode == true)
  {
    Serial.println("Reading sensors");
    int light;
    light = analogRead(0);
    Serial.print("Light sensor value: ");
    Serial.print(light);

    unsigned long distance;

    // Do trigger pulse
    digitalWrite(2, LOW);
    delayMicroseconds(2);
    digitalWrite(2, HIGH);
    delayMicroseconds(10);
    digitalWrite(2, LOW);

    distance = pulseIn(4, HIGH);
    distance = distance / 58; //centimeters
    Serial.print("   Distance sensor value: ");
    Serial.println(distance);

    if (light < 400)
    {
      Serial.println("Light below threshold");
      setAlarmMode = false;
      activateAlarm();
    }

    if (distance < 50)
    {
      Serial.println("Distance below threshold");
      setAlarmMode = false;
      activateAlarm();
    }

    delay(500);
  }

```

I have also created a function to hold the common code of showing the alarm:

```
void activateAlarm(void)
{
  digitalWrite(12, HIGH); //red on
  digitalWrite(13, LOW); // green off
  digitalWrite(14, LOW); //yellow off
  tone(16, 832);
  delay(500);
}

```
> 1 votes

# Answer
The problem is that, if you enter 'O', you go thorugh the set alarm case only once. If no alarm was triggered, it just falls through the if statements and is then back in the main loop. In that main loop, you only check for your sensors, if something was entered to the serial console. That means if you do not enter anything during a loop, nothing happens.

The solution to this would be to implement a finite state machine. That means you use a state variable for the switch case. You then update your state based on the state and the external conditions. In your case you can just update the state using user input.

I changed your code a bit for a possible (but bad) implementation. I did not verify or check for errors. I recommend using a more solid implementation, if you plan to build upon this code for more complex behavior.

```
char state = 'A'; //initialize state in Off state
char b;          // make user input variable global
void setup()
{
  Serial.begin(115200);
  pinMode(12, OUTPUT); //RED
  pinMode(13, OUTPUT); //GREEN
  pinMode(14, OUTPUT); //YELLOW
  pinMode(16, OUTPUT); //SPEAKER
  pinMode(4, INPUT); //Echo
  pinMode(2, OUTPUT); //Trig
}

void loop()
{
  if (Serial.available() > 0)
  {
    b = Serial.read();
  }
  // close user input section

  switch (state) // run switch case every loop
  {
    //Turn Alarm off
    case 'A' :
      {
        digitalWrite(12, LOW); //red off
        digitalWrite(13, LOW); // green off
        digitalWrite(14, LOW); //yellow off
        noTone(16);

        delay(500);
      }
      break;

    // Set alarm
    case 'O' :
      {
        int light;
        light = analogRead(0);
        unsigned long distance;
        digitalWrite(2, LOW);
        delayMicroseconds(2);
        digitalWrite(2, HIGH);
        delayMicroseconds(10);
        digitalWrite(2, LOW);
        distance = pulseIn(4, HIGH);
        distance = distance / 58; //centimeters
        delay(500);

        digitalWrite(12, LOW); //red off
        digitalWrite(14, LOW); //yellow off
        digitalWrite(13, HIGH); //green on

        if (light < 400)
        {
          digitalWrite(12, HIGH); //red on
          digitalWrite(13, LOW); // green off
          digitalWrite(14, LOW); //yellow off
          tone(16, 832);
          delay(500);
        }

        if (distance < 50)
        {
          digitalWrite(12, HIGH); //red on
          digitalWrite(13, LOW); // green off
          digitalWrite(14, LOW); //yellow off
          tone(16, 832);
          delay(500);
        }

      }
      break;

    // snooze option
    case 'Z' :
      {
        digitalWrite(14, HIGH); //yellow on
        digitalWrite(12, LOW); //red off
        digitalWrite(13, LOW); // green off
        noTone(16);
        delay(300000UL);
        digitalWrite(12, HIGH); //red on
        digitalWrite(13, LOW); // green off
        digitalWrite(14, LOW); //yellow off
        tone(16, 832);
        delay(500);
      }
      break;
  }

  state = b; // update state based on input

}

```
> 2 votes

---
Tags: esp8266, code-review, photoresistor, ultrasonics
---


# Question
Title: Problems with Hardware Serial (UART) on Nano 33 BLE Sense
my new Nano 33 BLE Sense arrived today. I'm working on a project to send data from the the Nano via an Xbee S2C module to a receiver module connected to a Nano 33 IoT. I had the project working before using an MPU6050 and Mega 2560 board which worked (using Software Serial on the Mega). On the IoT side, I am using 'Uart XBeeRx (&sercom0, 5, 6, SERCOM\_RX\_PAD\_1, UART\_TX\_PAD\_0);' to process the data from the Xbee. Having tried this syntax on the BLE Sense I hit problems and after some Googling found a different syntax. However my new code isn't working in so far as it compiles, uploads and then crashes the BLE Sense (serial port disappears from tools and the onboard LED blinks slowly and erratically). I need to keep resetting the board and suspect there is some issue with my hardware serial implementation. I've cut the code down to simply send accelerometer data. My code is as follows - the EasyTransfer library simplifies the Xbee comms. Any help appreciated!

```
#include <EasyTransfer.h>
#include <Arduino_LSM9DS1.h>

UART XBeeTx (digitalPinToPinName(6), digitalPinToPinName(5), NC, NC);

EasyTransfer ET;

struct SEND_DATA_STRUCTURE {

  float xAcc;
  float yAcc;
  float zAcc;

};

SEND_DATA_STRUCTURE myData;

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {

XBeeTx.begin(9600);

ET.begin(details(myData), &XBeeTx);

}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop() {

  float x, y, z;

if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);

  }

  myData.xAcc = x;
  myData.yAcc = y;
  myData.zAcc = z;

  ET.sendData();

}

```

# Answer
> 2 votes
You can't make calls to IMU if you haven't initialised it with IMU.begin()

---
Tags: arduino-nano, uart, xbee, ble
---


# Question
Title: How do I get sensor values using transmitter and receiver?
I used an HC-SR04 sensor and connected it to an Arduino board (BOARD1) with a 433 MHz transmitter, and the other board (BOARD2) is connected to the 433 MHz receiver. I don't know how to see the sensor value readings from the (BOARD1) in the serial monitor.

**HERE IS THE CODE OF THE TRANSMITTER**

```
#include <RH_ASK.h>
#include <SPI.h> // Not actually used but needed to compile

RH_ASK driver;
int echo=11;
int trig=9; int sensorval;
void setup() {
   Serial.begin(9600); // Debugging only
   driver.init();
}

void loop() {
   digitalWrite(trig,LOW);
   delayMicroseconds(10);
   digitalWrite(trig,HIGH);
   delayMicroseconds(10);
   digitalWrite(trig,LOW);
   delayMicroseconds(10);
   sensorval=pulseIn(echo,HIGH);
   const char *msg = sensorval;
   driver.send((uint8_t *)msg, strlen(msg));
   driver.waitPacketSent();
   delay(200);
}

```

**HERE IS THE CODE OF THE RECEIVER**

```
#include <RH_ASK.h>
#include <SPI.h> // Not actually used but needed to compile

RH_ASK driver;
const int sensorval;
void setup() {
    Serial.begin(9600); // Debugging only
    driver.init();
}

void loop() {
    uint8_t buf[4];
    uint8_t buflen = sizeof(buf);
    if (driver.recv(buf, &buflen)) // Non-blocking
    {
    Serial.print("message Received: ");
 Serial.println((char*)buf);
    }
}

```

# Answer
**First: A short excourse about c-strings**

In C a string is an array of characters. Such an array is defined with

```
char msg[10];

```

`10` being the size of the array. Every valid c-string needs to be terminated with the null character `\0`. This character is not printable, thus you don't see it normally. But the standard string functions (like `printf()`, `strlen()`, etc) use the null character to find the end of the string. So when handling strings as `char` arrays, you absolutely always need to terminate the string with the null character. The standard functions are incrementing through the array, until they find the null character. If it is missing, they don't stop at the end of the array.

Needing the null character also means, that the above `char` array can only hold 9 characters (since the 10th is the null character).

The standard functions for creating a string (like `printf()` and its siblings) already terminate the string correctly with the null character.

---

You are obviously trying to send an ASCII encoded string. But `sensorval` is not a string, it is of type `int` (a number). In C/C++ one does not simply implicitly convert a number to a string (please insert the image of boromir from Lord of the Rings here in your head). You actually have to say the compiler how to convert the number to a string. Also `sensorval` cannot itself hold that string (as it is an integer number). For that you need a `char` array (often called c-string) for saving all the characters of your string.

So first we need to define the `char` array to hold our string:

```
char msg[10];

```

This creates a `char` array with 10 elements, each one can hold a character of your string. So you have space for 9 characters. If you need more, you can increase that number.

Now we need to build a string in `msg`, that represents the value of `sensorval`. For that we can use `sprintf()`, which lets us format a string out of data and save it in a `char` array.

```
sprintf(msg, "%d", sensorval);

```

The first parameter is the `char` array to put the string in. The second parameter is called format-string. That is a string literal, that defines the format. `%d` represents an integer value; it is a placeholder for the actual data and describes, how it should be formatted (you can read about the different format options in the C++ documentation if you search for `printf()`). The following parameters (here only one) are the data values for the placeholders in the format string. Let's take an example: Assume `sensorval` is 1000. Then `msg` will be:

```
1000\0

```

The `\0` being the null character.

So in your code you would replace

```
const char *msg = sensorval;

```

with

```
char msg[10];
sprintf(msg, "%d", sensorval);

```

---

**What you have done in your code:**

This line

```
const char *msg = sensorval;

```

will NOT create a string. You are defining `msg` as a pointer to a constant character (a pointer is a variable, that holds the address another variable in the memory, use google terms like "C pointers" for more info). And then you set the pointer to `sensorval`, which of course is not a valid pointer (valid meaning pointing to something reasonable here). It just points somewhere in the memory.

The example, that you got it from uses:

```
const char *msg = "hello";

```

This works, because the compiler takes all string literals (the strings enclosed by the double quotes) and puts them fixed into the memory, somewhat like a variable without a name. So here the compiler instructs the microcontroller so save the string `"hello"` in the memory. With the above line we define a pointer to the place in the memory, where this string is saved.

So this works good for string literals, but not, if you first need to actually build the string.
> 2 votes

---
Tags: arduino-ide, hc-sr04
---


title: Speaker-dependent Voice Recognition

text:
# Question
Title: Speaker-dependent Voice Recognition
I would like to install speaker-dependent voice recognition in a robot equipped with Arduino Uno compatible boards. Specifically, I want to record the robot's name beforehand and have it respond when I call the robot's name.

Although it is not an Arduino, there is a person who has developed a function that I would like to realize with the M5StickV. This person used isolated\_word.py, a library published by Sipeed, as a reference.

【K210】マイク搭載版M5StickV,Sipeed Maixシリーズで音声認識をする

After some research, I found Maix\_Speech\_Recognition in the library of Maixduino, which can use Arduino IDE. Apparently, it uses Mel-frequency cepstrum coefficients analysis of speech input, and then uses dynamic time stretching to find the similarity. The MFCC uses the K210 FFT on the Maixduino.

Arduino Uno does not have an FFT accelerator, but it can do FFT. Therefore, I thought it would be possible to use Maix\_Speech\_Recognition for specific speaker speech recognition on ArduinoUno compatible devices.

**Question**

1. Is it possible to use Maix\_Speech\_Recognition for speaker-dependent voice recognition on Arduino Uno compatible boards?
2. What part of Maix\_Speech\_Recognition should I modify to make it work on Arduino Uno compatible boards?

# Answer
> Is it possible to use Maix\_Speech\_Recognition for speaker-dependent voice recognition on Arduino Uno compatible boards?

No. It's not.

> What part of Maix\_Speech\_Recognition should I modify to make it work on Arduino Uno compatible boards?

Don't even think about it. The UNO *cannot* do anything even remotely like speech recognition of any form without adding extra specific speech recognition hardware.

Just get a K210 board - they're cheap enough.
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: Substring: What is causing my output to be truncated?
I suspect that I might be using too many resources, because of the strings, but I am new to Arduino, so not sure where I am going wrong. Any help would be appreciated.

What it should do when complete: "Birthday Reminder"

* Read the SD card for a "birthday" file ("MM-DD.txt" ) that matches "today".
* The file contains the Name of the person and year of birth.
* Flash LED's and display the person's name and age on the OLED.
* The unit will not displayed anything until someone's birthday.

I am using the SD card with a simple format, to easily add new birthday's.

```
Output:
⸮Initializing SD card...
card initialized.
25
111
opening: 04-25.txt
2020"Test Person"
bYearStr: 20

```

**The sd card file:**

```
Name: MM-DD.txt
Example: 04-25.txt

Contents: Birthyear, Name
Example: 2020"Test Person"

```

**The Sketch**

```
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"

RTC_DS3231 rtc;

int age;
int led;
int dly;
String bName;
String bYearStr;
int bYear;
int currentDay;
int  tDy;
int  tMth;
int  tYr;

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
  Serial.begin(9600);
  delay(3000); // wait for console opening

  // Setup Candle pins
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display(); // this command will display all the data which is in buffer
  display.setTextColor(WHITE, BLACK);

  const int SdCardPin = 10;
  Serial.println("Initializing SD card..."); // Verifying SD Card.
  //  if (!SD.begin(SdCardPin)) {
  if (!SD.begin(10)) {
    Serial.println("Card failed, or not present"); // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");

  currentDay = 111;
}

void loop() {
  age = 0;

  DateTime now = rtc.now();
  tDy = now.day();
  tMth = now.month();
  tYr = now.year();
  Serial.println(tDy);
  Serial.println(currentDay);

  if (currentDay != tDy) {
    String fileName;
    String m = String(tMth);
    String d = String(tDy);

    if (tMth < 10) {
      String mm = m;
      m = "0" + mm;
    }
    if (tDy < 10) {
      String dd = d;
      d =  "0" + dd;
    }
    fileName = m + "-" + d + ".txt";

    //String fileName = "01-01.txt";
    Serial.println("opening: " + fileName);
    File f = SD.open(fileName);
    delay(3000);

    if (!f) {
      Serial.println("open failed");
    } else {
      while (f.available()) {
        String line = f.readStringUntil('\n');
        Serial.println(line);
        bYearStr = line.substring(0, 4);
        bName = line.substring(4);
        delay(1000);
        currentDay = tDy;
        break;
      }
      f.close();
    }

    Serial.print("bYearStr: ");
    Serial.println(bYearStr);
    Serial.print("bName: ");
    Serial.println(bName);
    int bYear = bYearStr.toInt();
    age = tYr - bYear;
    Serial.print("Age: ");
    Serial.println(age);

  } else { // Start current day equal
    display.setTextSize(1);
    display.setCursor(38, 10);
    display.print("Birthday!");
    display.println();

    display.setTextSize(1);
    display.setCursor(0, 30);
    display.print("Name: ");
    display.print(bName);
    display.setCursor(0, 40);
    display.print("Age: ");
    display.print(age );
    display.println();

    led = random(3, 6);
    dly = random(80, 250);
    digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
    delay(dly);              // wait
    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  } // End current day

  display.display();

} // End void Loop

```

# Answer
It *is* quite likely you're out of memory. To know, really you need to keep track of the stack pointer and heap structure. There's enough going on in your code, that I'm not reasonably going to be able to set up an identical scenario to prove it.

### Display Library

The greatest use of SRAM in your project comes from the Adafruit SSD1306 library. It's allocating a buffer for the entire frame, which is 128 * 64 == 8192 bits, or 1024 bytes, half your Nano's SRAM. It will use more than that for other data, though probably not a lot more by percentage.

You may be able to mitigate this usage with a library like trades some SRAM usage for extra execution time or lower frame rates. One is the U8g2 library. You can read about how it can use half-buffer in some documentation to the older version of the library; the concept carries over to the newer library.

### SD Library

The next largest usage is the SD card libraries sector buffer, which is 512 bytes.

So between the two of them, there go 3/4 of your SRAM in just the two buffers, nevermind anything else.

You may be able to avoid this buffer by using a different library. You could try PetitFS. The library it wraps says it uses something like 44 bytes plus whatever call stack is needed.

### String Literals

You have at least 206 bytes of string literals in your sketch alone, assuming the compiler can't determine that any of them are in fact unused. There *may* be others in the libraries, though probably not many. So now we're down to at least 306 bytes or less SRAM.

| Size | String |
| --- | --- |
| 35 | `"RTC lost power, lets set the time!"` |
| 28 | `"Card failed, or not present"` |
| 24 | `"Initializing SD card..."` |
| 18 | `"Couldn't find RTC"` |
| 18 | `"card initialized."` |
| 12 | `"open failed"` |
| 11 | `"bYearStr: "` |
| 10 | `"opening: "` |
| 10 | `"Birthday!"` |
| 10 | `"01-01.txt"` |
| 8 | `"bName: "` |
| 7 | `"Name: "` |
| 6 | `"Age: "` |
| 5 | `".txt"` |
| 2 | `"-"` |
| 2 | `"0"` |
| 206 | *Total* |

The `"0"` is only counted once in the above, even though you have two of them. *Fun fact: the C and C++ languages allow identical string literals to be colocated or overlap. I don't know whether or not avr-gcc will combine `"Name: "` into `"bName: "`, since you have bigger problems to worry about, I'm just pretending it won't without looking.*

Mitigation can include use of the `F()` macro to move some of these string literals into PROGMEM (flash). You can't do this to every string literal, but the ones where you're involving them in a `String(F("we're trying to avoid these right?"))` constructor or in Serial (or other Stream/Print instances)'s `.print(F("Hello World"));`

The guts of the `F()` macro is another called `PSTR()`, which does the actual work of putting the string literal into PROGMEM. `F()` tags the resulting pointer with a dummy type that is used in function overloading in Arduino libraries. The only reason why I mention this is because below, you'll see me use `PSTR` to do the same thing, only with a function that belongs to avr-libc rather than Arduino.

Note when you're initializing a `String` object from a regular string literal, you're paying the SRAM cost twice for the lifetime of the `String` object. One copy is in SRAM for the literal used to call the String constructor, the other copy is in the dynamic memory allocated to the String object.

## String class

This was pointed out in the comments; and it's true that it's better to avoid them. Although, I think not actually the greatest problem in your case.

I see you've avoided unnecessarily adding them together for Serial output and instead are using separate `.print()` calls, so you're ahead of the game there.

For your filename, mitigation could be using fixed size local `char` array and `snprintf_P()` to cobble together your filename, something like:

```
char filename[sizeof "MM-DD.txt"];
snprintf_P(
    filename, sizeof filename,
    PSTR("%02u-%02u.txt"),
    tMth, tDy
);

```

or if you wanted to avoid pulling the beast of `printf` into your sketch, assuming it's not already there, you could do something like:

```
const char filename[] = {
    '0' + tMth / 10,
    '0' + tMth % 10,
    '-',
    '0' + tDy  / 10,
    '0' + tDy  % 10,
    '.',
    't',
    'x',
    't',
    '\0'
};

```

## Serial

What `Serial`? Yup, I mean, there's not a lot you can do about it, but I bring it up because the last conservative figure above was 306 bytes, and we didn't try to account for the what String is doing in the heap at all. Well Serial takes 157 bytes according to a simple test here, which makes sense, because on the UNO it has two ring buffers for transmit and receive that are 64 bytes in size each, half a dozen pointers for configuring hardware registers to use, and head and tail indices for those buffers. There's also another 12 bytes that are used for HardWareSerial's vtable.

So that puts you down to conservatively 137 bytes of SRAM for well, everything else.

### Everything Else

There's a lot not accounted for here. Your globals, the libraries globals, other vtables, the String data on the heap, and the stack. Those are just the ones coming to mind. I mean just the `millis()`/`micros()` counter variables and fract take 9 bytes. If you really want to dig into the details here, besides looking at the stack pointer and heap structure, the `avr-nm` command run on your sketch's .elf file with its `-D`, `-S`, and `--size-sort` is helpful for locating global variable usage and similar things.
> 3 votes

---
Tags: arduino-nano, sd-card, string
---


title: Basic hardware debouncing

text:
# Question
Title: Basic hardware debouncing
I was watching Jeremy Blum's Arduino tutorial series, and he explained the need for debouncing in a simple circuit involving a pushbutton. Pressing the button once should mean the led *stays* on, and pushing the button again should mean the led should *stay* off, and so on.

He implemented hardware debouncing on this circuit: using an RC circuit along with an inverting Schmitt trigger.

https://www.youtube.com/watch?v=CRJUdf5TTQQ&list=PLA567CE235D39FA84&index=10 2:45-8:45.

However, the circuit isn't performing as expected, when I implemented the denbuncing. Its behaving as if the debouncing has no effect:-

If anyone wants to see the simulation:- https://www.tinkercad.com/things/dniOQmnxJPY

Where exactly have I gone wrong? I have checked all the connections multiple times, it seems to be what Jeremy blum had in his video...

# Answer
> 2 votes
You did not change the lastbutton, but you compared it to HIGH. Change your code to the one below.

You can more easily avoid such mistakes, if you put spaces around operators.

```
//sp is switchpin, lp is ledpin

int sp=2; //interrupt enabled pin (interrupt 0)
bool ledon=LOW;
bool lastbutton=LOW;
int lp=9;
void setup()
{
  Serial.begin(9600);
  pinMode(sp, INPUT);
  pinMode(lp,OUTPUT);
}

void loop()
{

   if (digitalRead(sp)==HIGH && lastbutton==LOW){
      ledon=!ledon;
      lastbutton = HIGH; // previously here was lastbutton==HIGH;
   }

   else {
     lastbutton=digitalRead(sp);
      }
   Serial.println(ledon);
   digitalWrite(lp,ledon);

     }

```

---
Tags: debounce
---


# Question
Title: Would someone provide an example of extracting data from a char array?
* I have tried so many things now that I am just confused.
* I am not understanding the way *char arrays* work.
* I can't get the date and names extracted. And when I use just strings, I jam up the memory.

Below was my last attempt, before asking the question.

```
while (f.available()) {
  String line = f.readStringUntil('\n');

  if (line.startsWith("04-23")) {
    currentDay = 1;
    int str_len = line.length() + 1;
    char char_array[str_len];
    line.toCharArray(char_array, str_len);
    Serial.println(char_array);                 // Everything works to here
    for (int j = 0; j < 2; j++) {
      b += char_array[j];
    }
    bMth = b.toInt (); // This should be an int of the birth month in this case: 04
  }
}

Var:
format: MM-DD-YYYY,Name  // this is inside the file
line = "04-23-2020,James"  // This is the output from - Serial.println(char_array);

```

**What I am trying to do is**

* Extract the month/day so that I can compare it to today.
* The year so I can calculate the age.
* The name to display on OLED.
* Everything else seems to work, but I can't get my head wrapped around the **char array** access.

To do this in PowerShell I would do:

```
$line = "04-23-2020,James"

$dob = ($line.Split(","))[0]
$bMth = ($dob.Split("-"))[0] # This is not used in this example
$bDy = ($dob.Split("-"))[1]  # This is not used in this example
$bYr = ($dob.Split("-"))[2]

$age = $(get-date -UFormat %Y) - $bYr

Clear-Host
Write-Host (@'
Name: {0}
Age:  {1}

'@ -f $($line.Split(","))[1], $age)

```

In Python:

```
import datetime as dt

line = "04-23-2020,James"

dob = (line.split(',')[0])
bMth = (dob.split("-"))[0] # This is not used in this example
bDy = (dob.split("-"))[1]  # This is not used in this example
bYr = (dob.split("-"))[2]

age = int(dt.datetime.now().year) - int(bYr)

print('Name: ',(line.split(',')[1]))
print('Age: ', age)

```

# Answer
> 1 votes
When working with Arduino, cplusplus.com is your friend. Scroll down and look on the left side under **(string.h)**. Lot's of great `char` functions there. Other useful functions such as `iota()` \- cplusplus.com.

Here's one way to accomplish the parsing of the input data.

```
// Sketch uses 2064 bytes (6%) of program storage space.
// Global variables use 323 bytes (15%) of dynamic memory.
// Arduino IDE 1.8.9.
char line[] = "04-23-2020,James";
char Name[100];
unsigned int Month, Day, Year;

// Make an attempt to validate the input data.
byte Counter = 0;

void setup(){

  Serial.begin(9600);

  char * pch = strtok(line, "-,");

  while(pch != NULL){
    if(Counter == 0){Month = atoi(pch);}
    else if(Counter == 1){Day = atoi(pch);}
    else if(Counter == 2){Year = atoi(pch);}
    else if(Counter == 3){strcpy(Name, pch);}
    pch = strtok(NULL, "-,");
    Counter += 1;
  }

  // Print out the data.
  if(Counter == 4){
    Serial.println(Month);
    Serial.println(Day);
    Serial.println(Year);
    Serial.println(Name);
  }
  else{
    Serial.println("Error");
  }

}

void loop(){}

```

# Answer
> 0 votes
You could try sscanf if your data format is fixed, something like this:

```
char line[] = "04-23-2020,James";
int day, month, year;
char name[100];
if (sscanf(line, "%d-%d-%d,%s", &month, &day, &year, name) == 4)
{
    // Process the four items.
}

```

---
Tags: arduino-nano, c++, array
---


title: Interfacing LM35 and MQ2 with Arduino

text:
# Question
Title: Interfacing LM35 and MQ2 with Arduino
When I interface LM35 temperature sensor and MQ-2 gas sensor with Arduino - my LM35 sensor gave incorrect values. From research I've found out that MQ-2 gas sensor dragging the AREF voltage down and causing the error due to its 31ohm heater that drawn 161mA current . What'll I do to solve this problem?

# Answer
> 0 votes
A wiring diagram would help! But it sounds like you're powering your sensor from the Arduino's AREF pin. That is not the purpose of AREF; AREF is there for you to provide an accurate +5v or other reference voltage to the A/D convertor.

You need to power the sensor independently from your 5v supply (and not through the Arduino either, because of the sensors current draw); connect the sensor's Analog Out to one of the Arduino's A/D pins, sensor Ground to the supply ground. The digital out appears to be optional, if all you want is a go/no-go output that you adjust with the on-sensor potentiometer.

---
Tags: arduino-uno, sensors, hardware, temperature-sensor, lm35
---


title: Arduino Serial.readString() trouble

text:
# Question
Title: Arduino Serial.readString() trouble
Hello everyone I write my code and have some troubles. When I write on in my serial monitor my buzzer condition wasn't changed. Can you help me realize the reason. I wrote code with int type and it works with Serial.parseInt() function properly.

```
String ask="Please enter buzzer condition";
int buzzerPin=2;
String state;
void setup() {
  pinMode(buzzerPin,OUTPUT);
  Serial.begin(115200);

}

void loop() {
 Serial.println(ask);
 state=Serial.readString();
 Serial.println(state);
 while(Serial.available()==0){

 }
 if(state=="on"){
  digitalWrite(buzzerPin,HIGH);
 }
 if(state=="off"){
  digitalWrite(buzzerPin,LOW);
}
}

```

# Answer
You need to use `Serial.readStringUntil('\n')` instead of `Serial.readString` if you use the Arduino IDE's serial monitor (where a `\n` is added as termination character when you press enter). Also remove that `while(Serial.available()==0)`. It will wait as long as there are any bytes in the serial buffer and as you don't `Serial.read()` within the loop, the buffer will not be emptied. So, if anything is received while `Serial.println(state)` is called or if you send two termination characters, the program will be stuck in that loop.
> 1 votes

---
Tags: serial, arduino-mega, string, serial-data, print
---


# Question
Title: Why does my stepper motor run when I open the Serial port?
For some reason my motor moves a certain amount every time I open the serial port without giving it any other instructions. It will move further by the same amount if I close and reopen the serial port. Please could someone tell me how to avoid this? I haven't had this problem before.

I am using two stepper motors with a A4988 driver each.

Here is my code so far

```
#include <AccelStepper.h>
#include <MultiStepper.h>

// Define pin connections
const int dirPin1 = 2;
const int stepPin1 = 3;
const int dirPin2 = 4;
const int stepPin2 = 5;

String incomingByte; // for incoming serial data

// Define motor interface type
#define motorInterfaceType 1

// Creates an instance
AccelStepper stepper1(motorInterfaceType, stepPin1, dirPin1);
AccelStepper stepper2(motorInterfaceType, stepPin2, dirPin2);

MultiStepper steppers;

void setup() {
  Serial.begin(9600);
  String excess1 = Serial.readString();
  // Configure each stepper
  stepper1.setCurrentPosition(0);
  stepper2.setCurrentPosition(0);
  stepper1.setMaxSpeed(100);
  stepper2.setMaxSpeed(100);
  stepper1.setAcceleration(10);
  stepper2.setAcceleration(10);
  // Then give them to MultiStepper to manage
  steppers.addStepper(stepper1);
  steppers.addStepper(stepper2);
}

void loop() {
  // send data only when you receive data:
  if (Serial.available() > 0) {
    // read the incoming byte:
    incomingByte = Serial.readString();

    // say what you got:
    Serial.print("I received: ");
    //Serial.println(incomingByte, DEC);
    Serial.println(incomingByte);

    int x = incomingByte.toInt();

    long positions[2];

    positions[0] = x;
    positions[1] = 0;
    steppers.moveTo(positions);
    steppers.runSpeedToPosition();
  }
}

```

# Answer
> 1 votes
When you open or reopen the Serial port, the Arduino resets (depending on how you open it; some programs don't send the signal on DTR or RTS, which result in the reset).

My guess is, that the stepper driver reacts to the Arduino configuring its pins for the stepper. Difficult to say, what exactly happens there. To mitigate that, you can add an external pulldown resistor (assuming you have an active high stepper driver. For active low use a pullup resistor). That should keep the step line of the driver low even when its not actively driven by the Arduino.

---
Tags: arduino-uno, stepper, stepper-motor, a4988
---


title: Driving a servo with an ATTiny13A

text:
# Question
Title: Driving a servo with an ATTiny13A
So, I managed to fry my cheap servo/ESC (electronic speed controller) and decided to make my own using an ATTiny13A on some perfboard. But, I have run into some issues getting the servo to respond. I'm assuming the servo.h library is not compatible with the ATTiny13A because of incompatible internal clock speeds not creating the right PWM signals. And I haven't found a solution for this.

I have messed around with the Servo8Bit.h library, but this also doesn't seem to work (as its designed for the ATTiny45 and the ATTiny85 ). Is the ATTiny13A even able to produce the needed PWM signals?

Any help/links to documentation would be appreciated!

Thanks in advance.

Code:

```
#include <Servo.h>

Servo myservo;
int potpin = A3;
int val;    // variable
int Toggle = 2;

void setup() {
  Serial.begin(9600);
  pinMode(Toggle, INPUT);
  myservo.attach(1);  // Servo/ESC is attached to pb1
}

void loop() {
  int ToggleState = digitalRead(Toggle);
  Serial.println(ToggleState);
    val = analogRead(potpin);

  if (ToggleState == 0) {
  val = map(val, 0, 1023, 0, 180);  //Servo motor
   myservo.write(val);
  delay(15);
}
else {
  val= map(val, 0, 1023,1000,2000); //ESC
  myservo.write(val);
  delay(15);
 }
}

```

# Answer
> 1 votes
## Servo8Bit and ATTiny13(A)

I had a look at the Servo8Bit and had pretty much the same thoughts on this as Edgar Bonet in his comment:

> Servo8Bit relies on an 8-bit timer, and the ATtiny13A does have an 8-bit timer. It should not be too hard to port this library to that micro. Study the source code, then study the datasheet of the tiny13A (mostly the chapter dedicated to the timer). You should then be able to easily see what changes are needed.

Ignoring the timing differences between the ATTinyx5 and ATTiny13(A), I just went ahead and saw if I could get it to compile. And yeah, it's pretty easy to compile. This mostly consists of adding `0` to some hardware register names. The bad news is:

> Sketch **uses 1486 bytes (145%)** of program storage space. **Maximum is 1024 bytes.**
> Global variables use 31 bytes (48%) of dynamic memory, leaving 33 bytes for local variables. Maximum is 64 bytes.
>
> Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.
>
> Error during build: text section exceeds available space in board

So, yeah, that was a bit much to hope for, I guess. The library does use ISRs to support a number of servos kind of like the more common servo library that you'd use on an UNO. I haven't looked into chopping it down to size; I expect that will be impractical.

## PWM... sort of.

Prior to considering modifying Servo8Bit, I kind of thought it made sense to just use the timer counter directly to produce a waveform. The problem is the conventional servo signal is 20ms long, and does all of its control in a 1ms window. If you try to fit the whole 20ms frame into a single 8bit timing interval, what you end up with is pretty crappy angular control. So, doing it is a bit painful without a 16-bit timer counter. But, I guess that's the game.

So, the below is a crude and barely tested attempt at it. The code that follows is state machine inside the OCR0B overflow vector that schedules the rising an falling edges is "normal" mode. Just to warn you, I don't actually have an ATTiny13(A) on hand. And in fact I don't happen to have a servo hand either. But I do have an ancient storage scope and an ATTiny85 and the ability to compile for ATTiny13(A), and a calculator for working out the 8 MHz vs 9.6 MHz difference.

So here's what I came up with, which I *think* (but don't know) will work if you compile and upload using MCUDude MicroCore, ATTiny13(A) with the 9.6 MHz internal oscillator chosen.

It's only designed to operate 1 servo. Extending it to two should be easily doable. Going beyond that you're likely run into problems.

Code:

```
// +---------------------------------------------------------------------------------------+
// |                                                                                |
// |                                 +-------------+                                       |
// |                                 |             |                                       |
// |                                 |      A      |                                       |
// |  PCINT5 ADC0 dW  /RESET  PB5 *--|-1    T    8-|--* VCC                                |
// |                                 |      T      |                                       |
// |  PCINT3 ADC3      CLKI   PB3 *--|-2    I    7-|--* PB2  SCK   ADC1 T0         PCINT2  |
// |                                 |      N      |                                       |
// |  PCINT4 ADC2             PB4 *--|-3    Y    6-|--* PB1  MISO  AIN1 OC0B  INT0 PCINT1  |
// |                                 |      1      |                                       |
// |                          GND *--|-4    3    5-|--* PB0  MOSI  AIN0 OC0A       PCINT0  |
// |                                 |      A      |                                       |
// |                                 |             |                                       |
// |                                 +-------------+                                       |
// |                                                                                |
// +---------------------------------------------------------------------------------------+

#if !defined(__AVR_ATtiny13__) && !defined(__AVR_ATtiny13A__)
#error This code is written specifically for ATTiny13(A) devices.
#endif

#if F_CPU != 9600000
#error  This code is written specifically for 9.6 MHz
#endif

//
//
//
#include <avr/io.h>
#include <avr/interrupt.h>

//
//
//
constexpr uint8_t TCCR0A_config(
  int com0b // two bits
) {
  return
      (    0 << COM0A1) // normal
    | (    0 << COM0A0) //   port operation
    | (com0b << COM0B0) // bits 5 AND 4
    | (    0 <<      3) // reserved
    | (    0 <<      2) // reserved
    | (    0 <<  WGM01) //  lower two bits
    | (    0 <<  WGM00);//     of Normal (mode 0);
}

//
//
//
constexpr uint8_t TCCR0A_config_for_go_low()  {return TCCR0A_config(0x2);}
constexpr uint8_t TCCR0A_config_for_go_high() {return TCCR0A_config(0x3);}

//
// 50 Hz (hobby servo frame frequency); period 20 ms
//
// In the below you'll see the numbers 150 and 300 and 3000.
// The reason for these numbers is that I've chosen to to use a /64
// timer prescaler.  At 9.6 MHz, with a /64 prescaler, 1 millisecond
// is 150 timer timer counts.  There's as fixed 1 MS high in the servo,
// followed by 0 to 1ms variable portion.  The number 150 helpfully
// fits within the 8-bit timer registers and also gives a reasonable
// number of increments to the servo control.  For 180 degrees, 150 increments
// is 1.2 degrees.
//
// The maximum high time is the fixed 1ms high time and the maximum
// variable high time, totalling 2 MS, or 300 timer ticks, that's what that
// number is about.
//
// 3000 is the number of timer ticks for a full 20ms signal frame,
// that is 20 * 150 = 3000.
//
//
// Deriving the 150 figure:
//
//  At 9.6 MHz and /64 prescaler
//
//        1 second         64 mcu_cycles   A_MS_DURATION timer_counts
//  -------------------- X ------------- X ---------------
//  9_600_000 mcu_cycles   1 timer_count    0.001 seconds
//
//
//       1      64    A_MS_DURATION
//  --------- X -- X  -----
//  9_600_000   1     0.001
//
//
//     64       A_MS_DURATION
//  --------- X -----------
//  9_600_000      0.001
//
//
//     64 x A_MS_DURATION
//  --------------------
//        9_600
//
//
//  A_MS_DURATION
//  -------------
//      150
//

static constexpr uint8_t  ONE_MS_WORTH_OF_TICKS    = 150;
static constexpr uint8_t  MAXIMUM_HIGH_PERIOD      = ONE_MS_WORTH_OF_TICKS * 2;
static constexpr uint16_t TWENTY_MS_WORTH_OF_TICKS = 3000;
static constexpr uint16_t MAX_WASTE_CYCLES         = 0x80;

static volatile uint8_t g_pulse_width = ONE_MS_WORTH_OF_TICKS / 2;  // default to mid-range.

ISR(TIM0_COMPB_vect) {
  static uint8_t l_pulse_width; // this caches g_pulse_width
                                // and is updated from g_pulse_width
                                // only between frames

  //
  // The ISR is a state machine with four macro states.
  //
  enum class t_signal_generator_state : uint8_t {
    timing_to_variable_high_period,
    timing_to_set_pulse_width,
    calculate_time_to_start_of_next_pulse_and_waste_a_bit,
    timing_to_start_of_pulse
  };

  //
  // Macro state variable
  //
  static t_signal_generator_state g_signal_generator_state =
    t_signal_generator_state::timing_to_variable_high_period;

  // low_time_remaining is an extended state variable
  // for the timing_to_start_of_pulse state
  static uint16_t low_time_remaining;

  switch (g_signal_generator_state) {
    case t_signal_generator_state::timing_to_variable_high_period:
      // We just went high at the OCR0B value that triggered this interrupt
      // and we need to retrigger ((MAXIMUM_HIGH_PERIOD==300) - 256 == 44)
      // timing cycles later such that there are 256 timing cycles left of the
      // 2ms (maximum) high part of the frame.
      OCR0B += (MAXIMUM_HIGH_PERIOD - 256);  // 2ms worth of timer nicks minus the resolution of our timer

      // We're remaining HIGH as we head into the variable portion of the HIGH period.
      g_signal_generator_state = t_signal_generator_state::timing_to_set_pulse_width;
      break;
    case t_signal_generator_state::timing_to_set_pulse_width:
      // We're retrieving the global variable which holds a (potentially new) value from 0 to 150
      // representing a span of 0ms to  1ms (the full range of the servo), but
      // we're starting out the variable pulse a head of time, part way through the always-on first ms.
      // There are (150 - 44) timer cycles, that's 1 ms worth of timer cycles
      // where the timer remains high to finish out first millisecond of HIGH.
      // So we add this to the requested variale pulse width time.
      l_pulse_width = g_pulse_width + (ONE_MS_WORTH_OF_TICKS - 44);

      // Set adjust pulse width
      OCR0B += l_pulse_width;

      // We'll be going low and the end of the variable high period.
      TCCR0A = TCCR0A_config_for_go_low();

      g_signal_generator_state = t_signal_generator_state::calculate_time_to_start_of_next_pulse_and_waste_a_bit;
      break;

    case t_signal_generator_state::calculate_time_to_start_of_next_pulse_and_waste_a_bit:
      // We just went low at the OCR0B value.

      // Calculate remaining timer cycles to the beginning of the next pulse
      // accounting for the MAX_WASTE_CYCLES we're about to waste in this state.
      low_time_remaining = (TWENTY_MS_WORTH_OF_TICKS - 44 - MAX_WASTE_CYCLES) - l_pulse_width;
      OCR0B += MAX_WASTE_CYCLES;

      // We will remain LOW since the pulse is done and we've not finished out the 20ms period
      g_signal_generator_state = t_signal_generator_state::timing_to_start_of_pulse;
      break;

  case t_signal_generator_state::timing_to_start_of_pulse:
      // Continue retriggering the timer until we've used up 20ms total,
      // in increments of not more than MAX_WASTE_CYCLES.

      if (low_time_remaining > MAX_WASTE_CYCLES) {
        low_time_remaining -= MAX_WASTE_CYCLES;
        OCR0B += MAX_WASTE_CYCLES;
        // We'll need to wast more, so we're remaining LOW.
      } else {
        OCR0B += low_time_remaining;
        low_time_remaining = 0;

        // This is out last round through this state to finish out the 20ms
        // window, so we'll be returning to HIGH.
        TCCR0A = TCCR0A_config_for_go_high();

        g_signal_generator_state = t_signal_generator_state::timing_to_variable_high_period;
      }
      break;
  }
}

//
//
//
void servo_init() {
  const auto SREG_saved = SREG; cli();

  DDRB |= 1U << 1;  // Servo data pin attached on Attiny PB1 aka (OCR0B)

  // select no clock source / stop counter
  TCCR0B &= ~(
      (1U << CS02)
    | (1U << CS01)
    | (1U << CS00)
  );

  // reset counter
  TCNT0 = 0x00;
  OCR0B = 0x80;

  TIMSK0 =
      (0 <<      7) // reserved
    | (0 <<      6) // reserved
    | (0 <<      5) // reserved
    | (0 <<      4) // reserved
    | (1 << OCIE0B) // we *ARE*  using output-compare B interrupt
    | (0 << OCIE0A) // we aren't using output compare A interrupt
    | (0 <<  TOIE0) //             nor overflow interrupt
    | (0 <<      0);// reserved

  TIFR0 = 1U << OCF0A;

  TCCR0A = TCCR0A_config_for_go_high();

  TCCR0B =
      (0 << FOC0A) // We're not doing any
    | (0 << FOC0B) //   output compare forcing.
    | (0 <<     5) // Reserved.
    | (0 <<     4) // Reserved.
    | (0 << WGM02) // High order bit of Normal mode (0)
    | (0 <<  CS02) // Clock source
    | (1 <<  CS01) //    prescaled
    | (1 <<  CS00);//      by 64.

  SREG = SREG_saved;
}

//
//
//
void setup() {
  servo_init();
}

//
//
//
void loop() {
  for (g_pulse_width = 0; g_pulse_width < 150; ++g_pulse_width) {
    __builtin_avr_delay_cycles(F_CPU >> 5);
  }
  for (; g_pulse_width > 0; --g_pulse_width) {
    __builtin_avr_delay_cycles(F_CPU >> 5);
  }
}

//  vim:sw=2:ts=2:et:nowrap:ft=cpp:

```

On the scope, this produces servo signal that should sweep a servo on pin OCR0B (PB1). Something like 4 to 5 seconds going one way and same going back.

If I put an ATTiny13A on an order sometime and manage to dig out a servo myself, I'll actually test it. It may be a very long time before I can do that though. But the results on the scope look good. Admittedly everything is scaled by 9.6/8.0. It should be accurate on a ATTiny13(A). I verified that it compiles for it. The workings of the thing are explained in the code as I can.

For comparison:

> Sketch uses **490 bytes (47%)** of program storage space. Maximum is 1024 bytes.
> Global variables use 10 bytes (15%) of dynamic memory, leaving 54 bytes for local variables. Maximum is 64 bytes.

That's still a good chunk of what little code space you have, but it should be enough to read a switch and potentiometer. This is using the timer the device has, so `millis()`/`delay()` usage are kind of out-the-window, I think, I didn't try to see what happen when you call them or study their code in MicroCore. You *could* recreate your own `millis()` by making a timer overflow interrupt and it would overflow at about 1.7 ms intervals. As you can see, I just used `__builtin_avr_delay_cycles` to keep things simple.

If you, or anyone else, gets it working on at ATTiny13 before I try it myself, I'm curious to know that it worked (or didn't).

---
Tags: c++, servo, pwm, attiny
---


# Question
Title: Blynk, but continue program if Blynk connection fails
I'm having an issue with Blynk.begin(auth, ssid, pass); The problem is, when it fails to connect to the wifi, the rest of the program does not continue.

I'm using a Wemos D1 and it is also controlling some relays based on a temperature sensor. But when there was a power outage and power comes back on, the programs should continue whether the wifi is working or not, so that relays can still be controlled by the temperature sensor reading.

What happens now is if there is a wifi issue when Wemos D1 is starting up again, the program simply stops in the void setup() at Blynk.begin(auth, ssid, pass); and the rest of the program cannot be executed.

Anyone knows how to avoid this?

Kind regards, Peter

# Answer
You can try my Blynk\_WM or Blynk\_Async\_WM library with their Blynk.begin() functions are not blocking.

---

Check Why using this Blynk\_WiFiManager with MultiWiFi-MultiBlynk features

### Why using this Blynk\_WiFiManager with MultiWiFi-MultiBlynk features

You can see that the system **automatically detects and connects to the best or avaiable WiFi APs and/or Blynk Servers**, whenever interruption happens. This feature is very useful for systems requiring high degree of reliability.

Moreover, this `Blynk.begin()` is **not a blocking call**, so you can use it for critical functions requiring in loop().

Anyway, this is better for projects using Blynk just for GUI (graphical user interface).

In operation, if WiFi or Blynk connection is lost, `Blynk.run()` will try reconnecting automatically. Therefore, `Blynk.run()` must be called in the `loop()` function. Don't use:

```
void loop()
{
  if (Blynk.connected())
     Blynk.run();

  ...
}

```

just

```
void loop()
{
  Blynk.run();
  ...
}

```

---

It's also beneficial to search in Blynk Forum for more information and examples
> 0 votes

---
Tags: wifi, blynk
---


# Question
Title: MKR 1010 disconnects COM-port on each upload
Each time I attempt to upload to the *MKR WiFi 1010* board the COM-port gets disconnected, usually at one of the following points:

1. Either it disconnects just after compiling/verifying. In this case the `LED_BUILTIN` pulsates slowly, and the USB-cable needs to be reconnected in order to try again. The next attempt usually results in `2.`.
2. Or, it disconnects after a successful upload. The next attempt to upload will always result in `1.` occurring. When this happens the COM-port is still visible in Windows Device Manager but it can't be found by a Serial Monitor.

Any ideas what could be causing this or what could be done to have it stay connected? With an *UNO* this doesn't happen.

# Answer
> 1 votes
This was due to using a virtual machine (VMware) which apparently doesn't handle the MKR board COM-port so well. Moving the development environment to the host solved the problem. It still disconnects the COM-port after upload but then consistently reconnects to the same COM-port and that's good enough.

---
Tags: communication, windows, mkr1010
---


# Question
Title: How do I make my piezo buzzer only hum once without repetition?
I have a problem with getting my buzzer to only do the tones I programmed in *once*. I know I have to add some sort of code but I'm relatively new to this so I don't really know. I want it to start playing the tones I have in the code once I press the button. After that it should immediately stop, without looping everything until I press the button again. Basically I have these LEDs that light up in a row with every time I press my button and once the last LED lights up, the buzzer should play its melody. After that, I can press my button again and the whole thing starts from the beginning. If anyone could help, I'd be more than grateful!

This is my code:

```
#define button 3

#define LED 1
#define twoLED 2
#define threeLED 4
#define fourLED 5
#define fiveLED 6
#define sixLED 7
#define sevenLED 8
#define eightLED 9
#define nineLED 10
#define tenLED 11

int state = 0;
int old = 0;
int buttonPoll = 0;

void setup() {
  pinMode (3,INPUT);
  pinMode (11,OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(twoLED, OUTPUT);
  pinMode(threeLED, OUTPUT);
  pinMode(fourLED, OUTPUT);
  pinMode(fiveLED, OUTPUT);
  pinMode(sixLED, OUTPUT);
  pinMode(sevenLED, OUTPUT);
  pinMode(eightLED, OUTPUT);
  pinMode(nineLED, OUTPUT);
  pinMode(tenLED, OUTPUT);

  digitalWrite(LED, LOW);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);

}

void loop() {

  buttonPoll = digitalRead (3);
  if (buttonPoll ==1) {
    delay (50);
    buttonPoll = digitalRead (3);
    if (buttonPoll == 0) {
      state = old + 1;
    }
  }
  else {
    delay(100);

  }

  switch (state) {
    case 1:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 2:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 3:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 4:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 5:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 6:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 7:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 8:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 9:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, HIGH);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 10:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, HIGH);
  digitalWrite(tenLED, HIGH);
   old = state;

       tone (11,261);
      delay(250);

      tone(11, 330);
      delay(250);

      tone(11,391.99);
      delay(250);

      tone(11,440);
      delay(250);

      tone(11, 391.995);
      delay(250);

      tone(11, 330);
      delay(250);

        }

    break;

   default:
  digitalWrite(LED, LOW);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);

    old = 0;

    break;

  }
}

```

# Answer
> 0 votes
Enshrine the first section of the `loop()` code inside a `while` loop.

```
while (condition)
{
    // this code executes continually until 'condition' is true
}

```

In your case, the variable `state` changes when an active button press is recorded: use that as your `condition`.

```
while (state == old)
{
  buttonPoll = digitalRead (3);
  if (buttonPoll ==1)
  {
    delay (50);
    buttonPoll = digitalRead (3);
    if (buttonPoll == 0)
    {
      state = old + 1;
    }
  }
  else
  {
    delay(100);
  }
}

```

So long as `state` stays the same, i.e. it equals `old`, the code within the `while` loop will execute indefinitely. *NOTE:* Any code outside the `while` loop will effectively only run once. You may find, if you expand the code, most of it lives within the `while` loop. If that is the case there may be better approach to consider.

# Answer
> 0 votes
Once the LEDs & Piezo sequence finishes, your code doesn't wait for the button to be pressed again. If the button is not pressed, the code doesn't wait, it merely delays for 100ms, then repeats the sequence.

# Answer
> 0 votes
Welcome to ASE :)

1. You have mapped the Tone function and the LED to the same Pins. So, you may have to find another pin for the buzzer (pin 0 )
2. I have taken code from @charlieHanson as well.
3. The braces for the switch statement were put in the wrong place. I have fixed it.

Have a try: The code is here

```
#define button 3

#define LED 1
#define twoLED 2
#define threeLED 4
#define fourLED 5
#define fiveLED 6
#define sixLED 7
#define sevenLED 8
#define eightLED 9
#define nineLED 10
#define tenLED 11

int state = 0;
int old = 0;
int buttonPoll = 0;

void setup() {
  pinMode (3, INPUT_PULLUP);
  pinMode (11, OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(twoLED, OUTPUT);
  pinMode(threeLED, OUTPUT);
  pinMode(fourLED, OUTPUT);
  pinMode(fiveLED, OUTPUT);
  pinMode(sixLED, OUTPUT);
  pinMode(sevenLED, OUTPUT);
  pinMode(eightLED, OUTPUT);
  pinMode(nineLED, OUTPUT);
  pinMode(tenLED, OUTPUT);

  digitalWrite(LED, LOW);
  digitalWrite(twoLED, LOW);
  digitalWrite(threeLED, LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);

}

void loop() {

  while (state == old)
  {
    buttonPoll = digitalRead (3);
    if (buttonPoll == 1)
    {
      delay (50);
      buttonPoll = digitalRead (3);
      if (buttonPoll == 0)
      {
        state = old + 1;
      }
    }
    else
    {
      delay(100);
    }
  }

  switch (state) {
    case 1:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, LOW);
      digitalWrite(threeLED, LOW);
      digitalWrite(fourLED, LOW);
      digitalWrite(fiveLED, LOW);
      digitalWrite(sixLED, LOW);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 2:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, LOW);
      digitalWrite(fourLED, LOW);
      digitalWrite(fiveLED, LOW);
      digitalWrite(sixLED, LOW);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 3:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, LOW);
      digitalWrite(fiveLED, LOW);
      digitalWrite(sixLED, LOW);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 4:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, HIGH);
      digitalWrite(fiveLED, LOW);
      digitalWrite(sixLED, LOW);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 5:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, HIGH);
      digitalWrite(fiveLED, HIGH);
      digitalWrite(sixLED, LOW);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 6:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, HIGH);
      digitalWrite(fiveLED, HIGH);
      digitalWrite(sixLED, HIGH);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 7:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, HIGH);
      digitalWrite(fiveLED, HIGH);
      digitalWrite(sixLED, HIGH);
      digitalWrite(sevenLED, HIGH);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 8:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, HIGH);
      digitalWrite(fiveLED, HIGH);
      digitalWrite(sixLED, HIGH);
      digitalWrite(sevenLED, HIGH);
      digitalWrite(eightLED, HIGH);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 9:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, HIGH);
      digitalWrite(fiveLED, HIGH);
      digitalWrite(sixLED, HIGH);
      digitalWrite(sevenLED, HIGH);
      digitalWrite(eightLED, HIGH);
      digitalWrite(nineLED, HIGH);
      digitalWrite(tenLED, LOW);
      old = state;
      break;

    case 10:
      digitalWrite(LED, HIGH);
      digitalWrite(twoLED, HIGH);
      digitalWrite(threeLED, HIGH);
      digitalWrite(fourLED, HIGH);
      digitalWrite(fiveLED, HIGH);
      digitalWrite(sixLED, HIGH);
      digitalWrite(sevenLED, HIGH);
      digitalWrite(eightLED, HIGH);
      digitalWrite(nineLED, HIGH);
      digitalWrite(tenLED, HIGH);
      old = 0;
      state = 0;

      tone (11, 261);
      delay(250);

      tone(11, 330);
      delay(250);

      tone(11, 391.99);
      delay(250);

      tone(11, 440);
      delay(250);

      tone(11, 391.995);
      delay(250);

      tone(11, 330);
      delay(250);
      noTone(11);

      break;

    default:
      digitalWrite(LED, LOW);
      digitalWrite(twoLED, LOW);
      digitalWrite(threeLED, LOW);
      digitalWrite(fourLED, LOW);
      digitalWrite(fiveLED, LOW);
      digitalWrite(sixLED, LOW);
      digitalWrite(sevenLED, LOW);
      digitalWrite(eightLED, LOW);
      digitalWrite(nineLED, LOW);
      digitalWrite(tenLED, LOW);

      old = 0;

      break;

  }
}

```

Here is the preview :)

Here is the Arduino simulator link: https://wokwi.com/arduino/projects/297098737606459913

---
Tags: button, loop, piezo, buzzer
---


# Question
Title: Can i use PL2303 USB to TTL Serial Converter Module send keystrokes using Arduino nano?
If I can, which library to use (an example code will be great). Here is the module:

# Answer
> 1 votes
No. That is serial. Just like every other USB to TTL Serial converter. The clue is in the name.

You need an Arduino with a dedicated native USB interface, like those based on the ATMega32U4 chip.

Or dedicated software on the PC that will read serial data and emulate keypresses (which is outside the scope of this website).

---
Tags: serial, arduino-nano, usb, keyboard
---


# Question
Title: Basic doubt regarding encoders with Arduino
I created a program that measures the pulses set out by the encoder (part of the dc motor with encoder inbuilt), and uses the ppr value (pulses per rotation) to calculate the rotations per minute (rpm)

However, the serial monitor continuously shows 0 for the variable "pulsecount", that maintains the total pulses sent.

code:

```
float ppr=512.0;
int encpin=3;
volatile long pulsecount=0;
float revs;
float rps;
float rpm;
unsigned long time;

void setup()
{
  pinMode(encpin,INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //when pulse is detected
                                           //interrupt triggered,
                                           //function callled
}
void function(){
  pulsecount+=1;
}

void loop()
{
 revs= pulsecount/ppr ;
 time=millis()/1000;
 rps=revs/time ;
 rpm=revs*60;
 Serial.println(pulsecount);
}

```

# Answer
You code counts pulses just fine when tested here.

Fan/motor tachometer outputs and encoders frequently are set to switch your signal contact to ground, either with a transistor or mechanically. When the ground contact is not being made, the signal connection is floating and not reliably HIGH. So, you need a pullup resistor on the pin, just like you do for a typical push button switch configured to switch to ground.

My comment on the question:

> What happens if you use `INPUT_PULLUP` rather than `INPUT`?

was referring to doing this in your code:

```
pinMode(encpin, INPUT_PULLUP);

```

At higher frequencies, higher RPM, you may need to use an external resistor to get a lower resistance value than the 20k-50k of the internal pullup resistor that `INPUT_PULLUP` enables.

It is best to turn off interrupts when you retrieve your `volatile` pulse counter variable so that there's no tearing of the value where the ISR interrupts your code mid-read and updates the latter half of the value.

e.g.:

```
// Note I've switched your pulsecount variable
//  to unsigned long for this example.
unsigned long get_pulsecount() {
  noInterrupts();
  const auto r = pulsecount;
  interrupts();
  return r;
}

```

Note you can probably avoid `float` usage altogether, and should if you can.
> 2 votes

# Answer
It is hard to find the error in these TinkerCad examples, because I do not know where to find the datasheet of the components used there and I am never sure, what am I debugging, the program or Tinkercad?

Anyhow, the encoder simulated there needs to be connected with a pull-up resistor. Arduino has a built-in pullup and you can activate via the `pinmode()` function:

```
void setup()
{
  pinMode(encpin,INPUT_PULLUP); //  before here was pinMode(encpin,INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //when pulse is detected
                                           //interrupt triggered,
                                           //function callled
}

```

But notice: your types are all over the place and I expect that you get some bugs due to this. Avoid to divide float and int variables without converting, especially this can cause trouble, because you might divide by 0:

```
 time=millis()/1000;
 rps=revs/time ;

```

Also it is a long shot to have basic doubts regarding encoders and arduino, just because some code does not work. Many people are using encoders all the time and countless libraries of encoders have been published for arduino.
> 0 votes

---
Tags: rotary-encoder
---


# Question
Title: why can Arduino variables of int type contain a value such as A2
How come the following statement is true:

```
int inputPin = A2;

```

I thought int variables can only hold integer numbers. Is the `A` just a representation of a number?

Thanks for any help

# Answer
> 2 votes
You are correct. `A2` is just a number (like everything in a microcontroller). We can look at the corresponding part in `pins_arduino.h` (a file defined in the variants folder of your used core and of your used board, for me: `~/arduino-1.8.9/hardware/arduino/avr/variants/standard/pins_arduino.h`):

```
#define PIN_A0   (14)
#define PIN_A1   (15)
#define PIN_A2   (16)
#define PIN_A3   (17)
#define PIN_A4   (18)
#define PIN_A5   (19)
#define PIN_A6   (20)
#define PIN_A7   (21)

static const uint8_t A0 = PIN_A0;
static const uint8_t A1 = PIN_A1;
static const uint8_t A2 = PIN_A2;
static const uint8_t A3 = PIN_A3;
static const uint8_t A4 = PIN_A4;
static const uint8_t A5 = PIN_A5;
static const uint8_t A6 = PIN_A6;
static const uint8_t A7 = PIN_A7;

```

So here the core first defines the macro `PIN_A2` as 16 (which is the pin number of that pin) and then it declares a static constant `A2` with `PIN_A2`. So `A2` is just the pin number of that pin, `16` in this case.

This is done to make the code more readable. The analog pins are marked with `A0` to `A7`, so it is good to also be able to refer to that with these names. If you wanted, you could also use the pin number directly. But that wouldn't be as easy to read.

# Answer
> 0 votes
The value of the symbol 'A2' *is* an integer - it is an Arduino pin number. For an Uno, it is equal to 16. Are you maybe confusing the pin number, A2, with the value read from A/D channel 2? That would be the value returned by `analogRead(A2)` or `analogRead(PIN_A2)` as it has been #define'd. And even then, that value is also an integer between 0 and 1023, which represents the voltage on the pin, 0 representing 0v or Ground, and 1024 representing the reference voltage (therefore, 1023 represents any voltage that is greater or equal to ((1023/1024) * Vref).

---
Tags: arduino-uno, variables
---


title: Millis timer question

text:
# Question
Title: Millis timer question
Trying to figure out how to do this in millis. So right now the code works just fine, plays mp3\_play(2) while a push button is closed then plays mp3\_play(1) when its open. Lets say I want mp3\_play(2) to play while the push button closed but after 4 seconds if the button is still closed another audio file will be triggered to play. Cant figure that one out.

thanks Jason

```
void fire(){

  int reading = digitalRead(buttonPin);

  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {

    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == HIGH) {
        mp3_play (1); //power down sound
      }

      if (buttonState == LOW) {
        mp3_play (2);  // fire sound
      }

    }
  }
  lastButtonState = reading;
}

```

# Answer
> 1 votes
You have to keep track of time once a button is pressed (LOW). So `buttonLowTime` is initialized every time you press the button. In the `if` logic, you first check if the `buttonstate` is `LOW` and if the said time has been passed.

But you also mentioned you want to play the audio once. So you need to keep track if you already played the audio. So, a flag, `timeoutAudioPlayed` has been created to keep track of that. So, now, the 3rd audio will only play if:

1. The button is pressed
2. and is pressed for more than said time (`BUTTON_LOW_TIME_MAX`)
3. and if the audio hasn't been played.

>

```
void fire()
{
  static int buttonLowTime = 0; <-------------------
  static bool timeoutAudioPlayed = true; <---------

  int reading = digitalRead(buttonPin);

  if (reading != lastButtonState)
  {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay)
  {
    if (reading != buttonState)
    {
      buttonState = reading;

      if (buttonState == HIGH)
      {
        mp3_play (1); //power down sound
      }

      if (buttonState == LOW)
      {
        mp3_play (2);  // fire sound
        buttonLowTime = millis(); <-----------
        timeoutAudioPlayed = false; <---------
      }
    }
  }

  // The logic for timeout audio <------------
  if((buttonState == LOW) && (millis() - buttonLowTime) > BUTTON_LOW_TIME_MAX && timeoutAudioPlayed == false)
  {
    mp3_play (3);
    timeoutAudioPlayed = true;
  }

  lastButtonState = reading;
}

```

---
Tags: millis
---


# Question
Title: Can someone help me figure out why only one wheel is spinning?
I am attempting to use a code which I have posted below for two wheels. However, when connected to power, only one wheel spins. I am using a 9V battery which is what was suggested so I am not sure why only one wheel spins. When both wheels are connected, the wheel that was originally working stopped spinning.

```
#include <SPI.h>      //SPI library for communication with the nRF24L01+
#include "RF24.h"  //The main library of the nRF24L01+
#include "Wire.h"

RF24 radio (8, 9); // CE,CSN

//Create a pipe addresses for  communication
const uint64_t pipe = 0xE8E8F0F0E1LL;

struct package
{
  int X = 1;
  int Y = 1;
};

typedef struct package Package;
Package pos;

int buttonState;
int spinnerState = false ;
int motora_1 = 3;
int motora_2 = 4;
int motorb_1 = 5;
int motorb_2 = 6;
int spinner = 2;

void setup()
{
  Serial.begin(9600);
  radio.begin();                    //Start the nRF24 communicate
  radio.openReadingPipe(1, pipe);   //Sets the address of the transmitter to which the program will receive data.
  radio.startListening();
  pinMode(motora_1, OUTPUT);
  pinMode(motora_2, OUTPUT);
  pinMode(motorb_1, OUTPUT);
  pinMode(motorb_2, OUTPUT);
  pinMode(spinner, OUTPUT);
  digitalWrite(spinner, LOW);
  delay(100);
}

void loop()
{

  if (radio.available()) {
    radio.read(&pos, sizeof(pos));
    radio.read(&buttonState, sizeof(buttonState));
    Serial.print("X:");
    Serial.print(pos.X);
    Serial.print("      Y");
    Serial.print(pos.Y);
    Serial.print("      buttonState");
    Serial.println(buttonState);
  }

  int xAxis = pos.X;
  int yAxis = pos.Y;
  int forward = map(yAxis, 570, 1024, 0, 255);
  int backward = map(yAxis, 480, 0, 0, 255);
  int right = map(xAxis, 570, 1024, 0, 255);
  int left = map(xAxis, 480, 0, 0, 255);

  if (yAxis > 570) {          // Move Forward
    // Set Motor A forward
    analogWrite(motora_1, forward);
    analogWrite(motora_2, 0);
    // Set Motor B forward
    analogWrite(motorb_1, forward);
    analogWrite(motorb_2, 0);
  } else if (yAxis < 480) {                     //Move Backward
    // Set Motor A backward
    analogWrite(motora_1, 0);
    analogWrite(motora_2, backward);
    // Set Motor B backward
    analogWrite(motorb_1, 0);
    analogWrite(motorb_2, backward);
  } else if (xAxis > 570) {                     // Move Right
    // Set Motor A forward
    analogWrite(motora_1, right);
    analogWrite(motora_2, 0);
    // Set Motor B stop
    analogWrite(motorb_1, 0);
    analogWrite(motorb_2, 0);
  } else if (xAxis < 480) {                     // Move Left
    // Set Motor A stop
    analogWrite(motora_1, 0);
    analogWrite(motora_2, 0);
    // Set Motor B foward
    analogWrite(motorb_1, left);
    analogWrite(motorb_2, 0);
  } else  {     //stop
    // Set Motor A stop
    analogWrite(motora_1, 0);
    analogWrite(motora_2, 0);
    // Set Motor B stop
    analogWrite(motorb_1, 0);
    analogWrite(motorb_2, 0);
  }

  if (buttonState == 0 ) {
    spinnerState = ! spinnerState;
    delay(50);
  }

  if (spinnerState == true) {
    digitalWrite(spinner, HIGH);    //turn On spinner
    delay(100);
  } else {
    digitalWrite(spinner, LOW);      //turn Off spinner
    delay(100);
  }

}

```

# Answer
> 2 votes
Firstly, the 9V batery is going to struggle with driving two motors. Change this 9V battery out with another power source.

As @timemage points out in his comment, you are using a PWM command on a non-PWM pin. For the Arduino Uno, the PWM pins are: 3, 5, 6, 9, 10, 11. Move the wiring and change the code so that it is using pin 9, 10 or 11 instead of pin 4.

It sounds like you are trying to test your hardware setup and your firmware at the same time. It is much easier to test your hardware first and make sure that works as expected before testing your firmware. I suggest writing a simpler program (the simpler the better) that just drives the motors full forward - one at a time and then together. Verify that it works and then change your test program so the motors spin in (full) reverse. Then change your test program so it changes the speed of the motors. Then with known working hardware test your firmware.

---
Tags: arduino-uno
---


# Question
Title: Blew my arduino pro mini s4 named component
While working on my project I supplied 12v to my pro mini through raw input and then a s4 named component smoked and my pro mini stopped working . It didn't turn on either through vcc or raw. The voltage regulator seems completely fine. Can I repair my pro mini. Please help.

# Answer
> 2 votes
Many Arduinos have a Schottky diode between the power connector and the voltage regulator as a protection against accidental reverse polarity connection. The official Pro Mini, or the Sparkfun variant, does not.

So you can either de-solder the diode or break it off the board using diagonal cutters and then replace it with either a similar diode -- or with a solder-bridge if you are confident about never connecting power the wrong way around.

It's possible (likely even) that other components that look OK visually are actually damaged. Especially if you can't power the board by connecting a regulated 5V supply to the VCC pin.

# Answer
> 0 votes
Once you have removed the diode as described in @RedGrittyBrick's answer, you will need to replace it with another. Note you don't have to replace it with a SMD version if you can't get your hands on one. Most electronics shops sell a 1N4004 or 1N4007 diode which would be a suitable replacement.

If worst comes to worst, you could solder a blob of solder across the diode's pads - which would mean you lose the reverse polarit protection - but it would provide a path for your voltage input to go into the regulator.

---
Tags: arduino-pro-mini
---


title: ESP8266 ISO 8601 string to tm struct

text:
# Question
Title: ESP8266 ISO 8601 string to tm struct
I have a web service that returns timestamps in ISO 8601 format, e.g., `"2021-06-25T12:00:00"` I'm trying to turn the timestamp string into a tm type struct from the ESP8266 library `<time.h>`, to perform time calculations using the `difftime()` function.

I've been referring to the Redhat time functions https://sourceware.org/newlib/libc.html#time, as it seem to be compatible with the ESP library, though all i can find are functions converting tm structs to timestamp strings. Are there any functions to convert a string timestamp into a tm struct and then back into epoch? Or what would be the best way to approach this kind of conversion on the ESP8266 platform?

# Answer
> 3 votes
Try `strptime` from the `time.h`.

```
void setup()
{

  struct tm tm = {0};
  char buf[100];

  // Convert to tm struct
  strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm);

  // Can convert to any other format
  strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
  Serial.printf("%s", buf);
}

void loop()
{
    yield();
}

```

---
Tags: esp8266, c++, time
---