# Question
Title: Can't manually connect HC-05 master to slave
Using this as a tutorial, I've tried to connect the master Bluetooth module from my Nano to the slave module in my Mega. After following the steps in the tutorial, when I enter the command to my serial monitor:

```
AT+BIND=98d3,31,30690

```

I receive:

```
ERROR:(7)

```

After looking up the error, I only get results for ERROR:(0)

Does anyone know what the error means or how to fix it?

# Answer
> 1 votes
I found the solution.

Apparently, both of my modules were at `9600` baud rate when the optimal rate is of `38400`. I had to use `AT+ORGL` in command mode to reset both slave and master. Afterwards I was able to connect them manually.

So apparently `ERROR:(7)` represents a failed connection? Just don't forget to make sure everything is exactly like the tutorial that's teaching you.

# Answer
> 0 votes
You need to add zeros to your address.
For example my address of slave is "FCA8:A7:A134"
So command to bind it to master will be "AT+BIND=FCA8,7A,00A134"
XXXX:XX:XXXXXX

---
Tags: bluetooth, hc-05
---


title: Large number into variable

text:
# Question
Title: Large number into variable
Probably something easy but I’ve not resolved it.

I’m extracting data from a JSON string and all the values are correct accept for two.

They are referring to two date time values and are in milliseconds.

One is the date refreshed and the other is date updated.

Problem is they are both very large and I’m having difficulty assigning them in the IDE.

One is 1588447162117 which is showing as 020-05-02 20:19:53.948 on the dashboard using the JSON.

Here is the code I have thus far to get the data from JSON:

```
#include <ArduinoJson.h>

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

  const char* input = "{TotalCases:3308678,TotalCasesToday:4458,TotalDeaths:234123,TotalDeathsToday:293,TotalRecovered:1042991,TotalTerritories:124,CurrentUpdatedMS:1588312648603,CurrentChangedMS:1588312648603}";

  StaticJsonDocument<512> doc;

  DeserializationError err = deserializeJson(doc, input);

  if (err) {
    Serial.print("Error: ");
    Serial.println(err.c_str());
    return;
  }

  unsigned long TotalCases = doc["TotalCases"];
  unsigned long TotalCasesToday = doc["TotalCasesToday"];
  unsigned long TotalDeaths = doc["TotalDeaths"];
  unsigned long TotalDeathsToday = doc["TotalDeathsToday"];
  unsigned long TotalRecovered = doc["TotalRecovered"];
  unsigned long TotalTerritories = doc["TotalTerritories"];
  unsigned long CurrentUpdatedMS = doc["CurrentUpdatedMS"];
  unsigned long CurrentChangedMS = doc["CurrentChangedMS"];

  Serial.print("Total Cases: ");
  Serial.println(TotalCases);
  Serial.print("Total Cases Today: ");
  Serial.println(TotalCasesToday);
  Serial.print("Total Deaths: ");
  Serial.println(TotalDeaths);
  Serial.print("Total Deaths Today: ");
  Serial.println(TotalDeathsToday);
  Serial.print("Total Recovered: ");
  Serial.println(TotalRecovered);
  Serial.print("Total Territories: ");
  Serial.println(TotalTerritories);
  Serial.print("Update time in ms:");
  Serial.println(CurrentUpdatedMS);
  Serial.print("Change time in ms:");
  Serial.print(CurrentChangedMS);
}

void loop()
{

}

**Serial monitor output**

Total Cases: 3308678
Total Cases Today: 4458
Total Deaths: 234123
Total Deaths Today: 293
Total Recovered: 1042991
Total Territories: 124
Update time in ms:0
Change time in ms:0

```

Should be good to manipulate it once I can work with it in a variable.

Thanks for any input,

Shane

# Answer
I didn't try myself, but just by looking at the docs I suggest you try:

1. Adding

```
#define ARDUINOJSON_USE_LONG_LONG 1

```

at the top of the sketch, before including ArduinoJson.h.

2. Declare `CurrentUpdatedMS` and `CurrentUpdatedMS` as either `unsigned long long` or `uint64_t`.

**Edit**: To answer the question in the comment:

> When you said you looked at the docs where did you check?

I had to follow a (not so simple) path: Deserialization tutorialJsonDocument::operator\[\]JsonVariantJsonVariant::as\<T\>(). This last page states that the method `as<unsigned long long>()` “may require ARDUINOJSON\_USE\_LONG\_LONG”. Unfortunately, the macro is not linked, so I have to search for it and found `ARDUINOJSON_USE_LONG_LONG`.
> 1 votes

---
Tags: arduino-ide, json
---


# Question
Title: How to use AT+CFTRANTX command in SIM7100
I am working on a project using pro mini 8MHz/3.3v and SIM7100, I want to know how can I used AT+CFTRANTX command. I am try to read file from EFS and write to SD card via Serial port. I have get some data in SD but is junk.

My board is Arduino Pro Mini (ATMega 328) 8MHz/3.3 V datasheet (DEV-11114) and Modem is home-made board with SIM7100 module, already test board and module work with all functions without any problem. I’ve added a schematic of the board to the question.

Here is SIM7100 Schematic

Here is SD Module, Pro Mini and SIM7100 pin layout

c:\data2.txt is: A1 to F0

A1A2A3A4A5A6A7A8A9A0B1B2B3B4B5B6B7B8B9B0C1C2C3C4C5C6C7C8C9C0D1D2D3D4D5D6D7D8D9D0E1E2E3E4E5E6E7E8E9E0F1F2F3F4F5F6F7F8F9F0

Any help would be appropriated.

The code that I am using, I tried it with every possible baud rate:

```
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
SoftwareSerial simSerial(7, 6);
File myFile;

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  simSerial.begin(9600);
  Serial.print("\nInitializing SD card...");

  if (!SD.begin(10)) {
    Serial.println("\nInitialization failed!");
    while (1);
  }
  Serial.println("\nInitialization done.");
  delay(8000); //For booting SIM7100
  if (SD.exists("1.TXT")) SD.remove("1.TXT");

  myFile = SD.open("1.txt", FILE_WRITE);
  if (myFile) {
    simSerial.println("AT+CFTRANTX=\"c:/data.txt\"");
    while (simSerial.available() > 0) {
      byte voc = simSerial.read();
      myFile.write(voc);
    }
    myFile.close();
    // Serial.println("\nClose done.");
  } else {
    // Serial.println("Error opening 1.txt");
  }

  // re-open the file for reading:
  myFile = SD.open("1.txt");
  if (myFile) {
    Serial.println("1.txt:");
    while (myFile.available()) {
      Serial.print(myFile.read());
    }
    myFile.close();
    Serial.println("\nReading SD Card done.");
  } else {
    Serial.println("Error opening 1.txt");
  }

}

void loop() {

}

```

Here is test sketch for software & hardware serial.

```
SoftwareSerial mySerial(7,6); // RX, TX

void setup()
{
  Serial.begin(9600);
  while (!Serial) {
    ;
  }
  Serial.println("Hardware Serial port!");
  mySerial.begin(9600);
  mySerial.println("AT+CFTRANTX=\"c:/data.txt\"");
}

void loop() // run over and over
{
  if (mySerial.available())
    Serial.write(mySerial.read());
  if (Serial.available())
    mySerial.write(Serial.read());
}

```

# Answer
> 0 votes
The Manual v1.02 of Sim7100 with all the commands can be downloaded here
Here is code to test it compiled for UNO without warnings and errors: Please test it and give feedback (read the comments to get the flow of code) Test with the RX/TX of the Sim7100 to pins 4/5 (Software Serial and the Sim7100 to baud rate 9600):

```
#include <SPI.h>
#include <SD.h>

#include <SoftwareSerial.h>

#define SD_ChipSelectPin 10

SoftwareSerial simSerial(5, 6); // RX, TX to TX RX of the SIM7100 module
//#define simSerial Serial
char receiveArray[256] = {'\0'};
void readSerialPort(uint8_t);
uint8_t counter = 0;

void setup() {
   Serial.begin(57600);
    while (!Serial) {
     ;
    }
  simSerial.begin(9600); // using HW Serial on a Pro Mini
  while (!simSerial) {
    ;
  }

  simSerial.println("AT+IPR=9600"); // set sim7100 to same serial speed
  delay(1000);
  simSerial.flush();   // Flush buffer

  SD.begin(SD_ChipSelectPin);
  if (!SD.begin(SD_ChipSelectPin)) {
    //Serial.println("Error opening SD-card");
    return;
  }
  delay(1000);
  if (SD.exists("1.TXT")) SD.remove("1.TXT");
  delay(1000);
}

void loop() {

  if (counter < 3) {
    File saveFile = SD.open("1.TXT", FILE_WRITE);
    if (saveFile) {
      // This has to be the Serial the SIM7100 is attached to
      simSerial.println("AT+CFTRANTX=\"c:/data.txt\"\r");
      while (!simSerial.available()) {} // wait for data to arrive

        readSerialPort(0);

      saveFile.close();

      // Serial.println("Success creating file");
    } else {
      // Serial.println("Error creating file");
    }
    counter++;
  }
}

/* For a first test we print everything to 1.txt -
  there will be "garbagge" as the AT response in it -
  we can "clean" in a later  by using the intermediate array or the counter */
void readSerialPort(uint8_t startIndex = 0) {
  uint16_t i = 0;   // counter and we want later to filter the first X chars
  while (simSerial.available() > 0) {
    char inChar = simSerial.read();
    if (i >= startIndex) { // if we want to filter the first 16 chars it would be i>=16 (as it starts with 0)
      if (inChar == '\n') {
        receiveArray[i] = '\0'; // terminate the array
        return;
      }
      if (inChar != '\r') {
        receiveArray[i] = inChar;
        i++;
      }
    }
  }
}

```

# Answer
> 0 votes
When having trouble in getting started with a modem, it's usually best to connect to the modem in "interactive mode", to verify that you're sending the right commands and getting the right responses.

Have you made sure that your modem/module's UART is at the right logic level to interface directly with your Pro Mini? How about the supply voltage? (Post a link to the product). If you're done with all that, then connect **only** the modem to the Pro Mini:

```
5V/3.3V -> Vcc (depending on the module's supply voltage)
D6 -> Modem TX
D7 -> Modem RX
Gnd -> Gnd

```

Then, upload the following to your Pro Mini:

```
#include <SoftwareSerial.h>

SoftwareSerial fserial(6, 7);

void setup(void)
{
    Serial.begin(57600);
    // I assume this is the default for your modem
    fserial.begin(115200);
    Serial.println("Starting.");
}

void loop(void)
{
    while (fserial.available())
        Serial.write(fserial.read());
    while (Serial.available())
        fserial.write(Serial.read());
}

```

This should basically transfer everything you send from your Serial Monitor to the modem, and in the reverse, transfer everything the modem sends to your Serial Monitor.

After uploading the sketch, in the Serial Monitor, set the `Line Ending` at the bottom to `Carriage Return`. Then you can first send the simple `AT` and should receive `OK` from the modem, to confirm that your setup works. Then to test your file reading code, send your command `AT+CFTRANTX="c:/data.txt"` and see what you get.

