# Question
Title: How can I get additional Slave Select pins?
I have a project where I want to connect a number of SPI devices, and I'm running out of Slave Select pins (SPI) on the Arduino. So I thought that I could use something like an MCP23S17 to get additional pins and use those as SS pins, but most libraries require to pass the pins when initialising, and it seems that I can't pass the MCP's pins as a function/class argument (or can I?). For example:

```
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /*cs*/ 12, /*dc*/ 4, /*rst*/ 6);

```

So my question is: How can I get more SS pins? Thank you

# Answer
> 1 votes
I would suggest adding a layer of abstraction in your whole design.

Use the ESP8266 as the main system controller, then farm out sensor communications to one or more other "active" expansion devices.

Rather than just using an expander for the SS pins you are using the "expander" for all the communication.

By "expander" I basically mean some other microcontroller (maybe an ATMega328P for example) which receives an instruction to sample a sensor then goes off and gathers the data that is wanted and sends it back to the master ESP8266 controller.

How you arrange that communication is up to you, but maybe I2C would be a good way to go. You could even make the sensor data gathering completely autonomous so that the ESP8266 just then requests the latest data from the slave(s).

It means:

* You don't have to change any libraries
* You get distributed processing, sharing the work out
* The ability to communicate with an almost infinite number of sensors

# Answer
> 3 votes
My solution would be to keep it simple. Use real pins for every SPI SS. Buy an other Arduino board with more pins if you need more pins.

What else is connected to your Arduino board ? Perhaps it is easier to reduce those pins. Almost all analog pins can be digital pins as well. You could use external ADC modules. Perhaps replacing 1-Wire or DHT11 or DTH22 with I2C sensors. Using a I2C display. There are many options to use buttons and leds with a few pins. And so on.

# Answer
> 1 votes
A maybe dirty solution is to change all the libraries. Everywhere the SS pin is used, instead call a function and set it yourself (by using the MCP23S17).

To make this a bit better, define a class that contains this functionality to abstract it from the changed library classes.

Example:

As initialization of the library a function or class constructor will be used, e.g.

```
MCP23S17(void);

```

This you will use like:

```
MCP23S17 my_component = MCP23S17();

```

You need to change this to:

```
MCP23S17(int ss_pin);

```

And change the related code, store it in a class variable and use it everywhere in the library instead of the fixed SS pin number.

Than you can constructor your own instance by:

```
MCP23S17 my_component = MCP23S17(4);

```

Where 4 is the SS pin number

---
Tags: pins, spi
---


# Question
Title: error: expected unqualified-id before '.' token
I am working on a library to display custom text on a TFT screen and I came up with this error while making an example:

```
EsploraHelloWorld:31: error: expected unqualified-id before '.' token
   TFTCharPlus.drawChar(chars[5, 0], chars[5, 1], chars[5, 2], chars[5, 3], chars[5, 3], 120, 0, 255, 255, 255, 4, EsploraTFT);
               ^

```

Heres my code:

```
#include <Esplora.h>
#include <SPI.h>
#include <TFT.h>
#include <TFTCharPlus.h>

// A table for all of the characters
const char chars[6][5] = {
  {0xf8, 0x20, 0xf8, 0x1f, 0x15},
  {0xf8, 0x08, 0x08, 0x1f, 0x01},
  {0x70, 0x88, 0x70, 0x00, 0x00},
  {0xc0, 0x20, 0xc6, 0x29, 0xc6},
  {0xf0, 0x40, 0x80, 0x5f, 0x01},
  {0xf0, 0x90, 0x60, 0x00, 0x3d}
};

TFTCharPlus TFTCharPlus();

void setup() {
  // initialize the screen
  EsploraTFT.begin();

  // make the background black
  EsploraTFT.background(0,0,0);

  // print the characters
  TFTCharPlus.drawChar(chars[0, 0], chars[0, 1], chars[0, 2], chars[0, 3], chars[0, 3], 0, 0, 255, 255, 255, 4, EsploraTFT);
  TFTCharPlus.drawChar(chars[1, 0], chars[1, 1], chars[1, 2], chars[1, 3], chars[1, 3], 24, 0, 255, 255, 255, 4, EsploraTFT);
  TFTCharPlus.drawChar(chars[2, 0], chars[2, 1], chars[2, 2], chars[2, 3], chars[2, 3], 48, 0, 255, 255, 255, 4, EsploraTFT);
  TFTCharPlus.drawChar(chars[3, 0], chars[3, 1], chars[3, 2], chars[3, 3], chars[3, 3], 72, 0, 255, 255, 255, 4, EsploraTFT);
  TFTCharPlus.drawChar(chars[4, 0], chars[4, 1], chars[4, 2], chars[4, 3], chars[4, 3], 96, 0, 255, 255, 255, 4, EsploraTFT);
  TFTCharPlus.drawChar(chars[5, 0], chars[5, 1], chars[5, 2], chars[5, 3], chars[5, 3], 120, 0, 255, 255, 255, 4, EsploraTFT);
}

void loop() {
  // not necessary
}

```

And for reference, here is the `drawChar()` function:

```
void TFTCharPlus::drawChar(byte data1, byte data2, byte data3, byte data4, byte data5, uint8_t xpos, uint8_t ypos, uint8_t colR, uint8_t colG, uint8_t colB, uint8_t size, TFT tft) {
  tft.stroke(colR, colG, colB);
  tft.fill(colR, colG, colB);
  byte data[5] = {data1, data2, data3, data4, data5};
  for (uint8_t x = 0; x < 5; x++) {
    for (uint8_t y = 0; y < 8; y++) {
      if (bitRead(data[x], 7 - y)) {
        tft.rect(x*size+xpos, y*size+ypos, size, size);
      }
    }
  }
}

```

How can I fix the error?

**BTW**: The error is not in the library, everything is done correctly

**EDIT**: I realized that the error occurs on all six `drawChar()` lines, and After fixing a small error, I also got this: `request for member 'drawChar' in 'TFTCharPlus', which is of non-class type 'TFTCharPlus()'`

# Answer
> 1 votes
It appears that you are calling the "description" of the library method (function). What is necessary is to use the "description" to create a "working copy" of the library method. Then call the "working copy".

In the above statement, the "description" is the Class, "to create" means to instantiate and "working copy" is referred to as the Object.

In the Arduino Serial Port Example, you will find the following line:

```
SoftwareSerial mySerial(10, 11); // RX, TX

```

Here, the Class "SoftwareSerial" is used to instantiate the Object "mySerial". Later in the code calls are made to the "write" method with in that object:

```
mySerial.write(Serial.read());

```

# Answer
> 0 votes
In this line:

```
TFTCharPlus TFTCharPlus();

```

you've given your TFT object the same name as its class, making that name ambiguous. If you change the name of the object to, e.g.:

```
TFTCharPlus TFTobject();

```

as well as changing all of your references to it (`TFTobject.drawChar(...)`), it should fix the issue.

---
Tags: library
---


title: How does the Space Replay record audio?

text:
# Question
Title: How does the Space Replay record audio?
> The Space Replay
>
> A hovering object that explores and manipulates transitional public spaces with particular acoustic properties. By constantly recording and replaying these ambient sounds, the levitating sphere produces a delayed echo of human activity.

In this project, the Arduino board and an Adafruit Wave Shield is used. The Wave shield is not designed to record audio however, they say that they use the board for both *recording* and playback.

> The sphere responds sonically to people and its surroundings by means of a battery-powered Arduino, an Adafruit Wave Shield hacked to record and playback audio on-the-fly and a small speaker.

This generates a few questions.

* How would this be done?
* Where would the microphone be placed inside the balloon for decent audio capture?
* Would there be a better way to design this?

# Answer
It seems to be possible to record with the shield using a library called waverp

> WaveRP is an Arduino library for recording and playing Wave files with the Adafruit Wave Shield. It records 8-bit mono files at 4,000 to 44,100 samples per second.

Some details adafruit blog:

> It records 8-bit mono files at 4,000 to 44,100 samples per second.
> 4 votes

# Answer
As jippie said, you can use the Arduinos ADC to record audio, and presumably save that to the Arduino's RAM (the SD card is probably too slow for directly saving it). Then it writes the buffer to the SD card.
> 0 votes

# Answer
Maybe is kind of late but I found the code for the Space Replay is in here at the bottom of the last image, specifically in here

```
/*------------------------------------------------------------------------------

        __-__         Code for Space Replay, a floating black orb that records
      .X+..   Â·       and plays back ambient sounds. This sketch was adapted by
    .Xx+-Â·..    Â·     Francesco Tacchini, with the help of Oliver Smith & Brock
    XXx++-...         Craft, from the original WaveRecordPlay example sketch
    XXxx++--.....Â·    written by Bill Greiman.
    `XXXxxx++---'     This project was created as part of a university project at
      `XXXxxxx'       the Royal College of Art. It's a collaboration with Julinka
         """          Ebhardt and Will Yates-Johnson. See more: vimeo.com/88992597

------------------------------------------------------------------------------*/

#include <SdFat.h>
#include <WaveRP.h>
#include <SdFatUtil.h>
#include <ctype.h>

#define MIC_ANALOG_PIN 0             // Define the analog pin
#define RECORD_RATE 44100            // Define the record rate
#define ADC_REFERENCE ADC_REF_AVCC
#define PRINT_FILE_INFO 0            // Useful for debug: print file info and
#define PRINT_DEBUG_INFO 1           // bad wave file size or SD busy errors
#define MAX_FILE_SIZE 104857600UL    // 100MB or 150 min at 11025 samples/second
#define DISPLAY_RECORD_LEVEL 1

// debugging led
int playLED = 7;
int recLED = 8;
int delStopLED = 9;

// global variables
Sd2Card card;           // SD/SDHC card with support for version 2.00 features
SdVolume vol;           // FAT16 or FAT32 volume
SdFile root;            // volume's root directory
SdFile file;            // current file
WaveRP wave;            // wave file recorder/player
int16_t lastTrack = -1; // Highest track number
uint8_t trackList[32];  // bit list of used tracks

//------------------------------------------------------------------------------
// print error message and halt
void error(char* str) {
  PgmPrint("error: ");
  Serial.println(str);
  if (card.errorCode()) {
    PgmPrint("sdError: ");
    Serial.println(card.errorCode(), HEX);
    PgmPrint("sdData: ");
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}
//------------------------------------------------------------------------------
uint8_t trackName(int16_t number, char* name) {
  if (0 <= number && number <= 255) {
    strcpy_P(name, PSTR("TRACK000.WAV"));
    name[5] = '0' + number/100;
    name[6] = '0' + (number/10)%10;
    name[7] = '0' + number%10;
    return true;
  }
  PgmPrint("Invalid track number: ");
  Serial.println(number);
  return false;
}
//------------------------------------------------------------------------------
// start file playing
uint8_t playBegin(char* name) {
  if (!file.open(&root, name, O_READ)) {
    PgmPrint("Can't open: ");
    Serial.println(name);
    return false;
  }
  if (!wave.play(&file)) {
    PgmPrint("Can't play: ");
    Serial.println(name);
    file.close();
    return false;
  }
#if PRINT_FILE_INFO
  Serial.print(wave.bitsPerSample, DEC);
  PgmPrint("-bit, ");
  Serial.print(wave.sampleRate/1000);
  PgmPrintln(" kps");
#endif // PRINT_FILE_INFO
#if PRINT_DEBUG_INFO
  if (wave.sdEndPosition > file.fileSize()) {
    PgmPrint("play Size mismatch,");
    Serial.print(file.fileSize());
    Serial.print(',');
    Serial.println(wave.sdEndPosition);
  }
#endif // PRINT_DEBUG_INFO
  PgmPrint("Playing: ");
  Serial.print(name);
  return true;
}
//------------------------------------------------------------------------------
// play all files in the root dir
void playTracks(void) {
  dir_t dir;
  char name[13];
  uint8_t np = 0;
  root.rewind();
  while (root.readDir(&dir) == sizeof(dir)) {
    //only play wave files
    if (strncmp_P((char *)&dir.name[8], PSTR("WAV"), 3)) continue;
    // remember current dir position
    uint32_t pos = root.curPosition();
    // format file name
    SdFile::dirName(dir, name);
    if (!playBegin(name)) continue;
    PgmPrintln("");
    while (wave.isPlaying()) {
      uint8_t c = Serial.read();
    }
  }
  file.close();
}
//------------------------------------------------------------------------------
// delete a track
void trackDelete(int16_t track) {
  char name[13];
  if (!trackName(track, name)) return;

  if (SdFile::remove(&root, name)) {
    PgmPrintln("Deleted!");
  }
  else {
    PgmPrintln("Delete failed!");
  }
}
//------------------------------------------------------------------------------
// Finally we have the normal SETUP and LOOP functions -------------------------
//------------------------------------------------------------------------------
void setup(void) {
  Serial.begin(9600);
  if (!card.init()) error("card.init");
  if (!vol.init(&card)) error("vol.init");
  if (!root.openRoot(&vol)) error("openRoot");

  pinMode(playLED, OUTPUT);
  pinMode(recLED, OUTPUT);
  pinMode(delStopLED, OUTPUT);

}
//------------------------------------------------------------------------------
// loop to play and record files.
void loop() {
  digitalWrite(delStopLED, HIGH);
  if (file.isOpen()){
    file.close();      // Make sure file is closed
  }

  int16_t track = -1;
  uint8_t c;
  if (track < 0 ) {
    track = lastTrack;
  }

  char name[13];
  if (track < 0) track = lastTrack + 1;
  if (!trackName(track , name)) return;
  if (file.open(&root, name, O_READ)) {
    file.close();
    trackDelete(track);
    return;
  }
  digitalWrite(delStopLED, LOW);
  digitalWrite(recLED, HIGH);
  Serial.println( "Recording" );    // Record new file...

  if (!file.createContiguous(&root, name, MAX_FILE_SIZE)) {
      PgmPrintln("Create failed");
      return; }
  if(!wave.record(&file, RECORD_RATE, MIC_ANALOG_PIN, ADC_REFERENCE)) {
      PgmPrintln("Record failed");
      file.remove();
      return; }

  delay(5000);     // ...for x milliseconds
  digitalWrite(recLED, LOW);
  wave.stop();
  wave.trim(&file);
  file.close();     // Stop the recording, trim and close the file

  digitalWrite(playLED, HIGH);
  playTracks();     // Play the file
  digitalWrite(playLED, LOW);
}

```