If you can confirm this works, writing code to do this automatically should then be much clearer. Or at the very least, you'll have ruled out a whole bunch of possible problems.

(**Note**: the Arduino may not work reliably with 115200 baud on Software Serial. So you may want to change the modem's baud rate quickly with `AT+IPREX=9600`. And then modify your sketch accordingly and re-upload.)

---
Tags: gsm, arduino-pro-mini
---


# Question
Title: How long does my digital pulse need to be for it to be read?
I have the following really simple code. On every iteration it'll read the first pin, and if it's high - do some serial IO. Then do the same with the second pin. Nice and simple, works during my tests.

My concern is that (in production), the digital pulse I'm receiving (and trying to mimic during testing) would be too quick for the arduino to read. So, for example, the race condition could be:

1. *First pin is low* Read first pin - result is low.
2. *First pin is now high* Read second pin - result is low.
3. *Fist pin now low again* Read first pin - result is low again (missed the 'high')

How much of an 'edge case' is this? Am I worrying about something that's likely to be a non-issue here? In production, each single pulse would represent a significant amount of product (I multiply it elsewhere) - so even skipping one could throw my data off.

```
boolean count1High = false;
boolean count2High = false;
int count1 = 7;
int count2 = 8;
int a = 1;
void setup() {
  pinMode(count1, INPUT);
  pinMode(count2, INPUT);
  Serial.begin(9600);
}

void loop()
{
  if (digitalRead(count1) == HIGH)
  {
    if (!count1High)
    {
      count1High = true;
      a++;
      Serial.println(a);
    }
  }
  else
  {
    count1High = false;
  }

  if (digitalRead(count2) == HIGH)
  {
    if (!count2High)
    {
      count2High = true;
      a++;
      Serial.println(a);
    }
  }
  else
  {
    count2High = false;
  }
}

```

## EDIT:

I know best approach here might be to attach an interrupt but I've been advised to avoid serial IO from within interrupts, I don't see an alternative here.

# Answer
> 1 votes
This is exactly the reason interrupts were invented. They can respond a lot faster than a simple digital read. By "a lot" I mean orders of magnitude.

When an interrupt is triggered your interrupt handler for that interrupt executes. If another interrupt occurs whilst your interrupt handler is running the interrupt controller remembers it and the interrupt handler for that interrupt will execute as soon as the previous one is finished.

So you won't miss that pulse while the other pulse is processing.

However note that you shouldn't use Serial in interrupts, since Serial itself uses an interrupt internally to control the transmission, so transmission can't happen properly if your interrupt is already running. So instead your interrupt routine should just set a flag which you then check for in your main loop. You then benefit from the ability to notice a pulse while processing another pulse and still be able to use Serial. In fact, if you arrange it right, you can recognise and remember a pulse on the *same* input as the one you're currently processing.

# Answer
> 1 votes
As explained by Majenko's answer, you should detect the pulses from an interrupt and print the result from the regular code. However, instead of just setting a flag in the interrupt handler, I suggest you instead *count* the pulses within the handler. This will make the handler a tiny bit slower, which is often something you want to avoid. However, the extra overhead is really tiny, and you gain the ability to count not only pulses that are short but also pulses that are closely spaced.

There is, however, something to be aware of when sharing a variable between interrupt code and regular code. If the variable cannot be read in a single CPU instruction (which is the case of an `int` on an AVR-based board), there is some risk that the value gets changed in the middle of you reading it. To void this problem, you have to disable interrupts when reading the variable from regular code.

Here is an implementation of this strategy highlighting this point:

```
const uint8_t intPin1 = 2;
const uint8_t intPin2 = 3;

// This is volatile because it is shared between interrupt context
// and regular code.
volatile unsigned int sharedCount = 0;

// Interrupt handler.
void countPulse() { sharedCount++; }

// A variable shared with interrupt context should be accessed from
// regular code with interrupts disabled, in order to avoid race
// conditions.
unsigned int getCount() {
    noInterrupts();
    unsigned int countCopy = sharedCount;
    interrupts();
    return countCopy;
}

void setup() {
    pinMode(intPin1, INPUT);
    pinMode(intPin2, INPUT);
    attachInterrupt(digitalPinToInterrupt(intPin1), countPulse, RISING);
    attachInterrupt(digitalPinToInterrupt(intPin2), countPulse, RISING);
    Serial.begin(9600);
}

void loop() {
    static unsigned int previousCount = 0;
    unsigned int count = getCount();
    if (count != previousCount) {
        Serial.println(count);
        previousCount = count;
    }
}

```

Note that if the pulses come very fast, you may miss *printing* the value, but you will not miss *counting* it (up to some limit, of course). Thus you may see non-consecutive numbers being printed.

# Answer
> 0 votes
**It depends** where the signal comes from and on other code in your sketch.

Typically, a sketch is rather way too fast for a mechanical switch, and you have to debounce it.

If your fear to lose events is *realistic*, interrupts are the way to go. But an ISR is some very special code: You won't do more than collect the information that there was an event. And you have to assert your main sketch won't interfere with the ISR.

---
Tags: serial, loop, digital-in
---


title: Using RST pin as external power switch

text:
# Question
Title: Using RST pin as external power switch
I have Arduino Nano with powered over USB. I have the request for external (physical) slide switch acting as power on/off for Arduino even if USB is always connected.

Looking at documentation and various posts, it seems the RST button could do just that. So when the "power" switch is on, RST is disconnected (= pulled high) and everything runs like normal. When the "power" switch is switched, it will pull RST low. As long as RST is pulled low, the board is stopped (the PWR led is lit, which is true and okay). Once released, the board will boot again.

Even though I agree this is not terribly elegant, is it going to work? I tried manually with the reset switch. Any side-effects I am overlooking?

# Answer
> 2 votes
That is a perfectly legitimate use of the RESET pin. Holding the chip in reset perfectly valid. Everything in the chip will be stopped.

Releasing it will start your sketch from the start again perfectly fine.

The only negative point is that your switch will be pulling power through the reset pin's pullup resistor, so will waste a little power.

---
Tags: arduino-nano, power, reset
---


title: NodeMCU V3 and MPU6050 strange values

text:
# Question
Title: NodeMCU V3 and MPU6050 strange values
I am new to this platform, so please if I do something against the regular rules please let me know so I can learn. Now my problem: I have a nodeMCU V3 connected to a MPU6050. Using my Arduino Uno I do get sensible values in the order of 0 degrees when the device is flat. Using the same code and the same setup I get very strange values in the order of 45 degrees when the device is flat. I have tried the following:

1. Using the I2C scanner I do get a valid address.
2. Testing with the Arduino Uno the values are correct.
3. The GY 521 breakout uses 3V3 datalines with 2k2 pull ups. Datalines are short. Eg on the same breadboard.
4. The GY 521 has a voltage regulator on board for 5V, so I feed the device with 5V in order to overcome a voltage drop problem.
5. I have tried to stretch the stretchClock function but no luck.

I have read about people with a similar kind of issue, but I could not find a solution. Anyone that can help me? Apoligies. It would be more handy to attach my code: '' /\* * I2C example sketch for ESP8266 \*/

```
#include <Wire.h>

const int DevID = 0x68;
const int PWR_MGT1_REG = 0x6B;

const int DataReg_AX = 0x3B;
const int DataReg_AY = 0x3D;
const int DataReg_AZ = 0x3F;
const int AccConfigReg = 0x1C;
const int GyrConfigReg = 0x1B;
const int SelfTestReg = 0x0D;

const int TempReg = 0x41;

const int DataReg_GX = 0x43;
const int DataReg_GY = 0x45;
const int DataReg_GZ = 0x47;

const int CalibrationConfigAcc = 0xF0;//set this value for calibration
const int CalibrationConfigGyr = 0xE0;//set this value for calibration
const int NormalConfigAcc = 0x00;//set this value for calibration 2G
const int NormalConfigGyr = 0x00;//set this value for calibration 250dps

/*
  int16_t Acc_X;
  int16_t Acc_Y;
  int16_t Acc_Z;
*/
float Acc_X, accAngleX, accAngleY, Yaw_Angle;
float Acc_Y;
float Acc_Z;

//double Acc_X, accAngleX, accAngleY, Yaw_Angle;
//double Acc_Y;
//double Acc_Z;

int8_t X_selfTest;
int8_t Y_selfTest;
int8_t Z_selfTest;
int8_t Acc_X_Y_Z_selfTest;

int16_t Temp;
/*
  int16_t Gyro_X;
  int16_t Gyro_Y;
  int16_t Gyro_Z;
*/
float Gyro_X;
float Gyro_Y;
float Gyro_Z;

int16_t Gyro_X_selfTest;
int16_t Gyro_Y_selfTest;
int16_t Gyro_Z_selfTest;

//int SDApin = 3;//create I2C pinouts for ESP8266;
//int SCLpin = 4;

unsigned long elapsedTime, previousTime, currentTime;

void setup() {// put your setup code here, to run once:
  Serial.begin(115200);
  Wire.begin ();
 // Wire.setClock(400000);
//  Wire.setClockStretchLimit(40000);
  Wire.beginTransmission(DevID);
  Wire.write(PWR_MGT1_REG);
  Wire.write(0x0);// wake up the sensor
  Wire.endTransmission();
  CalibrationProcedure();// enter calibration procedure
}

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

previousTime = currentTime;
currentTime = millis();
 elapsedTime = (currentTime - previousTime) / 1000;

  Wire.beginTransmission(DevID);
  Wire.write(DataReg_AX);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 14);
  if (Wire.available() == 14) {
    Acc_X = ((Wire.read() << 8) | (Wire.read())) / 16384.0;// divide by 16384 for 2G setting according to datasheet
    Acc_Y = ((Wire.read() << 8) | (Wire.read())) / 16384.0;
    Acc_Z = ((Wire.read() << 8) | (Wire.read())) / 16384.0;
    Temp = (Wire.read() << 8) | (Wire.read());
    Gyro_X = ((Wire.read() << 8) | (Wire.read()))  / 131.0; // divide by 131.0 according to datasheet for setting 250 dps
    Gyro_Y = ((Wire.read() << 8) | (Wire.read())) / 131.0;
    Gyro_Z = ((Wire.read() << 8) | (Wire.read())) / 131.0;
    delay(500);
  }

  //The formulas below have been extracted from another program and uses mathematical
  //values for calulation of pitch roll and yaw. For the moment only pitch is calibrated
  //The next purpose of this program is follow a calibration procedure to take approx 200 samples
  //and average the total value to correct the pitch roll and yaw value
  accAngleX = (atan(Acc_Y / sqrt(pow(Acc_X, 2) + pow(Acc_Z, 2))) * 180 / PI);
  accAngleY = (atan(-1 * Acc_X / sqrt(pow(Acc_Y, 2) + pow(Acc_Z, 2))) * 180 / PI);
  Yaw_Angle = Yaw_Angle + Gyro_Z * elapsedTime;

  float Gyro_X_axis = (float)Gyro_X / 131.0;
  float Gyro_Y_axis = (float)Gyro_Y / 131.0;
  float Gyro_Z_axis = (float)Gyro_Z / 131.0;
  float Temperature = (Temp / (340.0)) + 36.53;
  //Serial.print(" Accelero X \t" );
  //Serial.print(Acc_X);
  //Serial.print(" Accelero Y \t" );
  //Serial.print(Acc_Y);
  //Serial.print(" Accelero Z \t");
  //Serial.print(Acc_Z);
  //Serial.println("");
  //Serial.print(" Gyro X \t" );
  //Serial.print(Gyro_X);
  //Serial.print(" Gyro Y \t" );
  //Serial.print(Gyro_Y);
  //Serial.print(" Gyro Z \t");
  //Serial.print(Gyro_Z);
  //Serial.print(" Temperature \t");
  //Serial.println(Temperature);
  //Serial.println(Temp);
  Serial.println ("Angle X");
  Serial.println(accAngleX);
  Serial.println ("Angle Y");
  Serial.println (accAngleY);
  Serial.println("Yaw Angle");
  Serial.println(Yaw_Angle);
  delay(500);
}

void CalibrationProcedure() {
  Serial.println("Keep sensor steady until calibration process is complete!");
  Wire.beginTransmission(DevID);
  Wire.write(AccConfigReg);//8 g
  Wire.write(CalibrationConfigAcc);
  Wire.endTransmission();
  delay(250);
  Wire.beginTransmission(DevID);
  Wire.write(GyrConfigReg);
  Wire.write(CalibrationConfigGyr);//250 deg/s
  Wire.endTransmission();
  delay(500);
  Serial.println("Selftest enabled, reading data...");

  Wire.beginTransmission(DevID);
  Wire.write(SelfTestReg);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 4);
  if (Wire.available() <= 4) {
    X_selfTest = Wire.read();
    Y_selfTest = Wire.read();
    Z_selfTest =  Wire.read();
    Acc_X_Y_Z_selfTest = Wire.read();
    delay(500);
  }

  //extracting factory trim values after self test
  //unsigned integers for accelero variables
  uint8_t XA_selfTest;
  uint8_t YA_selfTest;
  uint8_t ZA_selfTest;
  //unsigned integers for gyro variables
  uint8_t GX_selfTest;
  uint8_t GY_selfTest;
  uint8_t GZ_selfTest;
  //Factory Trim variables
  float FTGX;
  float FTGY;
  float FTGZ;
  float FTAX;
  float FTAY;
  float FTAZ;

  float SelfTestPercentage_GX;
  float SelfTestPercentage_GY;
  float SelfTestPercentage_GZ;
  float SelfTestPercentage_AX;
  float SelfTestPercentage_AY;
  float SelfTestPercentage_AZ;

  GX_selfTest = X_selfTest & 0x1F; // 0x1F is a bit mask to extract the first 5 bits. unsigned format
  GY_selfTest = Y_selfTest & 0x1F;
  GZ_selfTest = Z_selfTest & 0x1F;
  XA_selfTest = (X_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x30) >> 4; //shift the first 3 bits and extract bits with a mask depending on the LSB postion in the last received mixed byte
  YA_selfTest = (Y_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x0C) >> 2;
  ZA_selfTest = (Z_selfTest >> 3) | (Acc_X_Y_Z_selfTest & 0x03);

  Serial.println ("XA_selfTest");
  Serial.println (X_selfTest, HEX);
  Serial.println("YA_selfTest");
  Serial.println(Y_selfTest, HEX);
  Serial.println("ZA_selfTest");
  Serial.println(Z_selfTest, HEX);
  Serial.println("Acc_X_Y_Z_selfTest");
  Serial.println(Acc_X_Y_Z_selfTest, HEX);

  //calculate the factory trim settings
  FTGX = (25.0 * 131.0) * (pow(1.046, ((float)GX_selfTest - 1.0)));// Factortrim Gyro X
  FTGY = (-25.0 * 131.0) * (pow(1.046, ((float)GY_selfTest - 1.0)));// Factortrim Gyro Y
  FTGZ = (25.0 * 131.0) * (pow(1.046, ((float)GZ_selfTest - 1.0)));// Factortrim Gyro Z
  FTAX = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)XA_selfTest - 1.0) / 30.0)));
  FTAY = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)YA_selfTest - 1.0) / 30.0)));
  FTAZ = (4096.0 * 0.34) * (pow((0.92 / 0.34), (((float)ZA_selfTest - 1.0) / 30.0)));
  Serial.println("Selftest ended...please copy data");
  Serial.println(" GX trim value\t" );
  Serial.println(FTGX);
  Serial.println(" GY trim value\t" );
  Serial.println(FTGY);
  Serial.println(" GZ trim value\t");
  Serial.println(FTGZ);
  Serial.println(" AX trim value\t" );
  Serial.println(FTAX);
  Serial.println(" AY trim value\t" );
  Serial.println(FTAY);
  Serial.println(" AZ trim value\t");
  Serial.println(FTAZ);
  SelfTestPercentage_GX = 100.0 + 100.0 * ((float)GX_selfTest - FTGX) / FTGX;
  Serial.println("SelfTestPercentage");
  Serial.println(SelfTestPercentage_GX);
  SelfTestPercentage_GY = 100.0 + 100.0 * ((float)GY_selfTest - FTGY) / FTGY;
  Serial.println("SelfTestPercentage");
  Serial.println(SelfTestPercentage_GY);
  SelfTestPercentage_GZ = 100.0 + 100.0 * ((float)GZ_selfTest - FTGZ) / FTGZ;
  Serial.println("SelfTestPercentage");
  Serial.println(SelfTestPercentage_GZ);
  SelfTestPercentage_AX = 100.0 + 100.0 * ((float)XA_selfTest - FTAX) / FTAX;
  Serial.println("SelfTestPercentage Acclero x, y, z");
  Serial.println(SelfTestPercentage_AX);
  SelfTestPercentage_AY = 100.0 + 100.0 * ((float)YA_selfTest - FTAY) / FTAY;
  Serial.println("SelfTestPercentage Acclero x, y, z");
  Serial.println(SelfTestPercentage_AY);
  SelfTestPercentage_AZ = 100.0 + 100.0 * ((float)ZA_selfTest - FTAZ) / FTAZ;
  Serial.println("SelfTestPercentage Acclero x, y, z");
  Serial.println(SelfTestPercentage_AZ);

  // get data outputs with self test enabled
  Wire.beginTransmission(DevID);
  Wire.write(DataReg_AX);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 14);
  if (Wire.available() <= 14) {
    Acc_X = (Wire.read() << 8) | (Wire.read());
    Acc_Y = (Wire.read() << 8) | (Wire.read());
    Acc_Z = (Wire.read() << 8) | (Wire.read());
    Temp = (Wire.read() << 8) | (Wire.read());
    Gyro_X = (Wire.read() << 8) | (Wire.read());
    Gyro_Y = (Wire.read() << 8) | (Wire.read());
    Gyro_Z = (Wire.read() << 8) | (Wire.read());
    delay(500);
  }
  //print values with self test enabled
  Serial.println("Self test enabled values");
  Serial.println(" Accelero X " );
  Serial.println(Acc_X);
  Serial.println(" Accelero Y " );
  Serial.println(Acc_Y);
  Serial.println(" Accelero Z ");
  Serial.println(Acc_Z);
  Serial.println(" Gyro X " );
  Serial.println(Gyro_X);
  Serial.println(" Gyro Y " );
  Serial.println(Gyro_Y);
  Serial.println(" Gyro Z ");
  Serial.println(Gyro_Z);
  delay(500);

  //setup the device for normal OPS
  Wire.beginTransmission(DevID);
  Wire.write(AccConfigReg);
  Wire.write(NormalConfigAcc);
  Wire.endTransmission();
  delay(50);
  Wire.beginTransmission(DevID);
  Wire.write(GyrConfigReg);
  Wire.write(NormalConfigGyr);
  Wire.endTransmission();
  delay(50);

  //request data with self test not enabled
  Wire.beginTransmission(DevID);
  Wire.write(DataReg_AX);
  Wire.endTransmission();

  Wire.requestFrom(DevID, 14);
  if (Wire.available() <= 14) {
    Acc_X = (Wire.read() << 8) | (Wire.read());
    Acc_Y = (Wire.read() << 8) | (Wire.read());
    Acc_Z = (Wire.read() << 8) | (Wire.read());
    Temp = (Wire.read() << 8) | (Wire.read());
    Gyro_X = (Wire.read() << 8) | (Wire.read());
    Gyro_Y = (Wire.read() << 8) | (Wire.read());
    Gyro_Z = (Wire.read() << 8) | (Wire.read());
    delay(500);
    //print values with self test not enabled
    Serial.println("Self test not enabled values");
    Serial.println(" Accelero X " );
    Serial.println(Acc_X);
    Serial.println(" Accelero Y " );
    Serial.println(Acc_Y);
    Serial.println(" Accelero Z ");
    Serial.println(Acc_Z);
    Serial.println(" Gyro X " );
    Serial.println(Gyro_X);
    Serial.println(" Gyro Y " );
    Serial.println(Gyro_Y);
    Serial.println(" Gyro Z ");
    Serial.println(Gyro_Z);
    delay(5000);
  }
}
'''

```

# Answer
I had the same issue sometime back.I was able to get good results using the example given for the ESP8266 in the MPU6050 library itself.You can make the necessary changes starting from that sketch.Hope this helps.

Heres the github link to the library https://github.com/ElectronicCats/mpu6050
> 1 votes

---
Tags: i2c, nodemcu, mpu6050, wire-library
---


title: How to generate 3 PWM signals

text:
# Question
Title: How to generate 3 PWM signals
I have 2560 mega, and I Want to generate 3-phase PWM signal at 62.5khz, synced and shifted 120 degrees apart.

I need that for 3-phase split-coil boost converter (or even isolated flyback converter), with ~~3 phase transformer~~ coupled inductor. So I dont need sine wave table like here, but actually, a direct square wave PWM output, from 3 synced digital pins, with chosen duty cycle. How can I do that?

# Answer
If you have any timers left, I would (regardless of the number of PWM signals and if you need different PWM frequencies) just dedicate a timer to do IRQs to manage them.

The frequency of the IRQs would then depend on how accurately you want to control the duty cycle, ref. also to the comment from Edgar Bonet .
> 1 votes

---
Tags: arduino-mega, pwm
---


# Question
Title: how do i connect my Arduino Nano to my Linux Laptop
**update:** I uninstalled the portable package of Arduino IDE, completely, and installed the IDE using `sudo apt install arduino`. yes, I verified that my Nano was plugged in, the status on the bottom right says `Arduino Nano w/ ATmega328 on COM1`, but sadly the IDE won't explain to me *why* the `Tools > Serial Port` section is still unavailable.

Also, the online version doesn't recognize the board even though it's plugged in and configured in the settings to look for a "Nano". I also used a reliable USB Hub I use for my drawing tablet, because that was one of the remedies to troubleshoot the lack of connection, and because the Hub seems to do a lot of good things around here.

**end of update**

I received an Arduino Nano as a gift a couple months ago and had to place it on a shelf as a mere dust collector, because it was not as easy as I thought it would be to get it working. I plugged the Nano into my computer with a cable, and attempted to load an example "blink" program and it gives errors saying "no device connected" in the errors.

It does light up and flash, so I know it is receiving power, so how do I specify where the Nano is? I am familiar with the /dev category and how to use code in Linux, but I don't know how to communicate with the Arduino, as in, know which block device the Nano is in /dev

now that Thomas has brought to my attention the "port" setting in the drop down menus, I just realized that the port is greyed out. that could be a good detail in troubleshooting this issue.

# Answer
> 1 votes
I have to sadly conclude that this issue posted was for nothing. the board I was using most likely has an underlying defect (of all odds, the 45 boards my teacher was using, he gives me 1 defect board? believable.) rendering the board inoperable. I plugged the board into an entirely different laptop, downloaded and installed a full IDE for it, ran it normally, ran it in Administrator, downloaded and installed the plugin, ran the Online IDE to test that... same **exact** issues: greyed out serial port settings, and no device detected upon plugging in.

again, I apologize for this being a waste of time. I wished this was not the case and that I could make some pretty cool stuff during this quarantine mess.

I salute to all you programmers out there.... and wish you all good luck in your own endeavors in Arduino.

# Answer
> 1 votes
In the Arduino IDE, the mcu will show up in `Tools > Port`. Your Arduino Nano will probably be visible at `/dev/ttyUSB0` or `/dev/ttyUSB1` following whatever is already plugged on USB. Make sure to select it.

Select `Nano` in `Tools > Board`.

Last step is `Verify/Compile` your code (^R), then `Upload` (^U).

This link sounds to be a good read to start.

# Answer
> 0 votes
If you have managed your Linux security well, a normal user may not have access to the port where Arduino is plugged into. If so, try from terminal with "sudo arduino". (At least works for me)

---
Tags: arduino-nano, usb, linux
---


title: Scrolling an I2C text

text:
# Question
Title: Scrolling an I2C text
I want tried to make a programm to display a text on an I2C LCD-Display. The text should be scrolled for one position every time the function is called.

On the internet I saw a lot of solutions but there were all diffrent from what I need.

So I tried to make my own code. The code works well except of the part where I try to scroll in the Text from the left.

```
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 16, 2);

char Str[12] = {'T', 'r', 'u', 'e', 't', 'z', 's', 'c', 'h', 'l', 'e', 'r'};
int pos = 0;
int posretry = 0;
bool ledon = false;

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

  lcd.init();
  lcd.backlight(); //lcd.noBacklight();
}

void scroll()
{
  for (int i = 0; i < 12; i++)
  {
    //Print text
    lcd.setCursor(i + pos, 0);
    lcd.print(Str[i]);

    //Move in text from the left

    if (pos >= 6)
    {
      lcd.setCursor(i + pos, 0);
      lcd.print(Str[i]);

      lcd.setCursor(posretry, 0);
      lcd.print(Str[11 - posretry]);

      posretry++;
    }
  }
  delay(500);
  lcd.clear();

  pos++;
}

void changeled()
{
  if (ledon == false)
  {
    digitalWrite(13, LOW);
  }
  else
  {
    digitalWrite(13, HIGH);
  }

  ledon = !ledon;
}

void loop()
{
  scroll();
  changeled();  //Example Event
}

```

The goal is to move the text to the right and show the not displayed letters on the left.

Example:

```
|er    Truetzschl|  -->
|                |

```

A Video about the error can be found here: https://data.jonas-heinze.de/shares/stackexchange/lcd/

Thanks for your help.

# Answer
You do some strange things that I, at least, don't understand (e.g. I don't see what you need `posretry` for), but you might have a reason for doing so. But you don't reset `posretry` and `pos`, which means they will very soon be out of a reasonable range. At some point the `int` will actually overflow to negative values, which is definitely not going to work!

To make it less complicate, you should write a function that prints the char array shifted by a desired value as a beginning.

The below code is completely untested as I don't have your hardware and I'm aware that it does not include all your desired features. But it should give you an idea of how scrolling can be implemented **in principle** and it's up to you to improve/fix it.

```
#define LCD_SIZE 16
#define STR_LEN 12
char str_to_print[STR_LEN]={'T', 'r', 'u', 'e', 't', 'z', 's', 'c', 'h', 'l', 'e', 'r'};

void print_scrolled (uint8_t scrolled_by) {
  for (uint8_t i=0;i<LCD_SIZE;i++) {
    lcd.set_cursor(i,0);
    if (scrolled_by>=LCD_SIZE) scrolled_by=0;

    if (scrolled_by<STR_SIZE) lcd.print(str_to_print[scrolled_by]);
    else lcd.print(' ');
    scrolled_by++;
  }
}

```

You could call it like this:

```
for (uint8_t i=0;i<STR_LEN;i++) {
  print_scrolled(i);
  delay(500);
}

```

Once you are familiar with my approach you should be able to enhance it with additional features (end of text coming in from the other side, spaces between end and beginning, etc).
> 1 votes

---
Tags: i2c, lcd, string, array
---


# Question
Title: Confused as to how 2 of my interrupts are firing from just 1 pin input?
I have the following code which uses interrupts to set a flag for whether serial IO should happen to update my PC about a particular pin input. So I have interrupts on pins 2 and 3.