About your questions,

* In the latest WaveRP library there's a folder where it explains how to attach a microphone to the waveshield. And I'm guessing I don't know for sure, but I'd say they're using a contact mic, the contact mics are both, mics and speakers, some cheap walkies also use them. So I'm guessing that they're using only one?
* Contact mics pick up vibration so, I think the plastic cone that they're using is for de contact mic to pick up the vibrations of the surroundings sounds.
* A better way to design it? I think that it depends. In a way is an art piece. So, a better way to design it... is like to ask VanGogh a better way to paint sunflowers. But I think always the sound can be better. A way to improve it could be making a better amplifier circuit for reduce the noise or separating the mic and the speakers... But I don't know, I think it depends what you want to make and what you want to achieve. Because if you want it to float is better to have the leastest components. But if the sound is the priority I think it can be much more better using an amplifier, a better mic, etc.

Also, now in the Adafruit Wave Shield's page there is a project of realtime voice changer, that also record and playbacks. More information here
> 0 votes

---
Tags: sensors, shields, project-critique
---


title: PIR motion sensor stuck in a loop

text:
# Question
Title: PIR motion sensor stuck in a loop
I've bought an HC-SR501-compliant **PIR motion sensor** (like this one) and connected it to a **Teensy 3.1**. The circuit seems fine, and the LED lights up. However, **when nothing is moving in front of it, the sensor keeps reporting HIGH and LOW in suspiciously constant intervals**. The monitor reads like this (numbers in milliseconds)

```
motion detected  4113
motion stopped   7234
motion detected  4114
motion stopped   7274
motion detected  4113
motion stopped   7204
motion detected  4111
motion stopped   7184

```

When it detects movement, it stays on the triggered position for longer, but even then goes back to predetermined intervals, e.g.

```
motion detected   4113
motion stopped   17204
motion detected   4111
motion stopped   41754
motion detected   4113

```

This is the sketch (as found on Adafruit):

```
int ledPin   = 13;              // choose the pin for the LED
int inputPin = 1;               // choose the input pin (for PIR sensor)
int pirState = LOW;             // we start, assuming no motion detected
int val      = 0;               // variable for reading the pin status

unsigned long lastTime = millis();

void setup() {
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare sensor as input

  Serial.begin(9600);
}

void loop(){
  unsigned long currentTime = millis();

  val = digitalRead(inputPin);   // read input value
  if (val == HIGH) {             // check if the input is HIGH
    digitalWrite(ledPin, HIGH);  // turn LED ON
    if (pirState == LOW) {

      // we have just turned on
      Serial.print("motion detected ");
      Serial.println(currentTime - lastTime);

      // We only want to print on the output change, not state
      pirState = HIGH;

      // Save time for measurement
      lastTime = currentTime;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    if (pirState == HIGH){

      // we have just turned off
      Serial.print("motion stopped ");
      Serial.println(currentTime - lastTime);

      // We only want to print on the output change, not state
      pirState = LOW;

      // Save time for measurement
      lastTime = currentTime;
    }
  }
}

```

**Could this be a faulty device?** I'm thinking about getting a new one for testing. While I can compensate for the gaps when triggered, I can't think of a way to make sure that it's not actually being triggered by this weird internal interval.

# Answer
> 1 votes
Try powering the PIR motion sensor with a higher voltage. I get the same problem you're seeing when powering it with the 3.3v output of an Adafruit Huzzah ESP-12, but it works just fine when I power it with the 5v USB power.

---
Tags: sensors, teensy
---


# Question
Title: Can't upload any code to my Arduino board
I have an Arduino Uno R3 with an ATmega238 microchip. I can't upload any code to it: the green led and pin13 LED are always on (without flashing ) and the RX and TX LEDs don't flash when I upload code or press the reset button. Is the microchip malfunctioning?

And what happens when a reverse current returns to Arduino from a relay?

# Answer
> 1 votes
You basically have 2 questions here.

1: Why is my Uno not uploading code.

2: How does back EMF effect a microcontroller. We'll address 2 first

When a relay module is activated, it energizes a coil to close a switch. This coil is an inductor, which is an energy storage device. When the signal to the relay tells it to turn off, your trying to de-energize the coil. Whereas before you let current run through the coil to establish a magnetic field, now you cut the current supply and let the magnetic field die out. The problem this creates is back EMF. As Faraday's law will tell us, a change in a magnetic field causes a voltage (an EMF) in a coil. When we were charging the circuit, this was the voltage applied to the coil. When we discharge the inductor, this voltage is back EMF, and is in **the opposite direction as charging voltage**.

How does this affect your arduino? Well, it can be anything ranging from harmless to catastrophic. It may simply reset your arduino (as one I was working with did on a past project \[where an occiliscope showed back EMF spikes in excess of -30V\]) or it might straight-up burn the ATMega328p that acts as the Uno's brain. Or it might take out the voltage regulator, or cause a host of other problems.

The simplest fix for back EMF is to put a diode in parallel with the relay with cathode to your positive terminal and anode to your negetive terminal. This creates a short for the relay's coil to discharge through. Some better solutions (especially for sensitive digital equiptment) involve entirely isolating the relay's power supply form the rest of your circuit with an optoisolator.

Problem 1: Assuming that these problems were related to the use of a relay without the proper safeguards, you might try a few things to verify your chip is still alive. If you have a second arduino you might try using it to build an ISP, which will allow you to both reburn the bootloader and upload sketches independently of the uno's onboard usb com port programmer. If that works but the onboard programmer still does not, you may need to reflash the programmer (which I've read can also be done with an ISP, though I've never tried it.)

Hope that helps!

---
Tags: arduino-uno
---


# Question
Title: How to connect a Pressure Sensor-MPX10DP to an Arduino?
I'm very new to Arduino, I'm trying to connect an air pressure Sensor without success.

I followed this tutorial:

Arduino Air Pressure Measurement

The values I'm getting are very weird and the variations when I blow in the sensor are not more than about `+/- 0.2`.

So, the tutorial does use the same model, is that why? I need something else?

Any help will be very appreciated.

# Answer
The MPX10DP does not have an amplifier inside. The output is the output of the internal wheatstone bridge. It is not even compensated for temperature.

This is the manufacturers page about the MPX10 series: nxp.com MPX10 series.

You need an instrumentation amplifier and perhaps a temperature compensation. The INA125 is an instrumentation amplifier. It was used in the past with the Arduino a lot. Nowadays, most sensors are digital, and the bare sensors with wheatstone bridge output are not used that often anymore.

When you connect both sensor outputs to two Arduino inputs (without amplifier), then the difference is 35mV for 10kPa. The resolution is in theory 5V / 1024. The overall accuracy for two analog inputs perhaps 9 bits, then you can measure the 10kPa in 3.5 steps (about 2 or 3 kPa resolution).
If you seriously want to use this specific sensor, and don't want to use extra hardware, then you might have a look at my question about the differential mode and gain that is possible with the Arduino Mega 2560 and Leonardo.

Or you could buy a pressure sensor with 0...5V output, that can be connected to the Arduino analog input. The tutorial you mentioned uses the MPX5010. That sensor has a amplifier inside and is temperature compensated. They are reliable and ratiometric with the 5V, therefor super easy to use. With a lot of averaging in the code, you can get a high (relative) accuracy.
> 1 votes

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


# Question
Title: Which Timer can I use on the Arduino/Genuino Micro?
I'm trying to implement charlieplexing with bit angle modulation on my Arduino Micro, and for that I need to use the internal timers.

Which timers of the Atmega32u4 are unused by the standard firmware? Ideally I'd like to use either Timer1 or Timer3 as they have the highest resolution.

# Answer
Only Timer0 is used for millis and micros, just as with the Arduino Uno and Mega 2560.

Timer0 is used in "wiring.c".
That same file is used for the Uno, Mega 2560, Leonardo and Micro. The differences for the Leonardo is the pin numbers in "pins\_arduino.h".

If you don't use PWM output with analogWrite, then you can use all of the other timers. The timers are set to certain values in the function init (also in wiring.c). But you can ignore that if you never use analogWrite.
> 1 votes

---
Tags: pwm, timers, arduino-micro, atmega32u4
---