I am using the arduino's pin 13 as an output, and every 2 seconds send a pulse. On my arduino, I have 1 wire running from 13 to pin 3. **Note: I have nothing at all inserted into pin 2.**

Somehow, I get the following input every 2 seconds:

`Pin 2` `Pin 3`

How is my interrupt for pin 2 firing??

```
boolean serialCommsQueue1 = false;
boolean serialCommsQueue2 = false;

void setup()
{
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), pin2Fired, RISING);
  attachInterrupt(digitalPinToInterrupt(3), pin3Fired, RISING);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop()
{
  digitalWrite(13, HIGH); // sets the digital pin 13 on
  delay(1000);            // waits for a second
  digitalWrite(13, LOW);  // sets the digital pin 13 off
  delay(1000);            // waits for a second

  if (serialCommsQueue1)
  {
    serialCommsQueue1 = false;
    Serial.println("Pin 2");
  }

  if (serialCommsQueue2)
  {
    serialCommsQueue2 = false;
    Serial.println("Pin 3");
  }
}

void pin2Fired()
{
  serialCommsQueue1 = true;
}

void pin3Fired()
{
  serialCommsQueue2 = true;
}

```

## EDIT:

If I take the wire out of 3, pin 2 constantly (every 2 seconds) writes to serial. If I put the wire back in pin 3 regularly writes every 2 seconds - which itself is a problem too, since it should only be detecting a 'change'?

# Answer
> 2 votes
The interrupt on pin 2 triggers, because the pin is floating. Since nothing is connected to the pin, it reacts to whatever noise is flying by (for example from pin 3). That can lead to the pin changing its state together with pin 3, or to just erratically randomly changing state.

You need to connect a pullup or pulldown resistor (one rather big resistor going from the pin to either Vcc or ground), which sets the pins state, when it is not actively driven otherwise. If you need a pullup or pulldown depends on your wanted behavior.

If a pullup is ok for you, you can activate the Arduinos internal pullup resistor by using

```
pinMode(2, INPUT_PULLUP);

```

---
Tags: serial, interrupt, digital
---


title: HID with bidirectional communication

text:
# Question
Title: HID with bidirectional communication
I want to build a gamepad HID using the Arduino Micro, and intend to use Nico’s HID library for that.

But I would like to send some config info from the PC to the Arduino HID as well.

Can you have a gamepad that not only sends state to the PC, but also receives a configuration from the PC?

I intend to use this with a Linux PC as host.

# Answer
Yes, but the configuration side of things will not be part of the gamepad HID. You will need to set up a second communication channel - be that serial or raw HID - to do the configuration.
> 1 votes

---
Tags: usb, arduino-micro, hid
---


# Question
Title: Can i exchange my arduino nano for an atmega328p-pu in my project?
Im currently trying to make a smart light switcher that is attached in front of my rooms light switches. It basically mostly consists of two servos (to turn on or off either switch), two button (to turn the servo manually), an esp8266 esp-01 module (to be able to use with a google home) and my arduino nano. I really need to make it as small as posible and i also want to keep my only arduino not attached to the wall. Would it work if i use an atmega328p or like an attiny84a to replace the arduino?

Im not finished with connecting the esp-01 to the arduino but i was thinking of using the arduino's 3.3v output pin. Would i need extra components to run the microcontroller on its own?

Im really new to arduino and im trying to learn the most I can and to try to make my little project as good as i can.

Would really appreciate some help please, thank you!

# Answer
Sure you can - as long as you include the rest of the support circuitry.

However the ESP-01 beats the Arduino hands-down and can do everything the Arduino does by itself - except it lacks IO so connecting to the servo and button could be tricky.

So using some kind of extra MCU as an IO expansion over serial would be a good idea, but a 328P is rather more than you need. Maybe you should look at something smaller, such as one of the ATTiny chips.
> 0 votes

---
Tags: esp8266, arduino-nano, atmega328
---


# Question
Title: MKR Zero not showing up in WIN10 device manager / Arduino IDE cannot detect port / COM
I'm new to Arduino and hope you guys can give some advise.

I bought MKR Zero a few days before and tried to connect to my Win10 laptop. I can see the LED on the board is on, but the Arduino IDE cannot detect it. the "Port" is grey out. I tried 2 laptops which also Win10 but same situation happen. I tried different USB cables I had.

I checked the device manager in the control panel, there is no "Unknown device" under the USB port but also no MKR showing up. I don't know what to do.

I'm not sure if it is Win10 problem...Please kindly advise, thank you very much!!

# Answer
Hardware itself problem. Went to the shop and changed the board to me and now works.
> 0 votes

---
Tags: arduino-ide, usb, windows, mkrzero
---


# Question
Title: Is it dangerous to connect two output pins together?
If I have two output pins, one set high and the other set low with digital or analog write like this

```
digitalWrite(PIN1, LOW);
digtialWrite(PIN2, HIGH);

```

and then I short them together using a wire, will current flow through the wire?

# Answer
Yes. It is dangerous. You can imagine what would happen when you understand how a GPIO pin works in output mode.

You are effectively connecting VCC to GND via two small and weak MOSFETs which will overheat and break down.
> 0 votes

# Answer
You can connect but requires resistor between two pins to limit the current.
> 0 votes

# Answer
That's out of spec for any arduino microcontroller.

The behavior of a broken Arduino is "undefined" :)

I guess there will not flow current (after an initial peak), but *at least* one of the two pins is not working properly any more. But, this is just a guess.

And it's probably not dangerous for you or the connecting wire (Other than @jsotola's comparison with a shorted battery in a comment to your question). I guess the arduino will die before it gets dangerously hot.
> 0 votes

# Answer
Shorting the output pins together is a bad idea that will likely result in damage to your Arduino. According to specifications, the I/O pins are able to source (provide current to a load) or sink (accept current from an external source) up to 40mA. In almost all cases, you will want to use a current-limiting resistor. In some cases, an external circuit that you connect your Arduino to may intrinsically limit the current.

In the case of lighting up an LED, you can do this in two ways:

* Set the I/O pin HIGH to source current to the LED through a current-limiting resistor to ground. The I/O pin provides the current to light up the LED. LOW turns it off.
* Set the I/O pin LOW to sink current from the LED and current-limiting resistor where the power to the LED is provided by the external source. In this case, the LED floats and the I/O pn serves as ground. HIGH turns it off.

The internal pullup resistor is useful if you want to be able to drive an external transistor or logic level device.

This Arduino tutorial goes into more detail about the specific modes of operation.
> 0 votes

---
Tags: pins, analogwrite, digitalwrite
---


# Question
Title: Can I Interrupt on any keypress on this keypad?
I'm learning how to write code interrupt code. I just experimented with my first toy example that I got from here:

```
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;

void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}

void loop() {
  digitalWrite(ledPin, state);
}

void blink() {
  state = !state;
}

```

Now I'm trying to incorporate interrupts into my own project. I have a circuit that looks like this using an Arduino Uno Wifi Rev2, Membrane 3x4 Matrix Keypad, a buzzer, some resistors and an RGB LED:

Can I write code such that it interrupts any time any of the keys is pressed (and I can still tell which key is pressed)? How would I do that?

# Answer
No, you can't. Owing to the fact that you have to manually cycle through each row (or column, depending on which way you are holding your head at the time) in order to read which keys are pressed there is no way to relate a button to an interrupt.

The only possible way would be to use an external keypad interface chip (you could roll your own with another Arduino) which has an interrupt signalling facility in it.
> 1 votes

---
Tags: interrupt
---


title: Getting external data to the Arduino

text:
# Question
Title: Getting external data to the Arduino
I have a new Uno R3, it's pretty cool and I've enjoyed playing with it.

Now I want to build a couple of things:

1) a market price LCD tracker.

2) a servo motor type thing to open my electric gate.

Both of these either require input from an external website or some kind of message to initiate the action on the Arduino.

How do people generally get data onto the Arduino, I found a lot of conflicting information online.

Does this thing have Wifi or Bluetooth??

I got this pack, it doesn't seem to have either Wifi or Bluetooth, if not how do ppl generally get data onto the Arduino?

I have a raspberry pi spare, can I just use that, sending data from pins?

# Answer
> 1 votes
> How do people generally get data onto the Arduino, I found a lot of conflicting information online.

There are various ways depending on what the data is and how you access it.

> Does this thing have Wifi or Bluetooth??

Not unless you add WiFi or Bluetooth to it, no.

> I have a raspberry pi spare, can I just use that, sending data from pins?

Yes, there are ways.

---

How you go about getting data on to an Arduino depends very much on how the data is accessed. It is possible to add a WiFi interface to an Arduino, either through an official WiFi shield or through adding something like an ESP8266 on a breakout board (ESP-01 is popular) although interacting with the ESP8266 can be tricky.

You can do the same with Bluetooth or any number of other wireless protocols.

The simplest method of getting data to the Arduino, though, is through the USB serial port. Since you have a Raspberry Pi available the most logical option would be to plug the Arduino directly into the Pi's USB port. The Pi can then communicate through `/dev/ttyACM0` (or `/dev/ttyUSB0` for some clones) and the Arduino receive the data through the `Serial` object. Exactly how you arrange all that is entirely up to you.

# Answer
> 1 votes
It depends on the kind of data and where it will be coming from. Trigging your gate really only needs a signal to start moving, though a directional signal would be better ("Open" or "Close"). What is the source of that signal and far from from the gate will it originate?

If you're willing to press a button on the gate, it's a simple matter of sensing the button with one of the Arduino's pins. If you want to operate it from your phone from right in front of the gate, a Bluetooth module on the Arduino could pick up the phone's signal. If you also need to operate it from further away - more than 5-10 meters, a pair of RF modules with stick-antennas like the ones on a WiFi router, might get you 100m.

For the market-price tracker, your data is probably coming from the internet, in which case you'd need either an ethernet module or a WiFi module that would link it to the internet through your local network. Or if this device has to be portable, you could use a cellular module to link it to the internet through the cellular network. This latter is usually expensive - the price of adding an additional line to your cellular plan, for instance.

---
Tags: wifi, bluetooth, networking, data
---


# Question
Title: Writing elegant applications for Arduino
Coming from a C background, I was taught that tight loops that just burn CPU aren't desirable.

Is there any programming style guides on Arduino? Is it common practice to just let loop iterate as a tight loop forever?

# Answer
A microcontroller's execution path is a tight loop whether you like it or not.

If you take a CPU and connect it to empty memory the CPU will execute each empty cell in turn and loop back to the beginning of memory when it reaches the end (assuming empty memory cells equate to NOP and covers the whole memory space).

With no operating system, no scheduler, nothing except your specific code running, the CPU is always executing something.

The only time the CPU stops executing is when you manually send it to sleep to be woken by some external source (such as a timer, or a sensor sending an interrupt signal). You'd only do that, normally, to reduce power consumption.

On Arduino the `loop()` function is in fact executed from within a `while(1)` loop.

On microcontrollers when `main()` exits, or you call `exit()` it just disables interrupts and drops out to a `while(1)` loop.
> 3 votes

# Answer
On a multiprocess system, like your typical desktop, you usually have way more processes than logical CPUs. When programming such systems you therefore have to avoid burning more CPU cycles than needed. Instead, when your program has nothing to do, it should just *sleep*, and leave the CPU available for other processes.

On an Arduino, you only have one single program running at a time. It is then not that useful to keep the CPU idle. Also, the power dissipation is so low that you will not notice the microcontroller getting even slightly warm. The extra complexity of getting into and out of sleep mode is therefore not that useful. Only when running on batteries do you care about saving every possible milliamp: then learning about sleep modes starts getting useful.
> 3 votes

# Answer
That is a difference between embedded systems programming and (many but not all) other types of programming. An embedded system is usually a controller of some kind and needs to be responsive to one or more kinds of events. Three typical ways of accomplishing this are

* to use some kind of operating system to coordinate events and the code that manages each of them;
* to write interrupt service routines (ISRs) to manage events and dispatch to code that manages them;
* to poll for events frequently and dispatch to the code to manage them.

On processors as small as the AVRs, data memory and sometimes instruction memory, are scarce resources and an operating system is usually too expensive (in terms of memory needs) for most of them. On the ATtinys, forget it. On Uno, maybe kinda sorta, but memory will be a pretty severe limitation. On Megas, you might manage it.

ISR programming can be complex to write and is definitely more complex to debug(!). It's not out of the question, and it may be justified in a system that must be highly responsive - think automotive ABS braking, traction control, and fly-by-wire systems. On the other hand, systems like these *have to be right*.