# Question
Title: Custom board with ATMega32u4 having USB issues
I built a custom arduino based board (speciffically based off of Sparkfun's Pro Micro 3.3V 8Mhz and their Qduino mini boards) that uses the ATMega32u4-RC.

The board I built integrated an acceleromter (LSM6DS3) and a micro-SD card holder, and eleminated any uneeded GPIO. (This is basically a datalogger board for the LSM6DS3 accelerometer). It also inlcudes a usb-powered LIPO charging circuit, which is copied from the qduino mini.

A picture of the board I built, with power LED indicating life.

The problem I am experiencing is that, after apparently sucessfull upload of the bootloader (I've tried the bootloader for the qduino mini, promicro 3.3v 8Mhz, even the Leonardo), my computer will not reconize the board. I've exauhsted all the information about driver installation from the sources for the boards my board is based on, and still can't make windows recognize my custom board.

Specifically, I've tried using a multitude of signed and unsigned drivers (on Windows 10 and 7), and can not get windows to pick anything other than usbfilt.sys as the driver.

Any advice would be greatly appreciated!

Edit: Added Eagle Schematic below

# Answer
> 1 votes
As Chris Stratton pointed out, I neglected to include the 1uF capacitor on UCap. This is absolutely necessary on a 3.3v board for the board to communicate with USB properly.

Thanks!

---
Tags: usb, bootloader, atmega32u4
---


# Question
Title: Can I drive an LM334(Z) from an Arduino with AnalogWrite()?
I need programmable current control, fading from zero to 2 milliAmps. I was hoping to use Arduino's AnalogWrite(), which uses Phase Width Modulation (PWM) to simulate analog output with a sawtooth wave on a duty-cycle; to control an LM334Z to deliver a slowly ramped low current delivery. \[The application is a TransCranial Direct Current Stimulation (TDCS) micro-current delivery to the human scalp. Jumping straight to 2 milliAmps is uncomfortable\]. Will PWM work? Or, do I need some sort of smoothing circuitry to soften the PMW before it is applied to the LM334Z's Rset pin to accomplish the above?

# Answer
If you don't need super high accuracy, using a MOSFET's ohmic region, plus a smoothing filter on the output of your PWM (analog out), could be a solution.
> 2 votes

# Answer
You control the LM334 with a resistance, not a voltage. The current is set by multiplying the current through the resistor.

Maybe you can do what you want by replacing the `Rset` with a digital potentiometer?
> 0 votes

# Answer
> LM334Z's Rset pin to accomplish the above?

Most of that type of circuit has its operations be determined by the current In or out of that pin. So a voltage signal may not work - you will need to experiment. I have had some success with analogs dds chips and linear programmable osscillators.

So try it on your chip. Nothin to lose.
> 0 votes

---
Tags: pwm, current
---


# Question
Title: 2.8" TFT Touchscreen Prohibits Access to Unused Pins
This is probably a beginner question. You've been warned.

I recently purchased a touchscreen (http://www.adafruit.com/products/1651#tutorials) specifically because it left so many pins open to work with and I needed to hook up one, possibly two more items to my Arduino. However the touchscreen fits over the Arduino and covers all the pins.

**How do I access the pins that the LCD isn't using?**

To be specific, I will be adding a Galvanic Skin Sensor on two analog pins.

# Answer
> 1 votes
Dupont jumper cables are your friend. The most useful ones are male-to-female:

You can end up with a bit of a tangled mess though when you have a number of shields all side by side. Not a lot you can do about it though.

# Answer
> 3 votes
Several options:

1. Use wires to connect it rather than sticking it directly onto the Arduino.
2. Use a header extension to lift the display away from the other headers.
3. Use right-angle headers on the other pins.

# Answer
> 0 votes
Really I'm just posting to have participated in the forum. Actually I'm new to arduino, and don't even know how many pins the screen actually uses. My version of the screen is a Pixnor screen made by someone who does not really provide technical description, examples, etc.,, and some of the pins are different, or perhaps the entire chip driving the shield is different, so none of the adafruit sketches work. I haven't figured out anything more than how to hook up the touch to an x,y coordinate serial read,, there's an example somewhere that leaves all of the pins unplugged, with the exception of the touchpad data wires, and lets you play on a dark screen with the coordinate plane.

but anyway, my first thought was, really the touchscreen should plug into a protoshield, which would allow you to have a pin-layout which runs to a protoshield, and then your screen would be fixed over that layout, when would then plop onto your arduino, or back off again without disassembling your sensor/input layout. (which means you can still rig up some experiment with the arduino without having to rerig up your screen and sensors.) ,, So I think I'm going to go about getting more proto-shields.

# Answer
> -1 votes
get a Protoshield, a good one and put it between the arduino and the shield

---
Tags: arduino-uno
---


# Question
Title: character input for an integer variable?
Im trying out the code found here , let me quote the section of code that bothers me.

```
// set pin numbers for switch, joystick axes, and LED:
const int switchPin = 2;      // switch to turn on and off mouse control
const int mouseButton = 3;    // input pin for the mouse pushButton
const int xAxis = A0;         // joystick X axis
const int yAxis = A1;         // joystick Y axis
const int ledPin = 5;         // Mouse control LED

```

xAxis is a variable that is defined as an integer , however, it is being assigned a character(A0), How is this possible? I tried to compile and run the code and everything works well. I'm quite surprised!

# Answer
> 0 votes
A0 and A1 are not characters or what you mean probably: strings. Because it would be written as "A0" and "A1". The types of A0 and A1 are probably integers or another numeric type.

However, these are probably defined as (constant) integers, e.g.:

```
const int A0 = 100;
const int A1 = 101;

```

(note 100 and 101 are random numbers)

or defined by a macro. e.g.:

```
#define A0  100
#define A1  101

```

So the variables A0 and A1 are actually integers (or assigned as numeric values by a define).

# Answer
> 0 votes
The clue is this comment:

```
// set pin numbers for switch, joystick axes, and LED:

```

and the fact that xAxis is declared a `const int`. Because the declaration promises that this variable will not (must not) be changed once it has been initialized, it will not be assigned any memory at run time. The compiler will treat it much like the macro:

```
#define xAxis A0

```

and do a compile-time replacement of `xAxis` with A0, wherever xAxis appears.

`A0` is an analog channel, defined in the board-specific Arduino libraries to the Arduino pin# corresponding to it.

It is a somewhat recent idiom in C and C++ - since the inclusion of "const" in the language - to use "const int" declarations for this purpose instead of "#define" statements. The intent is the same.

---
Tags: arduino-ide, c, data-type
---


# Question
Title: How to store incoming serial string in arduino?
In my recent project, I am working with serial data. Till now, I'm able to receive data and display on LCD. Now, suddenly I can't get any serial data. Nothing display on LCD.

My incoming string is:

```
{"Action":"ONE","TPS":"0.40","MAP":"0.95","LOAD":"14"}

```

And my code is below:

```
#include<LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String response = "";
bool begin = false;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop()
{

  while(Serial.available() || !begin)
  {
    char in = Serial.read();

    if (in == '{')
    {
      begin = true;
    }

    if(begin)
    {
      response += (in);
    }

    if(in == '}')
    {
        break;
    }
    delay(1);
  }

  lcd.setCursor(0, 0);
  lcd.print(response);
}

```

# Answer
Actually I can see what I think may be an issue with your code.

```
 while(Serial.available() || !begin)

```

This isn't right. If there is no data available in the serial buffer but the first `{` hasn't been seen then go and read the non-existent data anyway?

Rather than try and explain what I mean in multiple comments I have put it all together and this is what I think your loop should be this:

```
/// This is un-compiled code, so you might have to fix some little issues.
/// bool begin = false;         // True when the initial { has been seen

void loop()
{
  while (finished == false)
  {
    if (Serial.available())
    {
      const char in = Serial.read();
      if (in == '{')
      {
        response = "";  // Blank the string
        begin = true;
      }
      if (begin)
      {
        response += (in); // Only write if within the {}
      }
      if (in == '}')
      {
        begin = false;   // Prevent any chars between } and { leaking through.
        lcd.setCursor(0, 0);
        lcd.print(response);
      }
    }
    delay(1);
  }

  delay(500); // Not sure what will happen if you send multiple {} to the LCD too fast.
}

```
> 1 votes

# Answer
I just switch from Arduino UNO to Arduino MEGA. And everything works fine. I know this is not a proper answer but I want to know why this happens. I don't understand why this happens? Can anyone explain me?
> 0 votes

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


title: Leonardo-based tachometer?

text:
# Question
Title: Leonardo-based tachometer?
I'm new here. I'm not a native speaker, so pardon my English.

I just received my Arduino Leonardo today. I tried some basic calculations and stuff like blinking and LCD interfacing. Its interesting.

I am now trying to make a tachometer with the Leonardo. I'm following this tutorial.

I guess the board they've used differs from the Arduino Leonardo (ie pin 3 is `interrupt0` in the Leonardo but it is pin 2 in the Arduino Uno board used in the tutorial). I tried changing the pins on the program and reconnecting the circuit but it doesn't work.

This is the code from the tutorial:

```
/* Optical Tachometer
 *
 * Uses an IR LED and IR phototransistor to implement an optical tachometer.
 * The IR LED is connected to pin 13 and ran continually.
 * Pin 3 (interrupt 0) is connected across the IR detector.
 *
 * Code based on: www.instructables.com/id/Arduino-Based-Optical-Tachometer/
 * Coded by: arduinoprojects101.com
 */

int ledPin = 13; // IR LED connected to digital pin 13
volatile byte rpmcount;
unsigned int rpm;
unsigned long timeold;
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void rpm_fun() {
  //Each rotation, this interrupt function is run twice,
  //so take that into consideration for calculating RPM
  //Update count
  rpmcount++;
}

void setup() {
  lcd.begin(16, 2); // intialise the LCD
  //Interrupt 0 is digital pin 2, so that is where the IR detector is connected
  //Triggers on FALLING (change from HIGH to LOW)
  attachInterrupt(0, rpm_fun, FALLING);
  //Turn on IR LED
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  rpmcount = 0;
  rpm = 0;
  timeold = 0;
}

void loop() {
  //Update RPM every second
  delay(1000);
  //Don't process interrupts during calculations
  detachInterrupt(0);
  //Note that this would be 60*1000/(millis() - timeold)*rpmcount if the interrupt
  //happened once per revolution instead of twice. Other multiples could be used
  //for multi-bladed propellers or fans
  rpm = 30*1000/(millis() - timeold)*rpmcount;
  timeold = millis();
  rpmcount = 0;
  //Print out result to LCD
  lcd.clear();
  lcd.print("RPM=");
  lcd.print(rpm);
  //Restart the interrupt processing
  attachInterrupt(0, rpm_fun, FALLING);
}

```

Can anyone help me to fix the project? Has anyone here tried this project before?

Thank you!

# Answer
> 1 votes
First, make sure that your LCD routines and wiring are working, by trying to display something on it.

Second, the code isn't correct - it will have some fluctuations from one measurement to another.

One way to do it is to start timing only after the first pulse has arrived, and stop timing only after the last pulse has passed.

Something like this:

* Wait until a falling edge.
* Time0 is millis().
* Wait for N pulses to pass.
* Time0 is millis() minus time0.

Now with time0 and N you can calculate your rpm.

*Edit:*

Here is the above code at work, running Arduino on a PIC24.

The input signal is 10Hz, 1 pulse per revolution, aka 600 rpm.

As you can see the rpm read-out is precisely 600rpm. I'm running the code at 8x oversampling.

As I indicated earlier, your code will introduce uncertainty, as much as one period for the pulses. So in a single pulse measurement, the rpm can be anywhere from 0.5x of the true value to 1.0x of the true value.

---
Tags: programming, motor, lcd, interrupt, arduino-leonardo
---


# Question
Title: How to create a simple TCP server with the analogRead value on Wemos D1 mini?
I want to create a TCP server on the Wemos that serves the analogRead value of the connected potentiometer.

The code below is based on this example. The Wemos connects to the Wi-Fi and i'm able to ping it, but the problem is that I **can't connect to the server**. Also I don't really understand why the length of the data has to be passed with the data (`serverClients[i].write(sbuf, len);`). Why can't the library figure that out?

```
#include <ESP8266WiFi.h>

//how many clients should be able to telnet to this ESP8266
#define MAX_SRV_CLIENTS 2
const char* ssid = "myWifi";
const char* password = "myPassword";

WiFiServer server(23);
WiFiClient serverClients[MAX_SRV_CLIENTS];

unsigned long previousMillis = 0;
const long interval = 200;
void setup() {
  Serial.begin(115200);
  Serial.print("\nConnecting to "); Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500);
  if (i == 21) {
    Serial.print("Could not connect to"); Serial.println(ssid);
    while (1) delay(500);
  }
  server.setNoDelay(true);
  Serial.print(WiFi.localIP());
}

void loop() {
  unsigned long currentMillis = millis();
  uint8_t i;
  //check if there are any new clients
  if (server.hasClient()) {
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      //find free/disconnected spot
      if (!serverClients[i] || !serverClients[i].connected()) {
        if (serverClients[i]) serverClients[i].stop();
        serverClients[i] = server.available();
        continue;
      }
    }
    //no free/disconnected spot so reject
    WiFiClient serverClient = server.available();
    serverClient.stop();
  }

  //do every 200ms
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    int isensorValue = analogRead(A0); //analog read
    String sSensorValue = String(isensorValue); //int to string
    size_t len = sSensorValue.length();
    uint8_t sbuf[len];
    sSensorValue.getBytes(sbuf, len);
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i] && serverClients[i].connected()) {
        serverClients[i].write(sbuf, len);
        delay(1);
      }
    }

  }
}

```

# Answer
> 3 votes
So the problem was that I forgot the following line. Thanks to @Johnny Mopp for pointing this out.

```
server.begin()

```

**Correct code:**

```
#include <ESP8266WiFi.h>

//how many clients should be able to telnet to this ESP8266
#define MAX_SRV_CLIENTS 2
const char* ssid = "myWifi";
const char* password = "myPassword";

WiFiServer server(23);
WiFiClient serverClients[MAX_SRV_CLIENTS];

unsigned long previousMillis = 0;
const long interval = 200;
void setup() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  uint8_t i = 0;
  while (WiFi.status() != WL_CONNECTED && i++ < 20) delay(500);
  if (i == 21) {
    Serial.print("Could not connect to"); Serial.println(ssid);
    while (1) delay(500);
  }
  server.begin();
  server.setNoDelay(true);
}

void loop() {
  unsigned long currentMillis = millis();
  uint8_t i;
  //check if there are any new clients
  if (server.hasClient()) {
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      //find free/disconnected spot
      if (!serverClients[i] || !serverClients[i].connected()) {
        if (serverClients[i]) serverClients[i].stop();
        serverClients[i] = server.available();
        continue;
      }
    }
    //no free/disconnected spot so reject
    WiFiClient serverClient = server.available();
    serverClient.stop();
  }

  //do every 200ms
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    int isensorValue = analogRead(A0);
    String sSensorValue = String(isensorValue) + "\n\r";
    size_t len = sSensorValue.length();
    uint8_t sbuf[len];
    sSensorValue.getBytes(sbuf, len);
    for (i = 0; i < MAX_SRV_CLIENTS; i++) {
      if (serverClients[i] && serverClients[i].connected()) {
        serverClients[i].write(sbuf, len);
        delay(1);
      }
    }

  }
}

```

---
Tags: esp8266
---


title: How to calibrate a load cell?

text:
# Question
Title: How to calibrate a load cell?
I'm working with a load cell and HX711. There was no weight on the sensor but I kept getting strange values, I thought it was broken or something so I used my second load cell but the same thing happened again. I'm wondering what is wrong with it ? If anyone have worked with it or have an idea how to work with it, please don't hesitate to give your opinions.

```
 #include "HX711.h"
#include <Wire.h>

#define DOUT  A0
#define CLK   A1

#define DEC_POINT  2
#define STABLE  1

float offset=0;
float calibration_factor = 1;
//float real_weight = 1.560;//kg
float real_weight = 0.5;//kg

HX711 scale(DOUT, CLK);

unsigned char state=0;
long  FindZeroFactor();
float get_units_kg();
void  ReadWeight();
void  FindCalibrationFactor();

void setup()
{
  Serial.begin(115200);
  Serial.println();
  Serial.println("Auto Calibrate Program");
  Serial.println("Send 'a' to Find Zero Factor (Please Remove all weight from scale)");
  Serial.println("Send 'b' to Find Calibration Factor (Please insert know the weight on the scales)");
  Serial.println("Send 'c' Show weight on the scales");
}
void loop()
{
  if(Serial.available())
  {
    char temp = Serial.read();
    if(temp=='a')
      state=1;
    if(temp=='b')
      state=2;
    if(temp=='c')
      state=3;
  }

  switch(state)
  {
    case 0:
    break;
    case 1:
      FindZeroFactor();
   //   ReadWeight();
      state=0;
    break;
    case 2:
     FindCalibrationFactor();
     state=0;
    break;
    case 3:
      ReadWeight();
      delay(200);
    break;
    case 4:

    break;

  }
}

long FindZeroFactor()
{
     Serial.println("Find Zero Factor");
     Serial.println("Please wait .....");
     scale.set_scale();
     scale.tare();
     long zero_factor = scale.read_average(20);
     Serial.print("Zero factor: ");
     Serial.println(zero_factor);
     return(zero_factor);
}

void FindCalibrationFactor()
{
  unsigned char flag_stable=0;
  unsigned int decpoint=1;
  for(unsigned char i=0;i<DEC_POINT+1;i++ )
    decpoint = decpoint*10;
  while(1)
  {
      scale.set_scale(calibration_factor); //Adjust to this calibration factor
      Serial.print("Reading: ");
      float read_weight = get_units_kg();
      String data = String(read_weight, DEC_POINT);
      Serial.print(data);
      Serial.print(" kg");
      Serial.print(" calibration_factor: ");
      Serial.print(calibration_factor);
      Serial.println();
      long r_weight      = (real_weight*decpoint);
      long int_read_weight = read_weight*decpoint;
      Serial.print(r_weight);
      Serial.print(" , ");
      Serial.println(int_read_weight);
      long x;
      if(r_weight == int_read_weight)
      {
        flag_stable++;
        if(flag_stable>=STABLE)
        {
          Serial.print("Calibration Factor is = ");
          Serial.println(calibration_factor);
          break;
         }
        }
       if(r_weight > int_read_weight)
          {
            x = r_weight - int_read_weight;
            if(x > 100)
              calibration_factor -= 1000;
            else if(x > 100)
              calibration_factor -= 10;
            else
              calibration_factor -= 1;
            flag_stable=0;
          }
          if(r_weight < int_read_weight)
          {
            x =  int_read_weight-r_weight;
            if(x > 100)
              calibration_factor += 1000;
            else if(x > 10)
              calibration_factor += 10;
            else
              calibration_factor += 1;
            flag_stable=0;
           }
  }
}

float get_units_kg()
{
  return(scale.get_units()*0.453592);
}
void ReadWeight()
{
  scale.set_scale(calibration_factor); //Adjust to this calibration factor
  Serial.print("Reading: ");
  String data = String(get_units_kg()+offset, DEC_POINT);
  Serial.print(data);
  Serial.println(" kg");
}

```

# Answer
The first thing that about Load Cells that always comes to my mind is the circuit which amplifies the load cell's signal, Usually the load cell signal changes in a low mv range, so you have to put a high gain circuit in the way of the signal, which amplifies signal and NOISE. You have to use an instrumentation amplifier for this purpose, otherwise, your signal would become so noisy.

And try to implement a low pass digital filter too, it should compensate the fluctuations and would give you smoother signal.
> 1 votes

# Answer
```
scale.set_scale(calibration_factor);

```

needs to be changed to :

```
scale.set_scale(calibration_factor/[the reference weight you have used]);

```
> 0 votes

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


title: Visual Studio integration with Arduino

text:
# Question
Title: Visual Studio integration with Arduino
I use Visual Studio 2015 extensively for work, so it would seem like a logical choice for getting started with Arduino programming (though my C/C++ is rusty, that may take some time to get back). From what I understand the Visual Micro Plugin is popular. Is that sort of the de facto choice for those who come from VS? Does it tie into everything so that I can handle debugging, breakpoints, deployment etc from Visual Studio? Much obliged!

# Answer
I think it is the *de facto* standard for VS (of course the default Arduino IDE is used most).

However, I think some advanced features (like breakpoint if I recall right) is only temporarily for free and you have to pay later for a subscription.

Note however, that debugging/breakpoints are not used often anyway since mostly it's more realtime controlled than PC applications.

If you need breakpoints etc. probably the easiest is to make stubs for some libraries and first develop the application not using Arduino and later use the Visual Micro plugin. \[Update: it seems breakpoints are possible with vMirco, I never got them to work though\].
> 1 votes

# Answer
Use Atmel's Atmel Studio 7. Uses the visual studio shell and is supported by Atmel. Also allows you to import your Arduino Sketches. Once I used it, I stopped using the Arduino IDE.
> 0 votes

---
Tags: ide, visualstudio
---


# Question
Title: Read Audio Data in Real-time over 3.5mm Stereo Cable
# My Goal

Have Arduino read audio output from a TRS stereo audio cable (coming from a computer, smartphone, etc.). *As motivation for this use-case*, once some audio data (depending on the sample rate) have been stored in a buffer, the Arduino will perform an FFT on the buffered data. The power contained in the FFT is mapped to the red, green, and blue frequency-bands of visible light to determine the color of an LED strip.

# My Set-up

The obvious first step was to connect a Right-Angle 3.5mm Stereo Plug to Pigtail Cable to the Arduino. As is commonplace, this cable has a **T**ip, **R**ing, and **S**leeve connector; Adafruit labels the black wire as ground (sleeve). They further label the red wire as "left channel live" (tip) and the white wire as "right channel live" (ring), if I can trust Wikipedia:

> Stereo sockets commonly provide two such NC contacts, one for the **tip (left channel live)** and one for the **ring or collar (right channel live)**.

# My Question

So, I've plugged the red wire into the `A0` pin and the white wire into the `A1` pin. However, I'm unsure of how to sample the actual audio signal from these analog pins.

I don't believe the `analogRead()` function solves the whole problem - it only converts a voltage reading at the pin into a value between 0 and 1023. Presumably, if I knew the bit rate (i.e., sample rate) & of each packet in the transmitted audio signal, I'd be able to construct signal from that. **Is it possible to extract the original audio's waveform from a simple voltage signal?** If not, what approach would enable the Arduino to read audio data from an audio cable?

*Note:* For those wondering, I have indeed heeded the advice from this Electronics SE answer to attach a DC-blocking/DC-bias circuit to the signal source before driving it into an analog pin on the Arduino.

# Answer
**The middle path**

Build the simple op-amp (or whatever) 70s-era color organ, but without all the LEDs. Then basically feed the organ's LED-driving lines into the Arduino's ADCs. Sampling that pre-processed/summarized data, you can define a wide variety of RGB interactions without complicated math or an EE background. The timing requirements will be well-within the Arduino's reach, unlike computing FFTs or other "difficult" processes. Besides, old/new hybrids are cool!
> 1 votes

# Answer
Simply, YES: it is possible to reconstruct the waveform from the sampled signal. There are entire 400 level college courses on this subject, in fact, but it is rather simple to implement. However, you should study the FFT algorithm you plan to use a little more closely, as it actually requires a discreet time (sampled) input.

Some background: The audio signal you are getting from the TRS cable is continuous, but was recreated from discreet samples (unless your using a tape deck) by using reconstruction theory. The basic idea is this: you take a continuous train of discreet values (the sample points of the sound you want to make), then you multiply each one by a sinusoidal rectangle function (called a sinc, if you want to look it up), which basically takes your discrete values and makes them analog. The frequencies of the sampled signal will probably be 44.1 or 96kHz, although the signal you actually get is analog.

Now, the FFT! The FFT itself is a discrete time function, meaning that it is designed to use sampled data (for instance, of vector of values read from `analogread()` once every T seconds, where T=1/f, f being your sampling frequency). I should warn you, unless you're planning on using a library someone else already made, the FFT is a complicated beast! It's not impossible to use--in fact once you understand it, it's really quite beautiful--just be aware there is a lot of circle-based math and opaque optimization.

So, again in short, yes, **you can reconstruct a signal from its sample, but you don't need to!**

Note: there may be more information on what you're trying to do on the Signal processing SE as well.

Hope that helps!

**EDIT ADDITION:**

In response to the comments, I very much agree that most lower level arduinos (assuming uno or similar) is not the ideal chip. *However*, there is a way around your sampling problem. Whether your processor can handle the higher sampling rate is questionable, but we'll address that momentarily.

Q: How to get a higher sample rate out a 10kHz max ADC. A: Double up. Or triple up, or quadrupile up, etc. The basic idea is, if you have one ADC reading channel 1 of a signal nT seconds (T being period = 1/10kHz and n being a discrete set of integers = 0,1,2,3...), then you can have a second ADC reading the signal every nT+(T/2) seconds. Then, you populate your data vector as DATA=\[ADC1(0\*T),ADC2(0\*T+T/2),ADC1(1\*T),ADC2(1\*T+T/2),...\] and so on. This **effectively doubles your sampling rate**. If you want to sample at ~40Hz, you use 4 ADC channels. The real question is how high do you need to go. By Nyqist's Theorem, you need a sampling freequency \>= to twice of the highest frequency you expect to be present in your signal. In most recorded sounds this never above 18kHz. So, you do this with 4 ADC channels offset from each other by a quarter period, and you have a high enough sample rate.

Q: What if I can't process the data with an FFT that fast? A: Never fear! Discrete time filters and power integration are here! (okay, that was a bit corny). A much less processor intensive method of frequency band power estimation would be to implement band-pass filters in your software (which can work with *very little* overhead processor-wise) and then average the power output of each filter.

Again, hope this addition helps! But as another commenter pointed out, what you want to due may be much easier with a different chip. And as I will point out, moving the filtering and power integration to external op-amp circuits would be an equally simpler option, eliminating the entire sampling problem!
> -1 votes

---
Tags: analogread, audio, frequency
---


# Question
Title: Understanding the relationship of Pulse and Stepper RPM
This may be a better question for the Physics StackExchange so tell me if I should move the question.

I have a pretty simple script that I'm using to control the RPM of my stepper motor:

```
void loop(){
  digitalWrite(PIN, HIGH);
  delayMicroseconds(wait);
  digitalWrite(PIN, LOW);
}

```

as you can see it's just producing a pretty standard pulse, I have my Arduino connected to a driver that manages the motor. The `wait` variable comes from a second order equation I derived from measuring the RPM with a Tachometer and tweaking the value.

```
// From data RPM = 31729/x + 17.327 thus x = 31729/(RPM-17.527)
wait = M/(RPM-C);

```

It works pretty well, I get readings consistently within only 1 - 2 rotations off. But the slope and intercept seem completely arbitrary to me. Is there a chance it has to do with the clock speed of the Arduino? I'm using an Uno and from playing around with the numbers I can't seem to find a relationship. From what I can tell, the driver looks hardwired so I don't think it has much to do with the equation.

Any idea what these values, the slope/intercept mean?

Equation: `RPM=31729/wait + 17.327` M:`31729` and C:`17.327`

# Answer
The real answer to this question requires understanding exactly what hardware you have. The formula, assuming one step per pulse, is that the delay should be:

wait = (MicroSecondsPerMinute)*(1/RPM)*(1/PulsesPerRevolution) - overhead

where overhead is the extra time it takes to run digitalWrite twice and loop. It is small, but if it were zero your code would not work because the amount of time your signal is LOW would be zero as well.

Your numbers suggest Pulses Per Revolution is around 1891. This will be the product of how many steps per revolution the motor is wired for and how many bits of microstepping the driver is doing. A 225 step motor with 3 bit microstepping (8 fractional steps per "true" step) would have PPR of 1800 for example. Your number does not precisely match any common setups, but is exactly in the range expected, with 1600 and 2000 being normal for small steppers.

Because of the "overhead" term, RPM as a function of wait should not be linear. Your constant value should be a function of RPM; in fact, when RPM gets much larger than the number of Microseconds per minute it should converge to being equal to RPM. In this case your RPM is so low that approximating it to 17 is probably valid and all error too small to notice. It could be causing some of the oddness of your PPR value though.
> 2 votes

# Answer
one pulse equals one step of stepper and rpm is how many rotation stepper makes in one minute. Try to understand the stepper.h library and Accelstepper library
> 0 votes

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


title: Serial data affected by interrupt

text:
# Question
Title: Serial data affected by interrupt
In my recent project, I have done everything means capture serial data and split it out in proper form.

Until now everything is fine. But when I add another portion of code which contains Interrupt. Now, whenever Interrupt come into the picture, my incoming serial data totally destroy. And when I remove that interrupt portion then everything is fine. But this interrupt is also given one my reading(RPM READING).

I tried out `detachinterrupt` function, it disables my interrupt then I can't get my RPM READING.

I also tried out `interrupts()` and `noInterrupts()` function. But I don't get any results. I think I'm not able to utilize my code with this function.

Here, below my whole code which is a little bit lengthy. But, it's necessary.

```
#include<LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String data_TPS_Json = "";
String data_MAP_Json = "";
String data_LOAD_TM_Json = "";

String data_LOAD_RI_Json = "";
String data_RPM_Json = "";
String data_INJECTION_TIME_Json = "";

String response = "";
bool begin = false;

char in;
int len = 0;

float TPS_Json;
float MAP_Json;
float LOAD_TM_Json;

float LOAD_RI_Json;
float RPM_Json;
float INJECTION_TIME_Json;

//----------------------------For MAP calculation----------------------------//
float MAP_MIN = 0.85;
float MAP_MAX = 1.90;

int LOAD_MIN_MAP[] = {1, 2};
int LOAD_MAX_MAP[] = {3, 4};

float mMAP[2] = {};
float yMAP[2] = {};

int i, j, a;
float MAP, mFinalMAP, yFinalMAP;

//----------------------------For TPS calculation----------------------------//
float TPS_MIN = 0.00;
float TPS_MAX = 5.00;

int LOAD_MIN_TPS[] = {1, 3};
int LOAD_MAX_TPS[] = {2, 4};

float mTPS[2] = {};
float yTPS[2] = {};

int k, l, b;
float TPS, mFinalTPS, yFinalTPS;

//----------------------------For LOAD calculation---------------------------//
int LOAD_MIN = 2;
int LOAD_MAX = 100;

float injTime_MIN_LOAD[] = {6.20, 6.26};
float injTime_MAX_LOAD[] = {7.80, 8.06};

float mLOAD[2] = {};
float yLOAD[2] = {};

int m, n, c;
float LOAD, mFinalLOAD, yFinalLOAD;

//----------------------------For RPM calculation----------------------------//
const int kPinRPM = 3;        // RPM / Digital Pin 3
const int RPMInterrupt = 1;   // RPM's interrrupt pin
byte engineCylinders = 2;         // Engine cylinders = 4;
byte engineCycles = 4;            // Engine cycle = 2
int refreshInterval = 750;        // Milliseconds between sensor updates
unsigned long previousMillis = 0;
volatile int RPMpulses = 0,  RPM0 = 0;
int RPM, Final_RPM;

int RPM_MIN = 400;
int RPM_MAX = 6000;

float injTime_MIN_RPM[] = {6.20, 7.80};
float injTime_MAX_RPM[] = {6.26, 8.06};

float mRPM[2] = {};
float yRPM[2] = {};

int o, p, d;
float mFinalRPM, yFinalRPM;

//------------------------For GAS PRESSURE calculation-----------------------//
float minPosVolGas = 0.00;
float maxPosVolGas = 2.50;

float minInjPerPos = 0.35;
float maxInjPerPos = 0.00;

float minNagVolGas = 2.50;
float maxNagVolGas = 5.00;

float minInjPerNag = 0.00;
float maxInjPerNag = 0.25;

float GAS_Pressure, mGasPos, mGasNag, yGasPos, yGasNag;

//----------------------For INJECTION TIME calculation-----------------------//
float yInjTime, injTime, gasInjTime;
volatile uint32_t kInjTime = 0;

const int kPinInj = 8;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);

  pinMode(kPinRPM, INPUT_PULLUP); // Enable internal pullup
  attachInterrupt(RPMInterrupt, countRPM, FALLING); //Interrupt for RPM

  pinMode(kPinInj, OUTPUT);
}

void loop()
{
  //----------------------------MAP----------------------------//

  MAP = analogRead(A0) * (5.0 / 1023.0);

  for(a = 0; a < 2; a++)
  {
    mMAP[i] = (LOAD_MIN_MAP[a] - LOAD_MIN_MAP[a]) / (MAP_MAX - MAP_MIN);
    yMAP[j] = mMAP[i] * (MAP - MAP_MIN) + LOAD_MIN_MAP[a];
  }

  //----------------------------TPS----------------------------//

  TPS = analogRead(A1) * (5.0 / 1023.0);

  for(b = 0; b < 2; b++)
  {
    mTPS[k] = (LOAD_MAX_TPS[b] - LOAD_MIN_TPS[b]) / (TPS_MAX - TPS_MIN);
    yTPS[l] = mTPS[k] * (TPS - TPS_MIN) + LOAD_MIN_TPS[b];
  }

  //----------------TPS/MAP CALLIBRATION / LOAD----------------//

  mFinalTPS = (yMAP[1] - yMAP[0]) / (TPS_MAX - TPS_MIN);
  yFinalTPS = mFinalTPS * (TPS - TPS_MIN) + yMAP[0];

  mFinalMAP = (yTPS[1] - yTPS[0]) / (MAP_MAX - MAP_MIN);
  yFinalMAP = mFinalMAP * (MAP - MAP_MIN) + yTPS[0];

  LOAD = (yFinalTPS + yFinalMAP) / 2;

  //----------------------------LOAD---------------------------//

  for(c = 0; c < 2; c++)
  {
    mLOAD[m] = (injTime_MAX_LOAD[c] - injTime_MIN_LOAD[c]) / (LOAD_MAX - LOAD_MIN);
    yLOAD[n] = mLOAD[m] * (LOAD - LOAD_MIN) + injTime_MIN_LOAD[c];
  }

  //----------------------------RPM----------------------------//

  if(millis() - previousMillis > refreshInterval)
  {
    previousMillis = millis();
    RPM =  getRPM();
  }

  for(d = 0; d < 2; d++)
  {
    mRPM[o] = (injTime_MAX_RPM[d] - injTime_MIN_RPM[d]) / (RPM_MAX - RPM_MIN);
    yRPM[p] = mRPM[o] * (RPM - RPM_MIN) + injTime_MIN_RPM[d];
  }

  //-----------LOAD/RPM CALLIBRATION / INJECTION TIME----------//

  mFinalLOAD = (yRPM[1] - yRPM[0]) / (LOAD_MAX - LOAD_MIN);
  yFinalLOAD = mFinalLOAD * (LOAD - LOAD_MIN) + yRPM[0];

  mFinalRPM = (yLOAD[1] - yLOAD[0]) / (RPM_MAX - RPM_MIN);
  yFinalRPM = mFinalRPM * (RPM - RPM_MIN) + yLOAD[0];

  yInjTime = (yFinalLOAD + yFinalRPM) / 2;
  injTime = (yInjTime * 1000) / 1000;

  //------------------JSON SERIAL DATA---------------------//

  while(Serial.available() || !begin)
  {
      in = Serial.read();

      if (in == '{')
      {
        begin = true;
      }

      if(begin)
      {
        response += (in);
      }

      if(in == '}')
      {
        break;
      }

      delay(1);
  }

  len = response.length();

  if(len == 39)
  {
    data_TPS_Json = response.substring(8, 12);
    data_MAP_Json = response.substring(21, 25);
    data_LOAD_TM_Json = response.substring(35, 37);

    jsonMapTps();
  }

  if(len == 52)
  {
    data_LOAD_RI_Json = response.substring(9, 13);
    data_RPM_Json = response.substring(22, 26);
    data_INJECTION_TIME_Json = response.substring(46, 50);

    jsonRpmLoad();
  }

  //------------------------GAS_PRESSURE-----------------------//

  GAS_Pressure =  analogRead(A2) * (5.0 / 1023.0);

  mGasPos = (maxInjPerPos - minInjPerPos) / (maxPosVolGas - minPosVolGas);
  yGasPos = mGasPos * (GAS_Pressure - minPosVolGas) + minInjPerPos;

  mGasNag = (maxInjPerNag - minInjPerNag) / (maxNagVolGas - minNagVolGas);
  yGasNag = mGasNag * (GAS_Pressure - minNagVolGas) + minInjPerNag;

  if(GAS_Pressure >= 0.00 && GAS_Pressure < 2.50)
  {
    gasInjTime = injTime + (injTime * yGasPos);
  }
  else if(GAS_Pressure >= 2.50 && GAS_Pressure <= 5.00)
  {
    gasInjTime = injTime - (injTime * yGasNag);
  }

  //--------------------Pulse Generation-----------------------//

  if((kInjTime > 0) && ((millis() - kInjTime) >= injTime))
  {
    kInjTime = 0;
    digitalWrite(kPinInj, 0);
  }
}

void countRPM()
{
  RPMpulses++;

  digitalWrite(kPinInj, RPMpulses & 1); // Set or clear kPinInj
  if(RPMpulses & 1)
  kInjTime = millis();  // Store alternate times
}

int getRPM()
{
  Final_RPM = ((RPMpulses * (60000UL / 2) * (engineCycles/engineCylinders)) / refreshInterval);
  RPM0 = RPMpulses &= 1;
  RPMpulses - RPM0;
  return Final_RPM;
}

void jsonMapTps()
{
    TPS_Json = data_TPS_Json.toFloat();
    MAP_Json = data_MAP_Json.toFloat();
    LOAD_TM_Json = data_LOAD_TM_Json.toFloat();

    lcd.setCursor(0, 0);
    lcd.print(TPS_Json);
    lcd.setCursor(8, 0);
    lcd.print(MAP_Json);
    lcd.setCursor(0, 1);
    lcd.print(LOAD_TM_Json);
}

void jsonRpmLoad()
{
    LOAD_RI_Json = data_LOAD_RI_Json.toFloat();
    RPM_Json = data_RPM_Json.toFloat();
    INJECTION_TIME_Json = data_INJECTION_TIME_Json.toFloat();

    lcd.setCursor(0, 0);
    lcd.print(LOAD_RI_Json);
    lcd.setCursor(8, 0);
    lcd.print(RPM_Json);
    lcd.setCursor(0, 1);
    lcd.print(INJECTION_TIME_Json);
}

```

# Answer
Finally got the solution. My method of capturing Serial string data is a little bit faulty. And also remove maximum strings and try to declare maximum local variables And use `ArduinoJson` library for parsing the data.

This is my modified code:

```
#include<LiquidCrystal.h>
#include <ArduinoJson.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String response = "";
bool begin = false, finished;

//----------------------------For MAP calculation----------------------------//
float MAP_MIN = 0.85;
float MAP_MAX = 1.90;

int LOAD_MIN_MAP[] = {1, 2};
int LOAD_MAX_MAP[] = {3, 4};

float mMAP[2] = {};
float yMAP[2] = {};

int i, j, a;
float MAP, mFinalMAP, yFinalMAP;

//----------------------------For TPS calculation----------------------------//
float TPS_MIN = 0.00;
float TPS_MAX = 5.00;

int LOAD_MIN_TPS[] = {1, 3};
int LOAD_MAX_TPS[] = {2, 4};

float mTPS[2] = {};
float yTPS[2] = {};

int k, l, b;
float TPS, mFinalTPS, yFinalTPS;

//----------------------------For LOAD calculation---------------------------//
int LOAD_MIN = 2;
int LOAD_MAX = 100;

float injTime_MIN_LOAD[] = {6.20, 6.26};
float injTime_MAX_LOAD[] = {7.80, 8.06};

float mLOAD[2] = {};
float yLOAD[2] = {};

int m, n, c;
float LOAD, mFinalLOAD, yFinalLOAD;

//----------------------------For RPM calculation----------------------------//
const int kPinRPM = 3;        // RPM / Digital Pin 3
const int RPMInterrupt = 1;   // RPM's interrrupt pin
byte engineCylinders = 2;         // Engine cylinders = 4;
byte engineCycles = 4;            // Engine cycle = 2
int refreshInterval = 750;        // Milliseconds between sensor updates
unsigned long previousMillis = 0;
volatile int RPMpulses = 0,  RPM0 = 0;
int RPM, Final_RPM;

int RPM_MIN = 400;
int RPM_MAX = 6000;

float injTime_MIN_RPM[] = {6.20, 7.80};
float injTime_MAX_RPM[] = {6.26, 8.06};

float mRPM[2] = {};
float yRPM[2] = {};

int o, p, d;
float mFinalRPM, yFinalRPM;

//------------------------For GAS PRESSURE calculation-----------------------//
float minPosVolGas = 0.00;
float maxPosVolGas = 2.50;

float minInjPerPos = 0.35;
float maxInjPerPos = 0.00;

float minNagVolGas = 2.50;
float maxNagVolGas = 5.00;

float minInjPerNag = 0.00;
float maxInjPerNag = 0.25;

float GAS_Pressure, mGasPos, mGasNag, yGasPos, yGasNag;

//----------------------For INJECTION TIME calculation-----------------------//
float yInjTime, injTime, gasInjTime;
volatile uint32_t kInjTime = 0;

const int kPinInj = 8;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);

  pinMode(kPinRPM, INPUT_PULLUP); // Enable internal pullup
  attachInterrupt(RPMInterrupt, countRPM, FALLING); //Interrupt for RPM

  pinMode(kPinInj, OUTPUT);
}

void loop()
{
  //----------------------------MAP----------------------------//

  MAP = analogRead(A0) * (5.0 / 1023.0);

  for(a = 0; a < 2; a++)
  {
    mMAP[i] = (LOAD_MIN_MAP[a] - LOAD_MIN_MAP[a]) / (MAP_MAX - MAP_MIN);
    yMAP[j] = mMAP[i] * (MAP - MAP_MIN) + LOAD_MIN_MAP[a];
  }

  //----------------------------TPS----------------------------//

  TPS = analogRead(A1) * (5.0 / 1023.0);

  for(b = 0; b < 2; b++)
  {
    mTPS[k] = (LOAD_MAX_TPS[b] - LOAD_MIN_TPS[b]) / (TPS_MAX - TPS_MIN);
    yTPS[l] = mTPS[k] * (TPS - TPS_MIN) + LOAD_MIN_TPS[b];
  }

  //----------------TPS/MAP CALLIBRATION / LOAD----------------//

  mFinalTPS = (yMAP[1] - yMAP[0]) / (TPS_MAX - TPS_MIN);
  yFinalTPS = mFinalTPS * (TPS - TPS_MIN) + yMAP[0];

  mFinalMAP = (yTPS[1] - yTPS[0]) / (MAP_MAX - MAP_MIN);
  yFinalMAP = mFinalMAP * (MAP - MAP_MIN) + yTPS[0];

  LOAD = (yFinalTPS + yFinalMAP) / 2;

  //----------------------------LOAD---------------------------//

  for(c = 0; c < 2; c++)
  {
    mLOAD[m] = (injTime_MAX_LOAD[c] - injTime_MIN_LOAD[c]) / (LOAD_MAX - LOAD_MIN);
    yLOAD[n] = mLOAD[m] * (LOAD - LOAD_MIN) + injTime_MIN_LOAD[c];
  }

  //----------------------------RPM----------------------------//

  if(millis() - previousMillis > refreshInterval)
  {
    previousMillis = millis();
    RPM =  getRPM();
  }

  for(d = 0; d < 2; d++)
  {
    mRPM[o] = (injTime_MAX_RPM[d] - injTime_MIN_RPM[d]) / (RPM_MAX - RPM_MIN);
    yRPM[p] = mRPM[o] * (RPM - RPM_MIN) + injTime_MIN_RPM[d];
  }

  //-----------LOAD/RPM CALLIBRATION / INJECTION TIME----------//

  mFinalLOAD = (yRPM[1] - yRPM[0]) / (LOAD_MAX - LOAD_MIN);
  yFinalLOAD = mFinalLOAD * (LOAD - LOAD_MIN) + yRPM[0];

  mFinalRPM = (yLOAD[1] - yLOAD[0]) / (RPM_MAX - RPM_MIN);
  yFinalRPM = mFinalRPM * (RPM - RPM_MIN) + yLOAD[0];

  yInjTime = (yFinalLOAD + yFinalRPM) / 2;
  injTime = (yInjTime * 1000) / 1000;

  //------------------JSON SERIAL DATA---------------------//

  StaticJsonBuffer<100> jsonBuffer;

  while (finished == false)
  {
    if (Serial.available())
    {
      const char in = Serial.read();
      if (in == '{')
      {
        response = "";  // Blank the string
        begin = true;
      }
      if (begin)
      {
        response += (in); // Only write if within the {}
      }
      if (in == '}')
      {
        begin = false;   // Prevent any chars between } and { leaking through.
        break;
      }
    }
    delay(1);
  }

  JsonObject& root = jsonBuffer.parseObject(response);

  const char* ActionOne = root["ActionOne"];
  const char* ActionTwo = root["ActionTwo"];

  //--------------------TPS/MAP/LOAD-----------------------//

  if(root.containsKey("ActionOne"))
  {
    float TPS = root["TPS"];
    float MAP = root["MAP"];
    int LOAD = root["LOAD"];

    lcd.setCursor(0, 0);
    lcd.print(TPS);

    lcd.setCursor(8, 0);
    lcd.print(MAP);

    lcd.setCursor(0, 1);
    lcd.print(LOAD);
  }

 //--------------LOAD/RPM/INJECTION_TIME-------------------//

  if(root.containsKey("ActionTwo"))
  {
    float LOAD = root["LOAD"];
    int RPM = root["RPM"];
    float INJECTION_TIME = root["INJECTION_TIME"];

    lcd.setCursor(0, 0);
    lcd.print(LOAD);

    lcd.setCursor(8, 0);
    lcd.print(RPM);

    lcd.setCursor(0, 1);
    lcd.print(INJECTION_TIME);
  }

  //------------------------GAS_PRESSURE-----------------------//

  GAS_Pressure =  analogRead(A2) * (5.0 / 1023.0);

  mGasPos = (maxInjPerPos - minInjPerPos) / (maxPosVolGas - minPosVolGas);
  yGasPos = mGasPos * (GAS_Pressure - minPosVolGas) + minInjPerPos;

  mGasNag = (maxInjPerNag - minInjPerNag) / (maxNagVolGas - minNagVolGas);
  yGasNag = mGasNag * (GAS_Pressure - minNagVolGas) + minInjPerNag;

  if(GAS_Pressure >= 0.00 && GAS_Pressure < 2.50)
  {
    gasInjTime = injTime + (injTime * yGasPos);
  }
  else if(GAS_Pressure >= 2.50 && GAS_Pressure <= 5.00)
  {
    gasInjTime = injTime - (injTime * yGasNag);
  }

  //--------------------Pulse Generation-----------------------//

  if((kInjTime > 0) && ((millis() - kInjTime) >= injTime))
  {
    kInjTime = 0;
    digitalWrite(kPinInj, 0);
  }
}

void countRPM()
{
  RPMpulses++;

  digitalWrite(kPinInj, RPMpulses & 1); // Set or clear kPinInj
  if(RPMpulses & 1)
  kInjTime = millis();  // Store alternate times
}

int getRPM()
{
  Final_RPM = ((RPMpulses * (60000UL / 2) * (engineCycles/engineCylinders)) / refreshInterval);
  RPM0 = RPMpulses &= 1;
  RPMpulses - RPM0;
  return Final_RPM;
}

```

I'm also trying to capture `response` as char array but not able to capture it. Please guide me about that otherwise this one string may not cause any heap fragmentation. I am so glad if someone helps me out for this.
> 0 votes

# Answer
You need to clean up the whole sketch. I will try to mention the most important things first.

For an Arduino Uno, this sketch uses 520 bytes RAM and 1528 bytes are free to use for stack and heap. That seems enough but with heap fragmentation it might be a problem, see: Adafruit about an increasing heap

The `data_...` `String`s are only to display something. They can be replaced with normal strings. You could also make a single buffer of a char array for the "response".

The variables that are used in the interrupt routine **and** also outside the interupt routine should be made volatile.

When the variable `begin` is `false`, you still read data with `Serial.read()`. That can't be right. Could you rewrite that part ?

The variable `kInjTime` is used to store the `millis()` time and also to disable it by setting it to zero. That is not good programming since `millis()` can be zero. It is better to add an extra variable to turn that timing on and off.

The use of `digitalPinToInterrupt()` is advised when using `attachInterrupt()`. That makes it easier to see which pins are used.

The function `digitalWrite()` takes `HIGH` or `LOW`, not `0` or `1` and not a bit of a variable, only `HIGH` or `LOW`.

Try to use more local variables. You have too many variables as global, which makes it hard to read the sketch.
> 1 votes

---
Tags: arduino-uno, interrupt, json, serial-data
---


title: How to get different parsed JSON data?

text:
# Question
Title: How to get different parsed JSON data?
In my recent project, I have to parse incoming JSON data in Arduino and I successfully did it. But it is only for one constant data string.

For example, if my incoming JSON string like:

```
{"TPS":"0.40","MAP":"0.95","LOAD":"14"}

```

And Arduino code for parsing this data is below:

```
#include <LiquidCrystal.h>
#include <ArduinoJson.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String response = "";
bool begin = false;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
  StaticJsonBuffer<100> jsonBuffer;
  while(Serial.available() || !begin) {
    char in = Serial.read();
    if (in == '{') {
      begin = true;
    }
    if(begin) {
      response += (in);
    }
    if(in == '}') {
        break;
    }
    delay(1);
  }
  JsonObject& root = jsonBuffer.parseObject(response);
  String TPS = root["TPS"];
  String MAP = root["MAP"];
  String LOAD = root["LOAD"];
  lcd.setCursor(0, 0);
  lcd.print(TPS);
  lcd.setCursor(8, 0);
  lcd.print(MAP);
  lcd.setCursor(0, 1);
  lcd.print(LOAD);
}

```

Then the output looks like:

```
TPS  : 0.40
MAP  : 0.95
LOAD : 14

```

That's fine, but when the incoming JSON string changes, what should I do?

Suppose the incoming JSON string looks like:

```
{"LOAD":"2.40","RPM":"4200","INJECTION_TIME":"4.87"}

```

Because I have to handle both incoming JSON strings, I can't replace any part like:

```
  String LOAD = root["LOAD"];
  String RPM = root["RPM"];
  String INJECTION_TIME = root["INJECTION_TIME"];
  lcd.setCursor(0, 0);
  lcd.print(LOAD);
  lcd.setCursor(8, 0);
  lcd.print(RPM);
  lcd.setCursor(0, 1);
  lcd.print(INJECTION_TIME);

```

Instead of

```
  String TPS = root["TPS"];
  String MAP = root["MAP"];
  String LOAD = root["LOAD"];
  lcd.setCursor(0, 0);
  lcd.print(TPS);
  lcd.setCursor(8, 0);
  lcd.print(MAP);
  lcd.setCursor(0, 1);
  lcd.print(LOAD);

```

# Answer
Finally got the solution. I'm using the extra key name.

So, my modified serial data string now looks like:

```
{"ActionOne":"ONE","TPS":"0.40","MAP":"0.95","LOAD":"14"}
{"ActionTwo":"TWO","LOAD":"2.40","RPM":"4200","INJECTION_TIME":"4.87"}

```

and so now using `containsKey()` function, just check which one is coming. If `ActionOne` is coming then according to that serial data we got. And If `ActionTwo` is coming then according to that serial data we got.

```
#include <LiquidCrystal.h>
#include <ArduinoJson.h>

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

String response = "";
bool begin = false, finished;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
  StaticJsonBuffer<100> jsonBuffer;

  while (finished == false)
  {
    if (Serial.available())
    {
      const char in = Serial.read();
      if (in == '{')
      {
        response = "";  // Blank the string
        begin = true;
      }
      if (begin)
      {
        response += (in); // Only write if within the {}
      }
      if (in == '}')
      {
        begin = false;   // Prevent any chars between } and { leaking through.
        break;
      }
    }
    delay(1);
  }

  JsonObject& root = jsonBuffer.parseObject(response);

  const char* ActionOne = root["ActionOne"];
  const char* ActionTwo = root["ActionTwo"];

  if(root.containsKey("ActionOne"))
  {
    float TPS = root["TPS"];
    float MAP = root["MAP"];
    int LOAD = root["LOAD"];

    lcd.setCursor(0, 0);
    lcd.print(TPS);

    lcd.setCursor(8, 0);
    lcd.print(MAP);

    lcd.setCursor(0, 1);
    lcd.print(LOAD);
  }

  if(root.containsKey("ActionTwo"))
  {
    float LOAD = root["LOAD"];
    int RPM = root["RPM"];
    float INJECTION_TIME = root["INJECTION_TIME"];

    lcd.setCursor(0, 0);
    lcd.print(LOAD);

    lcd.setCursor(8, 0);
    lcd.print(RPM);

    lcd.setCursor(0, 1);
    lcd.print(INJECTION_TIME);
  }
}

```
> 0 votes

# Answer
If you want to read 3 values of a object that you don't know the names of the key, you can use an iterator as shown in the ArduinoJson library's docs.

And as already mentioned in the comments, you can also replace all the serial reading code with just `Serial` passed into the `jsonBuffer.parseObject` function.

```
#include <LiquidCrystal.h>
#include <ArduinoJson.h>

const struct LCDPos {
  uint8_t x;
  uint8_t y;
} lcd_pos[] = {
  {0, 0},
  {8, 0},
  {0, 1},
};

LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

void setup() {
  Serial.begin(115200);
  lcd.begin(16, 2);
}

void loop() {
  StaticJsonBuffer<100> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(Serial);
  if (root == JsonObject::invalid())
    return;

  uint8_t i = 0;
  for (JsonObject::iterator it = root.begin(); it != root.end() && i<(sizeof(lcd_pos)/sizeof(lcd_pos[0])); ++it, i++)
  {
    lcd.setCursor(lcd_pos[i].x, lcd_pos[i].y);
    lcd.print(it->value.asString());
  }
}

```

You will need to make sure, that the values are sent in the order that you want them on your LCD.

EDIT:
I don't have an LCD screen, so I didn't test the code with an LCD, but the code that just dumps the parsed data back to serial works.

```
//#include <LiquidCrystal.h>
#include <ArduinoJson.h>

const struct LCDPos {
  uint8_t x;
  uint8_t y;
} lcd_pos[] = {
  {0, 0},
  {8, 0},
  {0, 1},
};

//LiquidCrystal lcd(12, 11, 7, 6, 5, 4);

void setup() {
  Serial.begin(115200);
  //lcd.begin(16, 2);
}

void loop() {
  StaticJsonBuffer<100> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(Serial);
  if (root == JsonObject::invalid())
    return;

  Serial.println("JSON received");
  uint8_t i = 0;
  for (JsonObject::iterator it = root.begin(); it != root.end() && i < (sizeof(lcd_pos) / sizeof(lcd_pos[0])); ++it, i++)
  {
    //lcd.setCursor(lcd_pos[i].x, lcd_pos[i].y);
    //lcd.print(it->value.asString());
    Serial.print(i);
    Serial.print(':');
    Serial.print(lcd_pos[i].x);
    Serial.print(',');
    Serial.print(lcd_pos[i].y);
    Serial.print(' ');
    Serial.println(it->value.asString());
  }
  Serial.println();
}

```

If I send

```
{"TPS":"0.40","MAP":"0.95","LOAD":"14"}{"LOAD":"2.40","RPM":"4200","INJECTION_TIME":"4.87"}

```

over the serial, it returns

```
JSON received
0:0,0 0.40
1:8,0 0.95
2:0,1 14

JSON received
0:0,0 2.40
1:8,0 4200
2:0,1 4.87

```
> 1 votes

---
Tags: arduino-uno, node.js, json
---


# Question
Title: The fastest way to read out a digital pin state in an Arduino Due
What is the ***fastest*** way to read a digital pin status in an Arduino Due? Is it possible to achieve speed in the Nanosecond area?

With which type of code I can achieve this?

Edit: This question is not a duplicate please see my comment.

# Answer
If the pin is declared as input, let's say pin 13:

```
uint32_t pin_status;
pin_status = PIOB->PIO_PDSR & PIO_PDSR_P27;

```

If the pin is declared as output, let's say pin 13:

```
uint32_t pin_status;
pin_status = PIOB->PIO_ODSR & PIO_ODSR_P27;

```
> 2 votes

# Answer
Read the In out data register would be the fastest.
> 0 votes

---
Tags: programming, arduino-due, hardware, digital
---


# Question
Title: Why is the T2 transistor used in Arduino Micro?
I was about to design a small custom board using ATmega32U4, replicating the Arduino Micro. I know that T1 is used to block VUSB when VIN is connected.

But why T2? The gate is 5V, so it will be always OFF! Or does it act as a diode?

Schemtic https://www.arduino.cc/en/uploads/Main/arduino-micro-schematic.pdf

# Answer
T1 and T2 implement a power supply ORing of the VUSB and VIN voltages. Read this for extended information.

The body diode of each MOSFET performs the basic ORing function. When the MOSFET is turned OFF it just behaves as a diode. But when the MOSFET is turned ON, the diode is shorted by the conduction channel, thus avoiding its voltage drop (and achieving a behaviour closer to an ideal diode).

So:

1. When VUSB is present and VIN is not connected (but pulled down to ground by R9), T1 turns ON and the +5V rail is connected to VUSB. Also, T2 turns OFF and the regulator input is isolated from VIN and the regulator simply doesn't operate (thus, avoiding a potential conflict because its output +5V is being forced to VUSB).
2. When VUSB is not connected and VIN is present, T1 turns OFF and VUSB is isolated from the +5V rail. Also T2 turns ON and VIN is connected to the regulator input, which then regulates the voltage down into the +5V rail.
3. When both VUSB and VIN are connected, the behaviour is the same as in case 2 above. Because VIN is supposed to be \>7V and VUSB approx 5V, T1 will isolate VUSB and avoid a conflict with the regulator output. Also, a VIN \>7V will allow T2 to turn on hard enough to bypass the body diode and avoid its voltage drop.
> 3 votes

# Answer
It's known as a "zero drop-out diode". When the power is first applied the body diode of the MOSFET conducts and powers the system. That imposes a (roughly) 0.7V drop on the input voltage.

Once the power gets through the regulator and is regulated to 5V that is then fed back into the gate of the MOSFET, which turns it on (as long as -5V is above the source voltage less the diode drop, so -5.7V minimum \[it's a P channel so thresholds etc are negative\]). That then bypasses the internal body diode getting rid of the 0.7V drop.

If the input voltage is too low the 5V gate no longer turns the MOSFET on and the body diode blocks any reverse current.
> 2 votes

---
Tags: power, arduino-micro, mosfet
---


title: Servo FS5106B does not work properly

text:
# Question
Title: Servo FS5106B does not work properly
I was testing out my new Servo FS5106B. Here is the code I used:

```
#include <Servo.h>

Servo servo;
void setup()
{
    servo.attach(10);
}

void loop()
{
    servo.write(0);
    delay(1000);
    servo.write(180);
    delay(1000);
}

```

After I upload the sketch, the console says:

> Sketch uses 2872 bytes (1%) of your device memory. Total available 253952 bytes. Global variables use 161 bytes (1%) of the dynamic memory, leaving 8031 bytes for local variables. Maximum 8192

The delay between the rotations wasn't 1 second (as I was expecting), but 13 seconds (when I connect *only* a LED and use the delay function, everything works perfectly). Why is that happening?

P.S The power source for the servo is my Arduino-Mega 2560, wich outputs 5V. The model I use for wiring is:

*Edit 1*: I tried to execute the program that @ChrisStratton suggested, here an updated code

```
#include <Servo.h>
#define led 22

Servo servo;

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

    Serial.println("Start!");
    pinMode(led, OUTPUT);
    servo.attach(10);
}

void loop()
{
    digitalWrite(led, HIGH);
    servo.write(0);
    delay(1000);
    digitalWrite(led, LOW);
    servo.write(180);
    delay(1000);
}

```

When this program loads, servo does 2 rotations in 0.4 seconds and the LED goes high and low really fast, then anything changes for another 10 seconds, then again the LED goes high and low and the Servo does 2 rotations

# Answer
> 2 votes
In the official Arduino examples, a servo motor is powered by the 5V pin of the Arduino board. In real life, that is a bad idea.
Your FS5106B has specified about 1A stall current. The average current is less than that, but the start peak current could indeed be 1A.
Could you try to use a seperate power supply of 5V (or 6V) for the servo motor ?

To check if the Arduino resets, you could do a `Serial.begin(9600);` in setup, directly followed by `Serial.println("the sketch has started");`

Some servo motors require different timing. That would not explain the 13 seconds delay, so I assume that your servo motor has normal timing.

Do you use a breadboard ? Sending a current peak through a breadboard (with bad contacts) can cause a lot of voltage spikes.

(*To the other problem solvers: I'm ignoring the 13 seconds and assume that once in a while the servo motor is able to start, just a guess, I could be wrong*).

\[ADDED\]
@ChrisStratton is trying to tell you this:

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

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

```

The next step would be:

```
#include <Servo.h>

Servo servo;

void setup()
{
  Serial.begin(9600);
  Serial.println("The sketch has started");
  pinMode( LED_BUILTIN, OUTPUT);
  servo.attach(10);
}

void loop()
{
  servo.write(0);
  digitalWrite( LED_BUILTIN, HIGH);
  delay(1000);

  servo.write(180);
  digitalWrite( LED_BUILTIN, LOW);
  delay(1000);
}

```

\[ADDED2\]
Or even more fun, with a counter (as @ChrisStratton wrote):

```
#include <Servo.h>

Servo servo;

unsigned int counter;

void setup()
{
  Serial.begin(9600);
  Serial.println("The sketch has started");
  pinMode( LED_BUILTIN, OUTPUT);
  servo.attach(10);
}

void loop()
{
  servo.write(0);
  digitalWrite( LED_BUILTIN, HIGH);
  delay(1000);

  servo.write(180);
  digitalWrite( LED_BUILTIN, LOW);
  delay(1000);

  Serial.print("Still alive after ");
  Serial.print(counter);
  Serial.println(" seconds");
  counter += 2;   // two seconds per loop iteration
}

```

---
Tags: arduino-mega, arduino-ide, servo
---


title: Relay to Mains lightswitch

text:
# Question
Title: Relay to Mains lightswitch
So I purchased a 4 channel Relay which handles AC250V 10A ; DC30V 10A. But am I able to connect this to replace a light switch so I can automate it? My bedroom runs on 15 amps.

http://amazon.com/gp/product/B00VHVIBAM?psc=1&redirect=true&ref\_=oh\_aui\_detailpage\_o00\_s00

# Answer
> 2 votes
# All mains electrical work should be performed by a fully qualified electrician.

Yes, this relay board will easily switch a light bulb.

A note on current: A single 100 Watt incandescent globe will only draw 0.83 Amps at 120V AC (0.416 Amps at 240V AC). The equation I used: I=P/V. You would start coming close to the maximum rating after 10 globes (although I advise staying well below the maximum).

You mention that your bedroom runs on 15 Amps, which I assume means that the mains runs through a 15 Amp circuit breaker (or fuse). This circuit breaker will trip if the total current to all devices after it exceeds 15 Amps.

A similar question was asked by Matthieu Napoli over on the Electrical Engineering Stack Exchange site. There are a number of high quality answers there that would be helpful for you. Worthiest to mention is Cybergibbons answer where he recommends using the PowerSwitch Tail as a very safe way of switching mains voltage. You don't need an electrician when using the PowerSwitch Tail providing the light you are controlling has the matching plugs.

---
Tags: relay
---


title: GPS Logger Error

text:
# Question
Title: GPS Logger Error
I have created a GPS logger code using DFRobot SIM808 library. The tcp code and getGPS codes are working fine. but when integrating the both the code, it failed to upload GPS data to thingspeak. It gets the IP connect to the server, but the get command is not working; and also the GPS data shown as a string. Can anyone please tell me where the problem is?

```
/*
### Connect TCP and send GET request.
1. This example is used to test DFRobot_SIM808 GPS/GPRS/GSM Shield's connect TCP and send GET request.
2. Open the SIM808_TCPConnection example or copy these code to your project
3. Download and dial the function switch to Arduino
4. Open serial helper
5. Waiting for a few minutes, until serial has sent "Connect mbed.org success"
6. Serial will send "Hello world!"

create on 2016/09/23, version: 1.0
by jason
*/
#include <DFRobot_sim808.h>
#include <SoftwareSerial.h>

#define PIN_TX    10
#define PIN_RX    11
SoftwareSerial mySerial(PIN_TX,PIN_RX);
DFRobot_SIM808 sim808(&mySerial);//Connect RX,TX,PWR,

//make sure that the baud rate of SIM900 is 9600!
//you can use the AT Command(AT+IPR=9600) to set it through SerialDebug

//DFRobot_SIM808 sim808(&Serial);

char buffer[512];

void setup(){
  mySerial.begin(2400);
  Serial.begin(2400);

  //******** Initialize sim808 module *************
  while(!sim808.init()) {
      delay(1000);
      Serial.print("Sim808 init error\r\n");
  }
  delay(3000);

  //*********** Attempt DHCP *******************
  while(!sim808.join(F("hutch3g"))) {
      Serial.println("Sim808 join network error");
      delay(2000);
  }

  //************ Successful DHCP ****************
  Serial.print("IP Address is ");
  Serial.println(sim808.getIPAddress());

  //************* Turn on the GPS power************
  if( sim808.attachGPS())
      Serial.println("Open the GPS power success");
  else
      Serial.println("Open the GPS power failure");
  delay(2000);
}

void loop(){
//  gps();
  delay(2000);
  tcp();
  delay(2000);
}

void tcp(){
    //*********** Establish a TCP connection ************
  if(!sim808.connect(TCP,"api.thingspeak.com", 80)) {
      Serial.println("Connect error");
  }else{
      Serial.println("Connect mbed.org success");
  }

  //*********** Send a GET request *****************
    float lati=sim808.GPSdata.lat;
    float longi=sim808.GPSdata.lon;

    char http_cmd[100];
    sprintf(http_cmd, "GET https://api.thingspeak.com/update?api_key=FF19NVWMPZEWX0XK&field2=%s&field3=%s HTTP/1.0\r\n\r\n\0", lati, longi);

    boolean retValue = true;
    sim808.send(http_cmd, strlen(http_cmd));
    int ret = sim808.recv(buffer, sizeof(buffer)-1);
    if (ret <= 0){
        Serial.println("error receiving");
        retValue = false;
    }
    buffer[ret] = '\0';
    Serial.print(buffer);

  //************* Close TCP or UDP connections **********
  sim808.close();

  //*** Disconnect wireless connection, Close Moving Scene *******
  sim808.disconnect();
}

//void gps() {
//   //************** Get GPS data *******************
//   if (sim808.getGPS()) {
//    Serial.print(sim808.GPSdata.year);
//    Serial.print("/");
//    Serial.print(sim808.GPSdata.month);
//    Serial.print("/");
//    Serial.print(sim808.GPSdata.day);
//    Serial.print(" ");
//    Serial.print(sim808.GPSdata.hour);
//    Serial.print(":");
//    Serial.print(sim808.GPSdata.minute);
//    Serial.print(":");
//    Serial.print(sim808.GPSdata.second);
//    Serial.print(":");
//    Serial.println(sim808.GPSdata.centisecond);
//    Serial.print("latitude :");
//    Serial.println(sim808.GPSdata.lat, 6);
//    Serial.print("longitude :");
//    Serial.println(sim808.GPSdata.lon, 6);
//    Serial.print("speed_kph :");
//    Serial.println(sim808.GPSdata.speed_kph);
//    Serial.print("heading :");
//    Serial.println(sim808.GPSdata.heading);
//    Serial.println();
//
//    //************* Turn off the GPS power ************
//    sim808.detachGPS();
//  }
//}

```

# Answer
First, I would assume you need to call `sim808.getGPS()` to update the GPS data. Not sure why you commented that out.

Normally, when building a `GET` command, you don't include the url (unless going through a proxy).

Last, you need to use `%f` with `sprintf` to format a floating point value.

Something like this might work:

```
void tcp()
{
    // Update the GPS data
    float lati, longi;
    if (sim808.getGPS()) {
        lati = sim808.GPSdata.lat;
        longi = sim808.GPSdata.lon;
        sim808.detachGPS();
    }
    else {
        // No gps, abort
        return;
    }

    //*********** Establish a TCP connection ************

    if (!sim808.connect(TCP,"api.thingspeak.com", 80)) {
       Serial.println("Connect error");
       return;
    }
    else {
       Serial.println("Connect mbed.org success");
    }

   //*********** Send a GET request *****************

    char http_cmd[100];
    sprintf(http_cmd, "GET /update?api_key=FF19NVWMPZEWX0XK&field2=%f&field3=%f HTTP/1.0\r\n\r\n\0", lati, longi);
    sim808.send(http_cmd, strlen(http_cmd));
    int ret = sim808.recv(buffer, sizeof(buffer) - 1);
    if (ret <= 0){
        Serial.println("error receiving");
    }
    else {
        buffer[ret] = '\0';
        Serial.print(buffer);
    }

    //************* Close TCP or UDP connections **********
    sim808.close();

    //*** Disconnect wireless connection, Close Moving Scene *******
    sim808.disconnect();
}

```
> 1 votes

---
Tags: arduino-mega, gsm, gps
---


# Question
Title: Would this substitute for an Interrupt timer?
```
class Pseudo_Interrupt {
  //only cummulative time is important, exact interval is not
  // Class Member Variables
  // These are initialized at startup
  long OffTime = 1000; // milliseconds of off-time
  // These maintain the current state
  unsigned long previousMillis; // will store last time updated

  void Update() {
    // check to see if it's time for an Interrupt
    unsigned long currentMillis = millis();
    if ((currentMillis - previousMillis >= OffTime) {
      //Time to execute the one second code
    }
  }
}

```

# Answer
> 2 votes
The whole idea is sound, but I would make a few changes:

* as explained by Jot in a comment, you have to update `previousMillis` inside the `if` statement. You have two choices:
    + set it to `currentMillis`, then `OffTime` will be the *minimum* time between the pseudo-interrupts
    + increment it by a constant amount, which I would call `period`, then this will be the *average* time between pseudo-interrupts; this is more similar to how real timer interrupts work
* add a constructor for:
    + making the period user-selectable
    + making the action of the timer user-selectable via a callback
    + initializing `previousMillis`

With those changes, the class will look like:

```
class Pseudo_Interrupt {
    unsigned long period;
    unsigned long previousMillis;
    void (*callback)();

public:
    Pseudo_Interrupt(void (*callback)(), unsigned long period)
        : period(period), previousMillis(millis()), callback(callback)
    { }

    void update()
    {
        if (millis() - previousMillis >= period)
        {
            callback();
            previousMillis += period;
        }
    }
};

```

# Answer
> 2 votes
Latest Version: 7/6/17

```
//--------------------------------------------------------
class Pseudo_Interrupt {

{   // These maintain the current state of the timer
public:
volatile unsigned long previousMillis;   // will store last time updated
volatile unsigned long lateMillis = 0;       // how late was it
volatile bool CallOneMinute = false; //facilitates while loops,
}
// to prevent a callback set previousMillis = millis(); periodically within the 'period'
// to start the callback set previousMillis = millis() - period; lateMillis = 0;
volatile unsigned long currentMillis;
static const unsigned long period = 1000;     // milliseconds of off-time delay
volatile unsigned long delta;
    void (*callback)();
public:
    Pseudo_Interrupt(void (*callback)(), unsigned long period)
        : period(period), previousMillis(millis()), callback(callback)
    { }

    void update()
    {       currentMillis = millis();
            CallOneMinute = false
            delta = currentMillis - previousMillis - period
        if (lateMillis + delta >= 0)
            lateMillis = delta;
            CallOneMinute = true
        {
            callback();   // with correction to keep net correct cumulative time
            previousMillis += ( period - lateMillis );
    }
};
//----------------------------------------------------------

```

# Answer
> 1 votes
Yes, if you advance previous millis by 1000 once that comparison is true.

Setting previous millis to current millis is the wrong approach as it will accumulate timing errors.

edit:

here is a simple piece that hopefully will do what you are trying to do.

```
//pseudo timer isr
//return 1 if the timer overflows MYTMR_PR
uint8_t mytmr_ovf(void) {
    static uint32_t last_time=0;        //previous time
    uint32_t current_time;

    current_time = millis();            //take current time
    if (current_time - last_time >= MYTMR_PR) {
        last_time += MYTMR_PR;          //update last time
        return 1;                       //indicate overflow
    }
    return 0;                           //indicate no overflow
}

```

as I suggested earlier, the code is written so that the timer is long-term accurate.

Hope it helps.

edit 2: here is the above code running on a PIC24F, with MYTMR\_PR set to 100 (=100ms)

```
//user loop
void loop(void) {
    //looping around
    if (mytmr_ovf()) digitalWrite(LED, !digitalRead(LED));   //flip the led
}

```

# Answer
> 1 votes
A function called by your program can do some, but not all, of what an interrupt function does. If you call it frequently enough, you can get timely execution of your "one second code". How frequently you must call it depends on how precisely an execution interval you need. That may require your mainline code to spend more time polling the timer than you can afford; it depends on your particular circumstances.

A true interrupt function will be called nearly immediately on the occurrence of whatever event is set to trigger it. Until then, no time will be taken from your mainline code.

Whether that is that is an effective substitute depends on your particular situation.

The code you supplied is not syntactically correct and does not compile. Nested functions are not include in C or C++, and in the 'if' statement, the parentheses are unbalanced.

# Answer
> 1 votes
I have since put the following in a continuous fast loop. When the program gets to it, it executes. The one second is a little erratic, but the total cumulative is approximately correct.

```
long OffTime = 1000;     // milliseconds of off-time

// These maintain the current state of the timer
long previousMillis;   // will store last time updated
long lateMillis;       // how late was it

//----------------------------------------------------------------------

currentMillis = millis();     //correct for millis() overflow
if (currentMillis - previousMillis < 0 )
    currentMillis = currentMillis + 32768;
{
    if (currentMillis - previousMillis >= OffTime - lateMillis )

        // Assume the difference is longer than 1000 milliseconds
        // because the sample time will be late but not by much
        lateMillis = currentMillis - previousMillis - OffTime;

        // Thus, cumulative time is essentially correct
        //Time to execute the one second code here
        do some code
    else
        return;
    }
// ----------------------------------------------------
}  //  End Of Run Repeatedly

```

---
Tags: timers
---