Polling is the easiest to write and debug. You call each subsystem (code) in a tight loop (and there's your answer: "yes, let it iterate") that gives each one an opportunity to assess whether or not it needs to act and to do so. This is a case where burning cycles is inconsequential, while making a more responsive system.

In my hobbyists' classes, this is what I teach; it's also what use most. I call it "maybe-do" (and wrote about it here in answer to another question). In `loop()` I do nothing but call a number of functions in turn, each of which does:

```
   {
      if I dont need to act now,
         return;
      else {
         do what needs to be done -- quickly!;
         return;
      }
   }

```
> 1 votes

---
Tags: programming, loop
---


title: TLE9879 BLDC shield won't communicate

text:
# Question
Title: TLE9879 BLDC shield won't communicate
I just got the TLE9879 BLDC shield, which I connected to an Arduino Leonardo. Compiling the example sketch (bldc\_shield\_blinky\_test) went fine, however, upon flashing it to the board the LED on the shield doesn't change the color (it stays white) and the following line is repeatedly printed to the Serial console:

> WARNING: Board\[1\]; Command\[901\]; Answer\[0\]

I have initially tried the shield in its out of the box state. I have since then flashed it with the HALL version of the shield software, using the project included in the SW distribution that comes with the shield. In both cases, the shield behaved as described above when connected to the Arduino.

Does anybody know what this warning message is about?

# Answer
> 1 votes
I never use TLE9879, but I could guess of why it doesn't work as expected.

For ATMega328p-based Arduino boards (i.e. Uno, Nano and Pro Mini), it has pin 11, 12 and 13 as SPI’s MOSI, MISO and SCLK signals, but at the same time these signals are also available on those board’s In-Circuit Serial Programming (ICSP) header pin 4, 1 and 3, except for Pro Mini which does not have a dedicated ICSP header.

This however is not the case for Arduino Leonardo and Arduino Micro which are based on ATMega32U4, for those boards, the SPI is only available on ICSP header. This is one of the reasons that some of the Arduino shields designed for Arduino Uno does not work with Arduino Leonardo when SPI communication is involved.

Based on the information of TLE9879, the SPI port is connected to pin 11-13 so it is designed to work with Arduino Uno but will not work for Arduino Leonardo.

---
Tags: motor, shields, arduino-leonardo
---


# Question
Title: Does the MKR WIFI 1010 support the arduino mouse and keyboard controller?
I am working on a project right now that needs to connect to my computer via bluetooth and access the arduino mouse and keyboard library. In my research, I've found that only the Leonardo, Due, and Micro can emulate cursor movements, but they need to have additional hardware like the HC05. I would like to keep the amount of hardware I use to a minimum, but I understand if there is no way around it. Is there any way to use the MKR WIFI 1010 like a Leonardo, or would I need to get one of the aforementioned boards and then get a bluetooth module hooked up?

PS this is my first dive into bluetooth, so any additional resources to aid me in my journey would be much appreciated.

# Answer
Yes, the Arduino SAMD boards are supported by the Arduino Keyboard and Mouse library.

Nano 33 IoT is a smaler alternative to MKR 1010.

But the MKR1010 or the Nano33 IoT with original NINA firmware doesn't yet support classic Bluetooth like the HC-05 module. The ArduinoBLE library and the NINA firmware support only BLE which is different.

But there is a simple way to replace the NINA firmware with the ESP32 Arduino basic Bluetooth sketch SerialToSerialBT and then use it from the SAMD. This way the NINA module will be degraded to something like a HC-05.
> 1 votes

---
Tags: bluetooth, arduino-due, arduino-leonardo, arduino-micro, mkr1010
---


# Question
Title: turning positional servo motor more then 180 degrees
My RC servo motor is capable of turning more then 180 degrees(around 200 degrees) when I physically turn it, but when I use my code it only turns 180.

Is there a way to code it so that it turns to 200 instead of 180?

# Answer
First some basics to clear definitions:
A Servo Motor does not normally spin a full 360 degree rotation. Instead it is limited to a range of 180, 270 or 90 degrees depending on the make or type. A control signal is sent to the servo to position the shaft at the desired angle.
**Conventional Servo Motor Timing**
In a conventional analog servo motor a PWM signal with a period of 20 ms is used to control the motors. A signal of 20 ms has a frequency of 50 Hz.

The width of the pulse is varied between 1 and 2 ms to control the motor shaft position.

* A pulse width of 1.5ms will cause the servo shaft to rest in the 90 degree position, the center of its travel.
* A pulse width of 1ms will cause the servo shaft to rest at the 0 degree position.
* A pulse width of 2ms will cause the servo shaft to rest in the 180 degree position.

Varying the pulse width between 1ms and 2ms will move the servo shaft through the full 180 degrees of its travel. You can bring it to rest at any angle you desire by adjusting the pulse width accordingly.

So if your servo is a 270 degree servo (like the domanrc DM-S0903MD or DS3218 270 Degree Digital RC Servo) the standard sweep sketch (Arduino Servo library) will let your servo sweep from 0-270 even if in the \*.ino its `myservo.write(180);` So to simply test you could use `write(map(desired_angle, 0, 270, 0, 180))`
If you want to control it more precicly you use microseconds.

```
servo.attach(5,500,2500)
servo.writeMicroseconds(1500);

```

**AND** you have to use an extra power supply for 270 degree servos, the 5V from Arduino want make them move or only in a jittering way of.
If you just have a "defect" 180 degree servo turning to lets say 190 degree for some reason, you might try the microsecond method playing around with the values in attach, also use an extra power supply, but for real over 180 degree action get a 270 degree servo.
> 1 votes

# Answer
Just because a servo can manually be turned more than 180 degrees doesn't mean that it *should* be turned more than 180 degrees.

Most servos will include a certain amount of leeway in their design to help reduce damage from external forces, but the internal design will be geared1 towards operating over a 180 degree range.

While it may be possible to "overdrive" the motor by changing the PWM timing signals (see the Servo attach() reference page) doing so may end up damaging the servo itself.

---

1: Pun intended
> 0 votes

---
Tags: arduino-uno, servo
---


# Question
Title: RGB LED color control with a single value
Apps like Photoshop have a single slider to select color: .

I'd like to achieve the same using variable resistance knob as a slider to control color of RGB LED. Can anyone put me on the right track how to linearly map color values?

# Answer
What you are controlling there is one out of three values from the HSV (aka HSB) colour space.

Colour can be represented in a number of different ways, called "spaces". You computer monitor displays colour in the RGB colour space - red, green and blue. An RGB LED of course also displays in the RGB colour space. Your colour printer works in the CMYK colour space.

Different colour spaces represent the colour using different values and combinations of values, and which colour space you use may be imposed by technical limitations (such as in the printer it is dictated by the combination of the colours of the inks).

HSV is a convenient way of visually manipulating colour since it gives you easy to understand "Hue" (the colour), "Saturation" (how much colour) and "Value" (or "Brightness" - how light the colour is) values that are easy for a human to understand.

However physical devices don't generally work with that colour space, so you need to be able to translate between them.

You can think of HSV as the "Human" colour space, and RGB as the "Digital" colour space.

Fortunately it's relatively simple to convert from one to another and there are a number of code snippets online that give examples of how to do it.

I'm going to include one here that I use in my chipKIT TFT display library "Cariad". Given three 8 bit values (0-255) of "hue" "sat" and "val" it will calculate the red, green and blue values. "hue" would be the one you change with your pot - the others can be static values (or you could add more pots to control those too).

```
    unsigned int H_accent = hue/43;
    unsigned int bottom = ((255 - sat) * val)>>8;
    unsigned int top = val;
    unsigned char rising  = ((top-bottom)  *(hue%43   )  )  /  43  +  bottom;
    unsigned char falling = ((top-bottom)  *(43-hue%43)  )  /  43  +  bottom;

    int r = 0;
    int g = 0;
    int b = 0;

    switch(H_accent) {
        case 0:
                r = top;
                g = rising;
                b = bottom;
        break;

        case 1:
                r = falling;
                g = top;
                b = bottom;
        break;

        case 2:
                r = bottom;
                g = top;
                b = rising;
        break;

        case 3:
                r = bottom;
                g = falling;
                b = top;
        break;

        case 4:
                r = rising;
                g = bottom;
                b = top;
        break;

        case 5:
                r = top;
                g = bottom;
                b = falling;
        break;
    }
    if (r > 255) r = 255;
    if (g > 255) g = 255;
    if (b > 255) b = 255;
    if (r < 0) r = 0;
    if (g < 0) g = 0;
    if (b < 0) b = 0;

```
> 2 votes

---
Tags: arduino-ide
---


title: Read status on SCART output

text:
# Question
Title: Read status on SCART output
I'm trying to get the status of my set top box (on/off).
It does have USB but it's always powered on.
It has optical out that is also always on.
It has an IP address that always responds to ping.

So my next idea is to read the signal in the SCART.
If I read the voltage across pin 8 and 14 I get 0-ish when off and 12 when on.
But when it powers on it spikes at 18 volt (at least what my multimeter can see).
https://youtu.be/D2eVFe33MeM

What do I need to do to read this?
If I add a voltage divider with 1 and 4.7 Kohm I get a safe voltage **if it does not go above 18 volt at any time**.

But what can I do to be sure I don't burn a ESP chip?
Is there any way to make sure it's safe to read even if it spikes at say 25 volts?

# Answer
I would use something like below. The optical isolator (PC817 or similar) protects your ESP.

* Use a 1.0-1.5K resistor from the incoming SCART switch signal (SCART pin 8) to the anode of the Opto isolator (pin 1 in case of the PC817). This will limit the current through the PC817 internal LED to about 10mA with a 12V signal but the PC817 can survive up to 50mA, i.e. up to 60V on the SCART plug and even then will not damage your ESP processor.
* Connect SCART ground (pin 14) to the cathode of the Opto isolator
(pin 2).
* Connect a 3.3K - 4.7K resistor to the collector of the phototransistor of the PC817 (pin 4 of the PC817) and connect the other side of this resistor to Vcc of your ESP (+3.3V) as a pullup.
* Connect pin 3 (emitter) of the PC817 to the Ground of your ESP.
* Connect a digital input pin of your ESP to pin 4 (phototransistor collector) of your PC817 to create an active-low signal indicating your set top box is active.

This is the schematic you could use:

simulate this circuit – Schematic created using CircuitLab
> 1 votes

---
Tags: esp8266
---


# Question
Title: Use NeoSWSerial instead of SoftwareSerial with Adafruit Fingerprint Library
I'm using the FPM10A fingerprint sensor together with the Adafruit Fingerprint Library. I also have a GPS and Bluetooth module on the board already (connected to an Arduino UNO) and I'm using the neoSWserial library to communicate with them. I would like to use neoSWserial to communicate with the fingerprint sensor.

I've replaced all the instances of SoftwareSerial with NeoSWSerial in the respective .h and .cpp files but now the program says

```
'Did not find fingerprint sensor'

```

For completeness here's the sketch, .h and .cpp file:

```
/***************************************************
  This is an example sketch for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit BMP085 Breakout
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Adafruit_Fingerprint.h>

// On Leonardo/Micro or others with hardware serial, use those! #0 is green wire, #1 is white
// uncomment this line:
// #define mySerial Serial1

// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// comment these two lines if using hardware serial
NeoSWSerial mySerial(12, 13);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

void setup()
{
  Serial.begin(9600);
  while (!Serial);  // For Yun/Leo/Micro/Zero/...
  delay(100);
  Serial.println("\n\nAdafruit finger detect test");

  // set the data rate for the sensor serial port
  finger.begin(57600);
  delay(5);
  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  finger.getTemplateCount();
  Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");
  Serial.println("Waiting for valid finger...");
}

void loop()                     // run over and over again
{
  getFingerprintIDez();
  delay(50);            //don't ned to run this at full speed.
}

uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK converted!
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    Serial.println("Did not find a match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID);
  Serial.print(" with confidence of "); Serial.println(finger.confidence);

  return finger.fingerID;
}

// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK)  return -1;

  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID);
  Serial.print(" with confidence of "); Serial.println(finger.confidence);
  return finger.fingerID;
}

```

The header file:

```
#ifndef ADAFRUIT_FINGERPRINT_H
#define ADAFRUIT_FINGERPRINT_H

/***************************************************
  This is a library for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit Fingerprint sensor
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "Arduino.h"
#if defined(__AVR__) || defined(ESP8266)
#include <NeoSWSerial.h>
#elif defined(FREEDOM_E300_HIFIVE1)
#include <NeoSWSerial.h>
#define NeoSWSerial NeoSWSerial
#endif

#define FINGERPRINT_OK 0x00
#define FINGERPRINT_PACKETRECIEVEERR 0x01
#define FINGERPRINT_NOFINGER 0x02
#define FINGERPRINT_IMAGEFAIL 0x03
#define FINGERPRINT_IMAGEMESS 0x06
#define FINGERPRINT_FEATUREFAIL 0x07
#define FINGERPRINT_NOMATCH 0x08
#define FINGERPRINT_NOTFOUND 0x09
#define FINGERPRINT_ENROLLMISMATCH 0x0A
#define FINGERPRINT_BADLOCATION 0x0B
#define FINGERPRINT_DBRANGEFAIL 0x0C
#define FINGERPRINT_UPLOADFEATUREFAIL 0x0D
#define FINGERPRINT_PACKETRESPONSEFAIL 0x0E
#define FINGERPRINT_UPLOADFAIL 0x0F
#define FINGERPRINT_DELETEFAIL 0x10
#define FINGERPRINT_DBCLEARFAIL 0x11
#define FINGERPRINT_PASSFAIL 0x13
#define FINGERPRINT_INVALIDIMAGE 0x15
#define FINGERPRINT_FLASHERR 0x18
#define FINGERPRINT_INVALIDREG 0x1A
#define FINGERPRINT_ADDRCODE 0x20
#define FINGERPRINT_PASSVERIFY 0x21

#define FINGERPRINT_STARTCODE 0xEF01

#define FINGERPRINT_COMMANDPACKET 0x1
#define FINGERPRINT_DATAPACKET 0x2
#define FINGERPRINT_ACKPACKET 0x7
#define FINGERPRINT_ENDDATAPACKET 0x8

#define FINGERPRINT_TIMEOUT 0xFF
#define FINGERPRINT_BADPACKET 0xFE

#define FINGERPRINT_GETIMAGE 0x01
#define FINGERPRINT_IMAGE2TZ 0x02
#define FINGERPRINT_REGMODEL 0x05
#define FINGERPRINT_STORE 0x06
#define FINGERPRINT_LOAD 0x07
#define FINGERPRINT_UPLOAD 0x08
#define FINGERPRINT_DELETE 0x0C
#define FINGERPRINT_EMPTY 0x0D
#define FINGERPRINT_SETPASSWORD 0x12
#define FINGERPRINT_VERIFYPASSWORD 0x13
#define FINGERPRINT_HISPEEDSEARCH 0x1B
#define FINGERPRINT_TEMPLATECOUNT 0x1D

//#define FINGERPRINT_DEBUG

#define DEFAULTTIMEOUT 1000 ///< UART reading timeout in milliseconds

///! Helper class to craft UART packets
struct Adafruit_Fingerprint_Packet {

  /**************************************************************************/
  /*!
      @brief   Create a new UART-borne packet
      @param   type Command, data, ack type packet
      @param   length Size of payload
      @param   data Pointer to bytes of size length we will memcopy into the
     internal buffer
  */
  /**************************************************************************/

  Adafruit_Fingerprint_Packet(uint8_t type, uint16_t length, uint8_t *data) {
    this->start_code = FINGERPRINT_STARTCODE;
    this->type = type;
    this->length = length;
    address[0] = 0xFF;
    address[1] = 0xFF;
    address[2] = 0xFF;
    address[3] = 0xFF;
    if (length < 64)
      memcpy(this->data, data, length);
    else
      memcpy(this->data, data, 64);
  }
  uint16_t start_code; ///< "Wakeup" code for packet detection
  uint8_t address[4];  ///< 32-bit Fingerprint sensor address
  uint8_t type;        ///< Type of packet
  uint16_t length;     ///< Length of packet
  uint8_t data[64];    ///< The raw buffer for packet payload
};

///! Helper class to communicate with and keep state for fingerprint sensors
class Adafruit_Fingerprint {
public:
#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  Adafruit_Fingerprint(NeoSWSerial *ss, uint32_t password = 0x0);
#endif
  Adafruit_Fingerprint(HardwareSerial *hs, uint32_t password = 0x0);

  void begin(uint32_t baud);

  boolean verifyPassword(void);
  uint8_t getImage(void);
  uint8_t image2Tz(uint8_t slot = 1);
  uint8_t createModel(void);

  uint8_t emptyDatabase(void);
  uint8_t storeModel(uint16_t id);
  uint8_t loadModel(uint16_t id);
  uint8_t getModel(void);
  uint8_t deleteModel(uint16_t id);
  uint8_t fingerFastSearch(void);
  uint8_t getTemplateCount(void);
  uint8_t setPassword(uint32_t password);
  void writeStructuredPacket(const Adafruit_Fingerprint_Packet &p);
  uint8_t getStructuredPacket(Adafruit_Fingerprint_Packet *p,
                              uint16_t timeout = DEFAULTTIMEOUT);

  /// The matching location that is set by fingerFastSearch()
  uint16_t fingerID;
  /// The confidence of the fingerFastSearch() match, higher numbers are more
  /// confidents
  uint16_t confidence;
  /// The number of stored templates in the sensor, set by getTemplateCount()
  uint16_t templateCount;

private:
  uint8_t checkPassword(void);
  uint32_t thePassword;
  uint32_t theAddress;
  uint8_t recvPacket[20];

  Stream *mySerial;
#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  NeoSWSerial *swSerial;
#endif
  HardwareSerial *hwSerial;
};

#endif

```

And the .cpp file:

```
/***************************************************
  This is a library for our optical Fingerprint sensor

  Designed specifically to work with the Adafruit Fingerprint sensor
  ----> http://www.adafruit.com/products/751

  These displays use TTL Serial to communicate, 2 pins are required to
  interface
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include "Adafruit_Fingerprint.h"

//#define FINGERPRINT_DEBUG

#if ARDUINO >= 100
#define SERIAL_WRITE(...) mySerial->write(__VA_ARGS__)
#else
#define SERIAL_WRITE(...) mySerial->write(__VA_ARGS__, BYTE)
#endif

#define SERIAL_WRITE_U16(v)                                                    \
  SERIAL_WRITE((uint8_t)(v >> 8));                                             \
  SERIAL_WRITE((uint8_t)(v & 0xFF));

#define GET_CMD_PACKET(...)                                                    \
  uint8_t data[] = {__VA_ARGS__};                                              \
  Adafruit_Fingerprint_Packet packet(FINGERPRINT_COMMANDPACKET, sizeof(data),  \
                                     data);                                    \
  writeStructuredPacket(packet);                                               \
  if (getStructuredPacket(&packet) != FINGERPRINT_OK)                          \
    return FINGERPRINT_PACKETRECIEVEERR;                                       \
  if (packet.type != FINGERPRINT_ACKPACKET)                                    \
    return FINGERPRINT_PACKETRECIEVEERR;

#define SEND_CMD_PACKET(...)                                                   \
  GET_CMD_PACKET(__VA_ARGS__);                                                 \
  return packet.data[0];

/***************************************************************************
 PUBLIC FUNCTIONS
 ***************************************************************************/

#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
/**************************************************************************/
/*!
    @brief  Instantiates sensor with Software Serial
    @param  ss Pointer to NeoSWSerial object
    @param  password 32-bit integer password (default is 0)
*/
/**************************************************************************/
Adafruit_Fingerprint::Adafruit_Fingerprint(NeoSWSerial *ss,
                                           uint32_t password) {
  thePassword = password;
  theAddress = 0xFFFFFFFF;

  hwSerial = NULL;
  swSerial = ss;
  mySerial = swSerial;
}
#endif

/**************************************************************************/
/*!
    @brief  Instantiates sensor with Hardware Serial
    @param  hs Pointer to HardwareSerial object
    @param  password 32-bit integer password (default is 0)

*/
/**************************************************************************/
Adafruit_Fingerprint::Adafruit_Fingerprint(HardwareSerial *hs,
                                           uint32_t password) {
  thePassword = password;
  theAddress = 0xFFFFFFFF;

#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  swSerial = NULL;
#endif
  hwSerial = hs;
  mySerial = hwSerial;
}

/**************************************************************************/
/*!
    @brief  Initializes serial interface and baud rate
    @param  baudrate Sensor's UART baud rate (usually 57600, 9600 or 115200)
*/
/**************************************************************************/
void Adafruit_Fingerprint::begin(uint32_t baudrate) {
  delay(1000); // one second delay to let the sensor 'boot up'

  if (hwSerial)
    hwSerial->begin(baudrate);
#if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1)
  if (swSerial)
    swSerial->begin(baudrate);
#endif
}

/**************************************************************************/
/*!
    @brief  Verifies the sensors' access password (default password is
   0x0000000). A good way to also check if the sensors is active and responding
    @returns True if password is correct
*/
/**************************************************************************/
boolean Adafruit_Fingerprint::verifyPassword(void) {
  return checkPassword() == FINGERPRINT_OK;
}

uint8_t Adafruit_Fingerprint::checkPassword(void) {
  GET_CMD_PACKET(FINGERPRINT_VERIFYPASSWORD, (uint8_t)(thePassword >> 24),
                 (uint8_t)(thePassword >> 16), (uint8_t)(thePassword >> 8),
                 (uint8_t)(thePassword & 0xFF));
  if (packet.data[0] == FINGERPRINT_OK)
    return FINGERPRINT_OK;
  else
    return FINGERPRINT_PACKETRECIEVEERR;
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to take an image of the finger pressed on surface
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_NOFINGER</code> if no finger detected
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
    @returns <code>FINGERPRINT_IMAGEFAIL</code> on imaging error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::getImage(void) {
  SEND_CMD_PACKET(FINGERPRINT_GETIMAGE);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to convert image to feature template
    @param slot Location to place feature template (put one in 1 and another in
   2 for verification to create model)
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_IMAGEMESS</code> if image is too messy
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
    @returns <code>FINGERPRINT_FEATUREFAIL</code> on failure to identify
   fingerprint features
    @returns <code>FINGERPRINT_INVALIDIMAGE</code> on failure to identify
   fingerprint features
*/
uint8_t Adafruit_Fingerprint::image2Tz(uint8_t slot) {
  SEND_CMD_PACKET(FINGERPRINT_IMAGE2TZ, slot);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to take two print feature template and create a
   model
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
    @returns <code>FINGERPRINT_ENROLLMISMATCH</code> on mismatch of fingerprints
*/
uint8_t Adafruit_Fingerprint::createModel(void) {
  SEND_CMD_PACKET(FINGERPRINT_REGMODEL);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to store the calculated model for later matching
    @param   location The model location #
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
    @returns <code>FINGERPRINT_FLASHERR</code> if the model couldn't be written
   to flash memory
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::storeModel(uint16_t location) {
  SEND_CMD_PACKET(FINGERPRINT_STORE, 0x01, (uint8_t)(location >> 8),
                  (uint8_t)(location & 0xFF));
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to load a fingerprint model from flash into buffer 1
    @param   location The model location #
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::loadModel(uint16_t location) {
  SEND_CMD_PACKET(FINGERPRINT_LOAD, 0x01, (uint8_t)(location >> 8),
                  (uint8_t)(location & 0xFF));
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to transfer 256-byte fingerprint template from the
   buffer to the UART
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::getModel(void) {
  SEND_CMD_PACKET(FINGERPRINT_UPLOAD, 0x01);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to delete a model in memory
    @param   location The model location #
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
    @returns <code>FINGERPRINT_FLASHERR</code> if the model couldn't be written
   to flash memory
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::deleteModel(uint16_t location) {
  SEND_CMD_PACKET(FINGERPRINT_DELETE, (uint8_t)(location >> 8),
                  (uint8_t)(location & 0xFF), 0x00, 0x01);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to delete ALL models in memory
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_BADLOCATION</code> if the location is invalid
    @returns <code>FINGERPRINT_FLASHERR</code> if the model couldn't be written
   to flash memory
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
uint8_t Adafruit_Fingerprint::emptyDatabase(void) {
  SEND_CMD_PACKET(FINGERPRINT_EMPTY);
}

/**************************************************************************/
/*!
    @brief   Ask the sensor to search the current slot 1 fingerprint features to
   match saved templates. The matching location is stored in <b>fingerID</b> and
   the matching confidence in <b>confidence</b>
    @returns <code>FINGERPRINT_OK</code> on fingerprint match success
    @returns <code>FINGERPRINT_NOTFOUND</code> no match made
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::fingerFastSearch(void) {
  // high speed search of slot #1 starting at page 0x0000 and page #0x00A3
  GET_CMD_PACKET(FINGERPRINT_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3);
  fingerID = 0xFFFF;
  confidence = 0xFFFF;

  fingerID = packet.data[1];
  fingerID <<= 8;
  fingerID |= packet.data[2];

  confidence = packet.data[3];
  confidence <<= 8;
  confidence |= packet.data[4];

  return packet.data[0];
}

/**************************************************************************/
/*!
    @brief   Ask the sensor for the number of templates stored in memory. The
   number is stored in <b>templateCount</b> on success.
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::getTemplateCount(void) {
  GET_CMD_PACKET(FINGERPRINT_TEMPLATECOUNT);

  templateCount = packet.data[1];
  templateCount <<= 8;
  templateCount |= packet.data[2];

  return packet.data[0];
}

/**************************************************************************/
/*!
    @brief   Set the password on the sensor (future communication will require
   password verification so don't forget it!!!)
    @param   password 32-bit password code
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_PACKETRECIEVEERR</code> on communication error
*/
/**************************************************************************/
uint8_t Adafruit_Fingerprint::setPassword(uint32_t password) {
  SEND_CMD_PACKET(FINGERPRINT_SETPASSWORD, (password >> 24), (password >> 16),
                  (password >> 8), password);
}

/**************************************************************************/
/*!
    @brief   Helper function to process a packet and send it over UART to the
   sensor
    @param   packet A structure containing the bytes to transmit
*/
/**************************************************************************/

void Adafruit_Fingerprint::writeStructuredPacket(
    const Adafruit_Fingerprint_Packet &packet) {
  SERIAL_WRITE_U16(packet.start_code);
  SERIAL_WRITE(packet.address[0]);
  SERIAL_WRITE(packet.address[1]);
  SERIAL_WRITE(packet.address[2]);
  SERIAL_WRITE(packet.address[3]);
  SERIAL_WRITE(packet.type);

  uint16_t wire_length = packet.length + 2;
  SERIAL_WRITE_U16(wire_length);

  uint16_t sum = ((wire_length) >> 8) + ((wire_length)&0xFF) + packet.type;
  for (uint8_t i = 0; i < packet.length; i++) {
    SERIAL_WRITE(packet.data[i]);
    sum += packet.data[i];
  }

  SERIAL_WRITE_U16(sum);
  return;
}

/**************************************************************************/
/*!
    @brief   Helper function to receive data over UART from the sensor and
   process it into a packet
    @param   packet A structure containing the bytes received
    @param   timeout how many milliseconds we're willing to wait
    @returns <code>FINGERPRINT_OK</code> on success
    @returns <code>FINGERPRINT_TIMEOUT</code> or
   <code>FINGERPRINT_BADPACKET</code> on failure
*/
/**************************************************************************/
uint8_t
Adafruit_Fingerprint::getStructuredPacket(Adafruit_Fingerprint_Packet *packet,
                                          uint16_t timeout) {
  uint8_t byte;
  uint16_t idx = 0, timer = 0;

  while (true) {
    while (!mySerial->available()) {
      delay(1);
      timer++;
      if (timer >= timeout) {
#ifdef FINGERPRINT_DEBUG
        Serial.println("Timed out");
#endif
        return FINGERPRINT_TIMEOUT;
      }
    }
    byte = mySerial->read();
#ifdef FINGERPRINT_DEBUG
    Serial.print("<- 0x");
    Serial.println(byte, HEX);
#endif
    switch (idx) {
    case 0:
      if (byte != (FINGERPRINT_STARTCODE >> 8))
        continue;
      packet->start_code = (uint16_t)byte << 8;
      break;
    case 1:
      packet->start_code |= byte;
      if (packet->start_code != FINGERPRINT_STARTCODE)
        return FINGERPRINT_BADPACKET;
      break;
    case 2:
    case 3:
    case 4:
    case 5:
      packet->address[idx - 2] = byte;
      break;
    case 6:
      packet->type = byte;
      break;
    case 7:
      packet->length = (uint16_t)byte << 8;
      break;
    case 8:
      packet->length |= byte;
      break;
    default:
      packet->data[idx - 9] = byte;
      if ((idx - 8) == packet->length)
        return FINGERPRINT_OK;
      break;
    }
    idx++;
  }
  // Shouldn't get here so...
  return FINGERPRINT_BADPACKET;
}

```

Is what I'm doing at all possible or am I just doing it wrongly?

# Answer
I got it to work with NeoSWSerial and some help from AdaFruit. For those in the future:

1. Write the blank example sketch to the arduino
2. Go to device manager and switch the COM port that the arduino is connected to COM1 (Right click \> Properties) - This applies even if you're using an FTDI breakout
3. Download and extract the SFG Demo Software
4. Click Open Device and select COM1
5. Change the baud rate (lower left corner) to 19200 - anything else seems unreliable (from my testing)
6. Replace all instances of SoftwareSerial to NeoSWSerial in the .cpp and .h files as well as your sketch. Change the finger.begin(57600) to finger.begin(19200) in the example sketches and that's it

If it doesn't work go back to device manager and change the baud rate on the COM port to 57600 Hope this helps someone!
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: How to replace String objects with char arrays while still using string methods
I am running the following code on my ESP8266 (AI-Thinker ESP8266MOD).

I send an HTTP GET request and a pin is set to high for a 1/2 second.

However, after some time (sometimes 1hr, 2hrs, 12hrs, totally random), it stops responding to HTTP requests. I think it might be because of heap fragmentation due to the String objects I'm using.

**Questions:**

How can I replace the `request` (in `loop()`) and `s` and `text` (in `GenerateResponse()`) objects with char arrays? After I replace the String objects with char arrays, how can I use the `indexOf()` method and `+` operator on the char arrays?

Will this approach help with heap fragmentation?

Is it possible to find out if heap fragmentation is the problem?

```
#include <ESP8266WiFi.h>

const char* ssid = "myWifi";
const char* wifiPassword = "y76ggS";
const char* passwordToOpenDoor = "/81"; //password should begin with a slash

const int doorPin = 5;

WiFiServer server(301); //Pick any port number you like
WiFiClient client;

void setup() {
  Serial.begin(115200);
  delay(10);
  Serial.println(WiFi.localIP());

  pinMode(doorPin, OUTPUT);
  digitalWrite(doorPin, 0);

  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, wifiPassword);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  server.begin();
  Serial.println("Server started. Diagnostics info:");
  Serial.println(WiFi.localIP());
}

void loop() {
  client = server.available();
  if (!client) {
    return;
  }

  while(!client.available()){
    delay(1);
  }

  String request = client.readStringUntil('\r');
  client.flush();

  Serial.println(request);
  if (request.indexOf(passwordToOpenDoor) != -1) { //Is password correct?
    GenerateResponse("Password is correct");
    OpenDoor();
  }
  //Got a GET request and it wasn't the favicon.ico request, must have been a bad password:
  else if (request.indexOf("favicon.ico") == -1) {
    GenerateResponse("Password is incorrect.");
  }
}

void OpenDoor() {
  digitalWrite(doorPin, 1);
  delay(500);
  digitalWrite(doorPin, 0);
}

void GenerateResponse(String text) {
  Serial.println(text);
  String s = "HTTP/1.1 200 OK\r\n";
  s += "Content-Type: text/html\r\n\r\n";
  s += "<!DOCTYPE HTML>\r\n<html>\r\n";
  s += "<br><h1><b>" + text + "</b></h1>";
  s += "</html>\n";
  client.flush();
  client.print(s);
  delay(1);
}

```

# Answer
> 2 votes
You already received good answer about some *general* ideas for replacing `String` objects with C strings. Here I will try to add some more tricks more specifically targeted to your actual situation.

I can see two places in your program where the use of `String` shines by its convenience, and replacing it with C strings will require some effort. The first is the use of `Stream::readStringUntil(char)` for getting the first request line. Here ~~I see no better option~~ (see edit below) than reading the stream one character at a time, and putting those characters into an array:

```
const size_t input_buffer_length = 256;

// Read a line of text up to the first '\r'.
// Returns a NUL-terminated string, without the final '\r',
// into a statically allocated buffer.
// Warning: this never times out.
const char *readline(Stream &input)
{
  static char buffer[input_buffer_length];
  size_t pos = 0;  // writing position within the buffer
  int c;           // current character
  while ((c = input.read()) != '\r') {
    if (c >= 0 && pos < sizeof buffer - 1) {
      buffer[pos++] = c;
    }
  }
  buffer[pos] = '\0';  // terminate the string
  return buffer;
}

```

You would use it like this:

```
const char *request = readline(client);

```

For more robustness, you may want to add a timeout. Note also that this implementation is no reentrant, as it uses a static buffer. This is not an issue for your use case.

**Edit**: As noted by hcheung in a comment, you do not need to implement this `readline()` function, as you can use `Stream::readBytesUntil()`, which handles the timeout and is provided by the Arduino core:

```
char buffer[input_buffer_length];
client.readBytesUntil('\r', buffer, input_buffer_length);

```

The other place is the usage of `String::operator+=(const char *)` for generating the response. Here I would advice you *against* using `strcat()` or `strncat()`: these will require extra memory to store the concatenated string which you probably do not need. Instead, you can simply `print()` the pieces one by one:

```
void GenerateResponse(const char *text) {
  Serial.println(text);
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println();
  client.println("<!DOCTYPE HTML>");
  client.println("<html>");
  client.print("<br><h1><b>");
  client.print(text);
  client.println("</b></h1></html>");
  client.flush();
  delay(1);
}

```

Alternatively, you can make use of the implicit concatenation of string literals in order to reduce the number of calls to `client.print()`:

```
void GenerateResponse(const char *text) {
  Serial.println(text);
  client.print(
      "HTTP/1.1 200 OK\r\n"
      "Content-Type: text/html\r\n"
      "\r\n"
      "<!DOCTYPE HTML>\r\n"
      "<html>\r\n"
      "<br><h1><b>"
  );
  client.print(text);
  client.print("</b></h1></html>\r\n");
  client.flush();
  delay(1);
}

```

# Answer
> 2 votes
So here is code to get you started:

```
myMessageArray [256] = {'\0'}; // Define global array large enough and zero terminate

```

the + method is replaced by

```
strcpy (myMessageArray, "Text to Add");
// Initializes the myMessageArray starts at index 0
strcat (myMessageArray, "More text to Add");
// Appends to the myMessageArray starts at current index

```

converting numeric values to chars:

```
uint_16_t myNumberValue  = 31253;
char numBuffer [16] = {'\0'}; // Helper buffer for conversions

itoa (myNumberValue,numBuffer,10);  // converts an integer to a base 10 (decimal) char
itoa (myNumberValue,numBuffer,2);  // converts an integer to a base 2 (binary) char
itoa (myNuberValue,numBuffer,16);  // converts an integer to a base 16 (hex) char

```

itoa initilizes a char array so we need the helper array:

```
strcat (myMessageArray, numBuffer);

```

to convert float we use

```
dtostrf(floatVariable, StringLengthIncDecimalPoint, numVarsAfterDecimal, numBuffer);

```

to convert chars back to int use

```
int16_t myIntVar = atoi(numBuffer);

```

to convert chars back to floats use

```
float myFloatVar = atof(numBuffer, decimalsToShow); // using just atof(numBuffer)
gives you standard x.XX only 2 decimals

```

A working IndexOf for char arrays:

```
/*******************************************************************************/
/**
    \brief Finds the index of the given value in the array starting at the given index
    \author codebreaker007
    \param [in] targetArray the array to search through for the char
    \param [in] valueToFind the value to find
    \param [in] startIndex the index to start searching at
    \return the index of the value within the array

    \details This method returns INDEX_NOT_FOUND^(-1) for a null input array.
        A negative startIndex is treated as zero. A startIndex larger than the array
        length will return INDEX_NOT_FOUND(-1)
*/
/********************************************************************************/
int8_t indexOf(char* targetArray, char valueToFind, uint16_t startIndex = 0) {
  if (targetArray == NULL) {
    return INDEX_NOT_FOUND;
  }
  if (startIndex <= 0) {
    startIndex = 0;
  }
  for (uint16_t i = startIndex; i < strlen(targetArray); i++) {
    if (valueToFind == targetArray[i]) {
      return i;
    }
  }
  return INDEX_NOT_FOUND;
}

```

To compare char arrays you should look into the `strcmp` function and if you want to checkthe first n char tomatchyou use:

```
if (strncmp(myMessageArray , "POST", 4 ) == 0) {
// compares the first 4 chars if it matches = 0, see details in the arduino doku

```

Hope this comprehensive intro to char arrays helps you for your current and future projects. How to find out - convert to char arrays and if its runnibg stable that was it. Before that conversion you can never rule out String class as culprit.

# Answer
> 1 votes
You asked: "After I replace the String objects with char arrays, how can I use the indexOf() method and + operator on the char arrays?"

Short answer: You can't. If you want to use C strings (aka arrays of char), you'll have to use C string functions.

The String methods operate on String objects. The common wisdom is to avoid the String class entirely since it relies on heap memory, and Arduinos are far, far too memory-starved to be able to use a class like String which creates temporary objects on the heap.

---
Tags: esp8266, string, http, c-string
---