# Question
Title: Code for mapping voltage on a sensor and outputting a value in liters
I got a Resistive sender fuel gauge sketch off the internet that I have adapted. The Resistive sender is a floating magnet that activates read switches to vary the resistance. Using a stable 5v power source and 100-ohm resistor I have a voltage bridge that is connected to the sender and pin A1. The original sketch uses this to get the voltage into liters:

```
TankValue0 = map(sensorTankValue0, 352, 824, 0, 100);
if (TankValue0 < 0) {
  TankValue0 = 0;
}
if (TankValue0 > 100) {
  TankValue0 = 100;

```

The lower range is not too far off but as you get to the top it is out to lunch.

I have mapped the segments of MY float sensor's intervals, and have found there to be 17 distinct points-- I measured the voltage at each point and made a table (I mean like on paper) to relate the measured voltage at a given point to a distance in mm, and then converted that to the relevant metric of liters in a tank when the float switch is reading a given voltage.

| V | L |
| --- | --- |
| 4.04 | 94 |
| 3.981 | 88 |
| 3.902 | 84 |
| 3.81 | 81 |
| 3.703 | 77 |
| 3.637 | 72 |
| 3.564 | 69 |
| 3.483 | 65 |
| 3.393 | 61 |
| 3.293 | 57 |
| 3.18 | 53 |
| 3.053 | 50 |
| 2.908 | 46 |
| 2.546 | 42 |
| 2.192 | 38 |
| 1.726 | 35 |

How do I get that information into the sketch to give me a read-out of L in my tank?

I have no programming knowledge really. I work with Arduino IDE a lot, but only using sketches other people have written. So, I have a huge basic knowledge gap. So, please bare that in mind.

This is the whole sketch:

```
#include <LiquidCrystal_I2C.h>

int TankValue0;
int TankValue1;

LiquidCrystal_I2C lcd(0x27, 16, 2);   // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup() {
  lcd.init();                          // initialize the lcd
  lcd.init();
  lcd.backlight();
  lcd.setCursor(1, 0);
  lcd.clear();
  lcd.print("WORD");
  lcd.setCursor(0, 1);
  lcd.print("TO");
  delay(1500);
  lcd.clear();
  lcd.print("YO ");
  lcd.setCursor(0, 1);
  lcd.print("MOMMA");
  delay(2000);
  lcd.clear();
  pinMode(A0, INPUT);
  Serial.begin(9600);               // starting the Serial Monitor

}
void loop() {
  int sensorTankValue0 = analogRead(A0);
  int sensorTankValue1 = analogRead(A1);
  TankValue0 = map(sensorTankValue0, 352, 824, 34, 94);
  TankValue1 = map(sensorTankValue1, 785, 310, 0, 100);
  if (TankValue0 < 0) {
    TankValue0 = 0;
  }
  if (TankValue1 < 0) {
    TankValue1 = 0;
  }
  if (TankValue0 > 100) {
    TankValue0 = 100;
  }
  if (TankValue1 > 100) {
    TankValue1 = 100;
  }
  lcd.print("S.V. SAVANNAH");
  lcd.setCursor(0, 1);
  delay(100);
  lcd.print("DAY TANK   ");
  lcd.print(TankValue0);
  lcd.print("%");
  lcd.setCursor(0, 0);

  delay(1000);
  lcd.clear();
}

```

# Answer
> 1 votes
## Curve fitting

Well, a lazy way to do it is just to fit a curve to it, using Excel, or Libreoffice, Google Docs or whatever. Here's gnuplot being used that way to fit a cubic polynomial to it:

"points.txt" containing your data, tab-delimited:

```
4.04    94
3.981   88
3.902   84
3.81    81
3.703   77
3.637   72
3.564   69
3.483   65
3.393   61
3.293   57
3.18    53
3.053   50
2.908   46
2.546   42
2.192   38
1.726   35

```

Gnuplot session:

```
gnuplot> f(x) = A*(x**3) + B*(x**2) + C*x + D
gnuplot> fit f(x) "points.txt" via A, B, C, D
iter      chisq       delta/lim  lambda   A             B             C             D
   0 1.8323200047e+01   0.00e+00  9.28e+01    2.818423e+00  -1.100151e+01   1.447650e+01   2.873579e+01
   1 1.8323200047e+01  -4.65e-10  9.28e+00    2.818423e+00  -1.100151e+01   1.447650e+01   2.873579e+01
iter      chisq       delta/lim  lambda   A             B             C             D

After 1 iterations the fit converged.
final sum of squares of residuals : 18.3232
rel. change during last iteration : -4.6534e-15

degrees of freedom    (FIT_NDF)                        : 12
rms of residuals      (FIT_STDFIT) = sqrt(WSSR/ndf)    : 1.23569
variance of residuals (reduced chisquare) = WSSR/ndf   : 1.52693

Final set of parameters            Asymptotic Standard Error
=======================            ==========================
A               = 2.81842          +/- 1.156        (41.02%)
B               = -11.0015         +/- 10.22        (92.86%)
C               = 14.4765          +/- 29.11        (201.1%)
D               = 28.7358          +/- 26.52        (92.27%)

correlation matrix of the fit parameters:
                A      B      C      D
A               1.000
B              -0.998  1.000
C               0.990 -0.997  1.000
D              -0.974  0.987 -0.996  1.000

```

And here's what looks like against the actual data with `plot "points.txt" with linespoints, f(x)`:

So you have a function:

```
float f(float x) {
  static const float A =   2.81842;
  static const float B = -11.0015 ;
  static const float C =  14.4765 ;
  static const float D =  28.7358 ;
  const float x_squared = x * x;
  const float x_cubed   = x * x_squared;

  return A * x_cubed + B * x_squared + C * x + D;
}

```

If you don't care about the code size and the slowness of `float` arithmetic, then that might be okay.

Otherwise you may want to convert that function to something like fixed point arithmetic.

A cubic polynomial may be overkill, but then whole technique may be also.

## Peicewise Linear

You can make a table of you points and just do what graphing programs typically do, linear interpolation between the points.

```
float f(float x) {
  static const struct pt {
    float v;
    int l;
  } points[] = {
    {0.0  ,  0},  // I put this here for testing, but put a better value here.
    {1.726, 35},
    {2.192, 38},
    {2.546, 42},
    {2.908, 46},
    {3.053, 50},
    {3.18 , 53},
    {3.293, 57},
    {3.393, 61},
    {3.483, 65},
    {3.564, 69},
    {3.637, 72},
    {3.703, 77},
    {3.81 , 81},
    {3.902, 84},
    {3.981, 88},
    {4.04 , 94}
    // you should probably have another entry here so that readings up to 5V work.
  };
  static const size_t table_len = sizeof points / sizeof points[0];

  for (size_t i = 0; i < table_len - 1; ++i) {
    if (x >= points[i].v && x < points[i + 1].v) {
      return
            (x - points[i].v)
          / (points[i + 1].v - points[i].v)
          * (points[i + 1].l - points[i].l)
          + points[i].l;
    }
  }

  return -1;
}

```

Sitting in the center of this in the `return` statement is basically a crude implementation of Arduino's `map()`, but for floating point, which again, you don't really need floating point, even if you want to use this piecewise approach.

In short, you find which two entries of the table you're sitting between, and apply what amounts to `map()` on the line segment formed by the two table entries.

## PROGMEM

Either of the curve fitting or piecewise approach could be used to generate a much larger lookup table out of which you could just chose the nearest point.

If you're doing this on an AVR-based Arduino, the table for the piecewise linear approach or a pure lookup table approach could use `PROGMEM` for the array.

## Regarding float and fixed point

Any of these techniques could be adapted to fixed-point math.
Which ever you use, if you're on AVR based Arduino, keep in mind that there's no hardware floating point support at all, and although `double` exists as a type it is implemented in avr-gcc as a single precision `float`.

If you're using one of the non-AVR based Arduinos, it may have support for `float` (and maybe for `double`), in which case the generated code may not be so bad, though may still be slower than using integers.

If you can do everything with integers, resulting code should be a lot smaller and faster. I'm guessing for what you're doing, if either of them are more important, it's probably being smaller.

For using integers, you may be able to keep your input "voltage" as an ADC count, not having an intermediate voltage calculation. And even if you want single digit liters when you're done, the intermediate interpolation, curve fitting, or table lookup may require that you work in something like centiliters, milliliters, so that values like the `A` constant from the curve-fitting example can be represented as an integer, e.g. 2818 mL rather than a cruder 3 L. If you're not using a plain lookup table and finding the nearest entry, that is if you're using the curve or piecewise linear approach, doing everything in integer arithmetic from ADC count to mL. Although you'll need to run another curve fitting, since the `A`, `B`, etc will representing mL-per-ADC-count not L-per-Volt. Or scale them from the value given.

And there are other options, piecewise cubic splines, etc.

---
Tags: map
---


# Question
Title: Arduino changing output based on wire voltage
I’m new to arduino and I want to build myself smart switch that can be turned of both manualy and via wifi, is there any way to change position of relay based on if another wire is live or not? Im from europe so we have 230V outlets.

Thanks for the answer.

# Answer
Maybe a wire coil wound around the wire could pick up the frequency. Though I won't write about this, since I don't know much about how you would measure this, and because I think, that you are looking the wrong way.

You want to switch one device with multiple switches (how these switches are operates is not important for now). You can look at how this is normally done in eletrical installations. Here the switches are all connected to your breaker box. And there is one component, that waits for trigger signals from the switches and will switch the target device (the light in this case) accordingly. So in the end there is only one place, where the light is switched: in the breaker box. The switches in the room are only triggers. The current for the light does not flow through them. Also they don't necessarily need to carry mains voltage (triggers could also be low voltage) (though it seems they are in fact just using mains voltage, for which I don't know the reason. Maybe to avoid additional voltage conversion).

So I propose the following solution: The mains wires (230V) are only connected to the light and a (suitable) relay board. The relay board is connected to the Arduino, which can act as a Smart Switch (switching via WiFi, time based or whatever). For manual switching you can connect a switch or button to the Arduino and program the Arduino to read it and control the relay accordingly.

This solution is way easier, than trying to sense the live voltage on the lines, and this will most likely make it more reliable . It comes down to controlling an relay board and reading a button/switch, both things with tons of tutorials on the web

Note: Since mains voltage is always really dangerous, you should be really really caution. Don't use mains voltage, when developing your device. A simple LED with current limiting resistir connected to the power line of the Arduino through the relay is sufficient to check the complete functionality. Only connect mains voltage, if you are really really sure, that you did everything correct
> 1 votes

---
Tags: relay, switch, voltage, input
---


# Question
Title: Connecting an Arduino Nano to a Raspberry Pi Zero
I'm working with an Arduino Nano Every, and I'm trying to connect it to the Raspberry Pi Zero for data collection from I2C sensors and writing/program code from the Pi to the Arduino. Typically, I would use a USB cable to connect from the Pi to the Arduino. However, this is going to be in an area where space is limited, so I'm looking for ways to connect the Arduino to the Pi that does not involve a USB cable. Are there other ways for the Pi and the Arduino to communicate the same way as if they were connected together via USB cable, perhaps through the Raspberry Pi's GPIO pins? What are some advantages/disadvantages of doing it in other ways?

EDIT: Something that also occurred to me: When connecting the Arduino to the Pi, to ensure that the Arduino has enough power, is there no choice but to use USB?

# Answer
You can connect via:

* UART
* I2C
* SPI

All are available on the Pi's GPIO header and on the Arduino. You will of course need logic level translation for a 5V Arduino.

Using UART is probably simplest for you since that is identical to using the USB - you just use /dev/ttyS0 (or /dev/ttyAMA0 on older Raspberries) instead of /dev/ttyUSB0 or /dev/ttyACM0. Just connect the Pi TX to the Arduino RX, and the Arduino TX to the Pi RX through logic level translation (voltage divider is a possibility).
> 3 votes

# Answer
The pi zero w has micro usb and the arduino nano has mini usb.

Can we use mini-micro usb cable to connect them?
> 0 votes

---
Tags: programming, arduino-nano, communication, raspberrypi
---


# Question
Title: Remove unwanted characters from char type
I'm working on an ESP8266 module that needs to fetch date data from worldtimeapi, everything works fine but the problem is **How do I strip of the time field off the datetime JSON response without loop**.

**Note:** Arduino JSON library was used in deserializing the response data and it seems the library only supports `char` data type.

```
void loop ()
{
  // Initialize the request object
  HTTPClient request;

// Make a http request
  request.begin(dateTime);
  delay(2000);

  // Check the request status code.
int  responseCode = request.GET(); //Get the api host response code.
  Serial.print("Response code is: ");
  Serial.println(responseCode);
  if (responseCode == 200); // If the server returned OK
  {
      String responseData = request.getString();
      Serial.println("Response from the server is:");
      Serial.println(responseData);
        // Deserialize the JSON response data
       StaticJsonDocument<715> result; // Declare data storage to stack

      //Check for error during data deserialization
      DeserializationError error = deserializeJson(result, responseData);

      if (error)
      {
        Serial.print(F("Response deserialization failed with reason: "));
        Serial.println(error.f_str());
        return;
      }

      else
      {
        char abbreviation = result["abbreviation"];  // Returns the current time zone abbreviation
        char timezone = result["timezone"]; // Returns the current time zone
        char datetime = result["datetime"]; // "2021-03-12T17:04:0
        char date = datetime.remove(9,22); // This line throws error : request for member 'remove' in 'datetime', which is of non-class type 'char'

        Serial.print("Current time is ");
        Serial.print(datetime);
        Serial.print(" ");
        Serial.print(abbreviation);
        Serial.print(" ");
        Serial.println(timezone);
        delay(2000);
      }

  }

}

```

# Answer
You can use `strtok` to split the string on the T character:

```
char *datepart = strtok(datetime, "T");
char *timepart = strtok(NULL, "T");

Serial.print("The current date is: ");
Serial.println(datepart);
Serial.print("The current time is: ");
Serial.println(timepart);

```

An alternative is to just find the `T` and turn it into the NULL terminating character:

```
char *T = strchr(datetime, 'T');
*T = 0;

```

---

If you need to copy the string data into a temporary string first you can do:

```
char temp[strlen(datetime)+1];
strcpy(temp, datetime);

```

Then operate on `temp` instead of `datetime`.
> 2 votes

---
Tags: esp8266, string, json
---


title: using a variable to index an array

text:
# Question
Title: using a variable to index an array
I'm using the keypad library to return a number 1-9. (im fairly sure this returns an int) I have an array (data) showing the state of each button press. so i would like the number returned by the keypad (key) to be the index number that gets edited from 0 to 1 and from 1 to 0.

```
    //REMOTE KEYPAD TO CONTROL OUTPUTS OVER SERIAL

#include <Keypad.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},

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

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

int iAm = 1;                                    //this is device number 1
float checkSum = 0.00;                          //check sum to send as serial
float voltage = 5.26;                           //system voltage
bool data[8] {0, 0, 0, 0, 0, 0, 0, 0, 0};       //keypad output call

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

void loop() {

  int key = keypad.getKey();

  if (key) {
        data[key] = 1;

    //checkSum = voltage * (iAm + data[0] + data[1] + data[2] + data[3] + data[4] + data[5] + data[6] + data[7] + data[8] + data[9]);
    //Serial.print(iAm);
    //Serial.print("/");
    Serial.print(data[1]);
    Serial.print("/");
    Serial.print(data[2]);
    Serial.print("/");
    Serial.print(data[3]);
    Serial.print("/");
    Serial.print(data[4]);
    Serial.print("/");
    Serial.print(data[5]);
    Serial.print("/");
    Serial.print(data[6]);
    Serial.print("/");
    Serial.print(data[7]);
    Serial.print("/");
    Serial.print(data[8]);
    Serial.print("/");
    Serial.print(data[9]);
    Serial.print("/");
    Serial.print(voltage);
    Serial.println("/");
    //Serial.println(checkSum);

  }

}

```

i can edit the index location by typing data\[1\] = 1 but not as a variable so i suspect an index cant be addressed as int? but i don't know what it should be addressed as or how to change it to that.

# Answer
> 1 votes
not going to pretend i understand why all my keypad numbers are 48 higher than the number printed on the keypad but:

```
int key2 = key -48;

```

works

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


title: Atmega 328P U crash on 5V/1A

text:
# Question
Title: Atmega 328P U crash on 5V/1A
Atmega 328PU crash on 5v/1A. Why? It works on 5V/400ma but when i switch it to 5V/1A power it crash. Any idea or solution for this?

# Answer
Nothing wong, if your power supply is trustworthy enough, then , if u even provide 100000 Amps of current with 5 volt, your IC won't burn, in your case , it burnt because your power supply seems to be defective, and please check the voltage of the power supply which is supposed to be defective, so it output more than 5 volts burning or crashing your ic...

Note:

I have personally worked with 5 volt 6 amp power supply which is very well precise and my ic is working full fledged without any problems.
> 3 votes

---
Tags: arduino-uno, atmega328
---


# Question
Title: FastLED fill_rainbow - Unexpected red pixel
I'm using FastLEDs builtin fill\_rainbow function for generating a rainbow spectrum on an LED strip. The issue is, I get a random red pixel midway through the yellow region. I've tried it on 3 different Arduino nano's, and two different LED-strips. Here's the code:

```
#include <FastLED.h>

#define DATA_PIN 2
#define NUM_LEDS 114
CRGB leds[NUM_LEDS];

uint8_t hue = 0;

void setup() {
  Serial.begin(115200);
  FastLED.addLeds<WS2812B, DATA_PIN, GRB>(leds, NUM_LEDS);

  fill_rainbow( leds, NUM_LEDS, hue, 1);
  for(int i=0; i<NUM_LEDS; i++) {
    Serial.print(i);
    Serial.print(' ');
    Serial.print(leds[i].r);
    Serial.print(' ');
    Serial.print(leds[i].g);
    Serial.print(' ');
    Serial.println(leds[i].b);
  }

  CHSV hsv;
  CRGB rgb;
  //rgb = hsv;
}

void loop() {
  fill_rainbow( leds, NUM_LEDS, hue, 1);
  FastLED.show();
}

```

Here pixel number 60 gets the rgb code 160, 0, 0. When it should have something like 160, 150, 0.

The strangest part of all is that I can get rid of the problem in two ways, either by uncommenting the line rgb = hsv;, or by commenting out the fill\_rainbow function in the loop function. This strange behavior leads me to believe im somehow messing up a pointer or misusing a FastLED feature. Additionally the fill\_rainbow function is very simple and relies on FastLEDs hsv to rgb typecasting, which is another reason to believe I'm doing something wrong.

So help me out here, am i doing something silly, or have I discovered a bug with FastLEDs hsv to rgb converter?

# Answer
> 1 votes
I just copied your exact code and ran it with 600 of my LEDs. I have WS2812B as well, and using the same data pin coincidentally.

I haven't experienced your red LED issue. I then ran it again on my LEDs after adding

```
 hue++;

```

at line 33.

Only problem I can see is that the last 30 LEDs at the end of the rainbow kind of flicker. Groups of 10 LEDs spontaneously flicker at once, then another 10, and so on. This could be a problem with my LEDs though because they were the cheapest one's I could find on ebay 2 years ago. The code seems to work fine for me though!

# Answer
> 0 votes
It seems that this is caused by a compiler bug when compiling with the default -Os (optimize for size) option.

see Issue : fill\_rainbow() - Unexpected red pixel #668

A workaround is to change the optimization level to -O3 for `fill_rainbow`, ie :

```
#pragma GCC push_options       // Disable the size optimization
#pragma GCC optimize ("-O3")   // to prevent the “red pixel” problem
void fill_rainbow( struct CRGB * pFirstLED, int numToFill,
                  uint8_t initialhue,
                  uint8_t deltahue )
{
    CHSV hsv;
    hsv.hue = initialhue;
    hsv.val = 255;
    hsv.sat = 240;
    for( int i = 0; i < numToFill; i++) {
        pFirstLED[i] = hsv;
        hsv.hue += deltahue;
    }
}
#pragma GCC pop_options // Enable the prior optimization

```

You would have to edit `colorutils.cpp` (the file where `fill_rainbow` lives above) in the FastLED source in your `\libraries` directory.

---
Tags: led, rgb-led, led-strip
---


# Question
Title: Controlling op amps amplification ratio by arduino
Is there any option how to control amplification ratio of operational amplifier by some logic signal which can be produced by arduino? I am talking about some clasic op amp like lm356 or ui741 in basic inverting or non-inverting circuit (i would like to use non-inverting circuit in my application). I know only about digital potentiometer like solution but i think that it isn't profesional and most eficient solution, so I want to know your opinion. Thanks for reply.

# Answer
The basic principle is easy to implement. A non-inverting configuration has a resistor Ri from the inverting input to ground, and a feedback resistor Rf from the same input to the output. The signal is applied to the non-inverting input. The gain is 1+Rf/Ri. You can control the gain by changing Ri, which can be done via a CD4016 quad analog switch and 4 resistors.
HOWEVER, the Arduino is a 0-5V device. The CD4016 can handle 15V, but to switch it the digital input must pass through half the supply. The op-amps you mention will require bipolar supplies to handle AC signals (which I assume is what you want), so you could run them with +/-7.5V, with the CD4016 powered between them. Then to get the Arduino 0-5V to toggle the CD4016 you'd need some level-shifting transistors to get it to +/-7.5. The upshot is that this is surely going to be more trouble than it's worth.

However, if you are willing to drop the ancient op-amps and use a modern single-supply type (MCP6021, LT1013, etc) that runs on 0-5V, you can use input and output capacitors to convert the signal to AC, then just use the CD4016 as-is. Or JFET transistors, or even bipolars to switch the gain resistor under Arduino control if you don't need audiophile quality.
> 2 votes

---
Tags: arduino-uno, arduino-nano, digital-analog-conversion, analog, op-amp
---


# Question
Title: Strange behavior from uint32_t, acting like signed int (Nano clone)
I'm having trouble with these variables. As you can see they're uint32\_t type, so they should have a maximum value of 4 million or so, but they're rolling over and going negative at 32,767 like a signed int. Here's the relevant code:

```
byte lPin = 7;
char buff[100];
uint32_t loAvg = 0;
uint32_t hiAvg = 0;

void setup() {
  pinMode(lPin, OUTPUT);
  digitalWrite(lPin, HIGH); // Active LOW, so this is off

  Serial.begin(9600);
  // Generate high/low averages
  for(int i = 0; i < 100; i++) {
    loAvg += analogRead(A0);
  }
  loAvg /= 100;

  digitalWrite(lPin, LOW);
  delay(500);

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

  digitalWrite(lPin, HIGH);
  delay(500);

  sprintf(buff, "loAvg=%d, hiAvg=%d", loAvg, hiAvg);
  Serial.println(buff);

  Serial.println(hiAvg);
  digitalWrite(lPin, LOW);
  hiAvg = 0;
}

void loop() {
  sprintf(buff, "test=%d", hiAvg);
  Serial.println(buff);
  hiAvg+=100;
}

```

I removed a bunch of stuff from the code to save posting the whole (much longer) thing. If it ends up being relevant I can though, I just think I narrowed the problem down to this. Observing the serial monitor I get this on startup:

```
loAvg=287, hiAvg=0
933
test=0
test=100
test=200
...

```

The `test=#` repeats until 32700, then continues at -32736. I'm confused by the hiAvg=0 followed by the 933, showing that it totally is getting a high average, because that's around what it should be. Even if it's the sprintf() messing with it, in the setup function the value should only be around the 900 range so it wouldn't overflow there. Any ideas anyone?

# Answer
`%d` expects a signed int. `%u` expects an unsigned int. Insert the `l` modifier to expect a long in each of those cases. So you need a format code of `%lu` to print a uint32\_t.

The following code:

```
#include <Arduino.h>

void setup()
{
    uint32_t x=110000;
    char buf[50];

   // Open console
   Serial.begin(115200);

    sprintf(buf, "%%d: %d\n", x);       Serial.print(buf);
    sprintf(buf, "%%u: %u\n", x);       Serial.print(buf);
    sprintf(buf, "%%ld: %ld\n", x); Serial.print(buf);
    sprintf(buf, "%%lu: %lu\n", x); Serial.print(buf);
}

void loop() {
   ;
}

```

prints this:

```
%d: -21072
%u: 44464
%ld: 110000
%lu: 110000

```
> 4 votes

# Answer
## *`printf` and bit-width specified types

`#include <inttypes.h>` or C++'s `#include <cinttypes>` counterpart (when you have it; not on AVR-based Arduinos) gives access to macros defined for the format specifiers for each of the fixed, fast, and least versions of these types. All of these macros expand to some string literal or another.

For `uint32_t` the macro defining to its format specifier is `PRIu32`. For an AVR, this is `"%lu"`. It needn't be `"%lu"` in the general case. `uint32_t` is one of the types where you can often get away with using `"%lu"` and have it either work out being exactly correct for the platform or somewhat incorrect but working anyway because it's a platform where `unsigned int` and `unsigned long` happen to have the same representation.

In C and C++, and so Arduino, adjacent string literals are concatenated into one logical string in the early phases of compilation that follow the macro preprocessor. So, the intention is that you choose the correct macro and you put them following something like `"%"` or `"%12"` if you wanted a minimum-width of 12. As in `"%" PRIu32` and `"%12" PRIu32` respectively. So, in your case, having included (directly or indirectly) `<stdint.h>` for `uint32_t` and `<inttypes.h>` for `PRIu32` or their C++ counterpart headers, and then your code looks something like:

```
snprintf(
  buf,
  sizeof buf,
  "loAvg=%" PRIu32 ", hiAvg=%" PRIu32,
  loAvg,
  hiAvg
);

```

There's little to no reason to not use the s**n**printf. The reason why the non-n version exists at all is mostly that `snprintf` showed up in 1999, instead of circa the mid 1970s. I'd say it's pretty safe to use `snprintf` now. There probably hasn't been an Arduino that doesn't support it. About the only reason to use `sprintf` would be if you were calling it with a null pointer for the buffer argument to get it to do a dry run and tell how much memory you need for the result, and you just didn't want to supply a limiting size.

There are `PRI...` macros for all of the combinations of standard bit width and choice of signed decimal, unsigned decimal, lowercase hex, uppercase hex, etc. E.g `"%" "PRId16"` is for `int16_t` in decimal, `"%" PRIX64` for `uint64_t` in hexadecimal with uppercase alphabetics. The are ones for the `fast` and `least` bitwidth types, and whole show is repeated with macros starting with `SCN` for the `scanf` specifiers, not that you should use the `scanf` family functions for anything really.

`snprintf` and `sprintf` are variadic functions. After the format specifier there's no type information available to the compiler to know what conversions to apply. It will convert types smaller than `int` rank up to `int` on `unsigned int`, but that's about it. E.g. it will not reliably down-convert an `unsigned long long` into an `unsigned int`, the way it would if the types were known. Modern compilers will sometimes warn you if you grossly misapply format specifiers, but they're not required to. They're not expected to dissect the format string and attempt to recover type information. So it's up to you to make sure whatever you pass in for arguments matches with the format specifiers. As you've seen it's confusing if you get it wrong with `printf`-type functions, but it doesn't cause real problems unless you, you know, don't limit it to stay within the output buffer with the s**n**printf version. In the case of passing in an `unsigned long long` where an `unsigned int` was expected, in practice, for a little-endian system like AVR, it may appear to do that for one argument. But then it may fail on the next argument, because the size of the last argument was in correct, it is now reading from the wrong place.

## `Print`/`Stream`/`Serial` concatenating and buffering

The way you're using `sprintf` in your code isn't taking advantage of any of its features that `Serial`/`Print` doesn't do.

```
Serial.print(F("loAvg="));
Serial.print(loAvg);
Serial.print(F(", hiAvg="));
Serial.println(hiAvg);

```

Despite taking four lines, this is actually smaller, faster, more reliable code than the `sprintf` one-liner.

Putting the output into a buffer first might make sense if you were going to put it into a packet, like for UDP or nRF24L01. But, `Print`/`Stream`/`Serial` already concatenates and buffers things for you.

---

Incidentally, if you're going to use `printf` functions and you're doing it on an AVR-based Arduino, look at the avr-libc documentation for the `_P` variants that take their format strings from PROGMEM and the `PSTR` macro.

It is also possible to complete the implementation of `<stdio.h>` for `stdout` and `stderr` through libc-specific means. So, if you really want to, you can have the regular `printf` function pushing data out through `Serial` (among other things) such that you *don't* need to buffer repeatedly with `sprintf`.
> 2 votes

---
Tags: arduino-nano, printf
---


# Question
Title: Arduino Leonardo doesn't print anything to Serial Monitor with my specific code
I did a project with an Arduino Leonardo and a fingerprint sensor (DY50). When I uploaded the `enroll` example from the `Adafruit Fingerprint Library` and saved my fingerprint, everything worked. But when I upload my code, it doesn't print anything.

**My Code**

```
#include <Keyboard.h>
#include <Adafruit_Fingerprint.h>
#define mySerial Serial1

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
int fingerprintID = 0;
String inData;
bool isRight;
int pos;

//Number of services to log in
#define servNum 5

//Login URLs for Google, Amazon, Stackoverflow, Arduino and Github
String LogInURL[] = {"https://accounts.google.com/signin", "https://www.amazon.de/ap/signin", "https://stackoverflow.com/users/login", "https://login.arduino.cc/", "https://github.com/login"};
String LogInUser[] = {"user.name@gmail.com", "user.name@example.com", "user.name@example.com", "username", "username"};
String LogInPwd[] = {"password", "password", "password", "password", "password"};

void donothing() {};

void StepsBefore(int serviceNum){
  switch(serviceNum){
    case 0: donothing(); break;
    case 1: donothing(); break;
    case 2: for(int k=0; k<18; k++) Keyboard.press(KEY_TAB); Keyboard.release(KEY_TAB); break;
    case 3: for(int k=0; k<2; k++) Keyboard.press(KEY_TAB); Keyboard.release(KEY_TAB); break;
    case 4: donothing(); break;
    default: Serial.println("Error: Number not recognized."); break;
  }
}

void StepsAfter(int serviceNum){
  switch(serviceNum){
    case 0: Keyboard.println(); break;
    case 1: Keyboard.println(); break;
    case 2: Keyboard.press(KEY_TAB); Keyboard.release(KEY_TAB); break;
    case 3: Keyboard.press(KEY_TAB); Keyboard.release(KEY_TAB); break;
    case 4: for(int k=0; k<2; k++) Keyboard.press(KEY_TAB); Keyboard.release(KEY_TAB); break;
    default: Serial.println("Error: Number not recognized."); break;
  }
}

int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK)  return -1;
  p = finger.image2Tz();
  if (p != FINGERPRINT_OK)  return -1;
  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK)  return -1;
  Serial.print("Found ID #");
  Serial.print(finger.fingerID);
  Serial.print(" with confidence of ");
  Serial.println(finger.confidence);
  return finger.fingerID;
}

void askForFingerprint() {
  fingerprintID = getFingerprintIDez();
    delay(50);
    if(fingerprintID == 1){
      isRight = true;
    }
}

void delAfterChar(String inString, String fromToKill){
  pos = inString.indexOf(fromToKill);
  inString.remove(pos, 1000);
  inData = inString;
}

void setup() {
    Serial.begin(115200);
    Serial.println("Debug 1");
    Keyboard.begin();
    Serial.println("Debug 2");
    finger.begin(57600);
    Serial.println("Debug 3");
    if(finger.verifyPassword()) {
        Serial.println("Found fingerprint sensor!");
    }
    else {
        Serial.println("Did not find fingerprint sensor :(");
        while (1) { delay(1); }
    }
}
void loop() {
  inData = Serial.read();
  delAfterChar(inData, "?openid"); //Amazon
  delAfterChar(inData, "/v2/"); //Google
  delAfterChar(inData, "?ssrc"); //Stackoverflow
  delAfterChar(inData, "login?state"); //Arduino
    for (int i=0; i<servNum; i++){
     if(inData == LogInURL[i]){
        askForFingerprint();
        if(isRight == true){
           StepsBefore(i);
           Keyboard.print(LogInUser[i]);
           StepsAfter(i);
           Keyboard.println(LogInPwd[i]);
        }
        else Serial.println("Finger not recognized");
     }
    }
}

```

**What I've tried so far**

* I changed the baud rate from `9600` to `15200`, didn't help
* Added a few debug points in the `setup` to check for an error there, nothing changed
* Uploaded a simple Hello World via Serial Monitor sketch, worked perfectly

**Question**
What could be the issue? It compiles with no error message. If you see any coding mistakes, feedback would be great.
**EDIT**
Using `SoftwareSerial` instead didn't help either.

# Answer
As @Juraj pointed out, I just forgot to use `while (!Serial)` in the `setup`, probably because I use other boards that don't need this more often.
> 1 votes

---
Tags: serial, arduino-leonardo
---


title: Weird serial behavior on atmega2560

text:
# Question
Title: Weird serial behavior on atmega2560
**EDIT** This seems to be something to do with the oscillators. Switching to the internal oscillator and writing straight avr-c allows me to run a basic blink program. Writing the same basic blink in arduino and flashing with the IDE (through serial or usbasp) results in a non functional program. I'd like to be able to use the oscillator because it doesn't look like I can get everything done in time at 8MHZ

I have an arduino mega 2560 which a few weeks ago was working fine. Now, I'm trying to output some data from it, and 've broken it down to a very, very basic proof of concept:

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

void loop() {
   // put your main code here, to run repeatedly:
   Serial.println("hello");
}

```

This prints:

```
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

```

indefinitely on the screen. If I change the baud to 115200, I get the "hello" and the newline, and slowly start getting garbage afterwards. If I switch to 234500, I get a few prints, and then nothing.

Adding a delay after the print does not change the frequency of the serial prints:

```
void loop() {
// put your main code here, to run repeatedly:
    Serial.println("hello");
    delay(100000);
}

```

They still come in immediately.

I have a feeling this has something to do with timing of an interrupt, but I'm not setting anything up. I plan to reflash and fix the fuses, but my usbASP cable is broken right now. Any other input on what might be going on here?

Edit: This occurs on two different boards. I originally had some i2c devices (mag/gryo/barometer) on board, but those have since been removed. I have tried two different usb cables in two different USB ports. This might be on the host side?

Edit: Both the TX and Rx lights are solid this whole time. Almost as if there's a loopback. My other laptop won't even boot right now. I'm concerned a surge from a storm last night might have taken out both of these machines

More testing: Looking at the output on a scope, the board is actually only outputting an "h" character. If I do:

```
Serial.println('U');
delay(1000);

```

I get a square wave, so the delay doesn't run at all. If I do: Serial.println('U'); Serial.println('U'); //or any other character delay(1000);

I get a U character over the scope, and then an empty serial frame. The delay still doesn't run, but it looks like the second println is exiting.

Even burning a new bootloader fails on these boards

# Answer
Answering my own question - a bit of a walk of shame here.

I had disabled the internal TIMER0\_OVF\_vect in the arduino core code, so that I could write my own (for another project). I wrapped in in an #if 0 so I could go and bring it back when I needed it.

Today, I learned that the atmega interrupts aren't filled with an IRET by default, but instead hit the reset vector, resetting the board. Anything I compiled on this library would reset whenever TIMER0 overflowed, because my ifdefs didn't cover the TIMSK setting in the arduino core either

The "Serial.println isn't exiting" was actually "the board is resetting before it can complete" and explains why faster bauds could print more data.

Not much smarter than hairless apes, sometimes.
> 1 votes

---
Tags: serial
---


title: Sharing clock pin on Pro Micro

text:
# Question
Title: Sharing clock pin on Pro Micro
I am trying to get both a SPI LED matrix display and an NRF24L01 to both work on the same Arduino Pro Micro. I know they both want to use the clock pin but how do I get them to share? Can I use the CS pin to turn off one device while trying to use the other? The display does can be set only when something needs to change so it's not always running.

# Answer
It is indeed possible and supported to use different CS (chip select) or SS (“slave select”) lines to address individual SPI devices on a single bus run by an SPI “master”.

*Image from Wikipedia*

Many SPI TFT Touch displays need this to address the display controller and the touch controller as individual SPI devices and/or an integrated SD Card interface (wich also uses SPI).

The MOSI, MISO and SCLK lines can be reused and shared between perpiheral devices, as long as only one device is actively being addressed at any point in time. I.e. only one SS/CS may be active at any time and the software must support such sharing of SPI resources.
> 2 votes

---
Tags: arduino-pro-micro
---


# Question
Title: HC-05 Module not receiving commands and not pairing
I'm working on a project where I'll need to establish a connection between two HC-05 modules, each connected to an Arduino, but for now I'm just trying to get one to work and connect to my phone, but I'm not sure if I'm doing anything right...

I'm not able to give AT-Commands, and as a result the device is not able to pair with my phone. My setup looks something like this:

With minor differences being that I'm using an Uno board instead of a Mega, the RX and TX pins are connected to...well, I tried a lot of different pins, from the default RX/TX pins to specifying other pins like the ones in the code, as well as reversing the connections (RX to TX, TX to RX), also this schematic neglected to mention the 'ENABLE' pin, which I connected to my Arduino's 3,3V pin.

I tried a lot of different code samples, the latest one I tried is the following:

```
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(38400);
  Serial.println("Enter AT commands:"); // a prompt in Serial Monitor
  // Deleted while loop, unnecessary

  mySerial.begin(38400);
}

void loop() { // run over and over
  //if (Serial3.available()) { // we don't use Serial3 any more
  if (mySerial.available()) {
    //Serial.write(Serial3.read());
    Serial.write(mySerial.read());
  }
  if (Serial.available()) {
    //Serial3.write(Serial.read());
    mySerial.write(Serial.read());
  }
}

```

Which I blatantly ripped-off from this answer, with minor changes.

So, I connect my Arduino to my PC, upload the code, connect my module, set the serial monitor's baud rate to 38400 and...a bunch of gibberish appear on screen, just an alternating sequence of the characters *'x'* and *'?'*, to my understanding that's actually the message *"Enter AT commands:"* written in my code...

Now, with this exact setup, I'm now actually receiving a response to my commands, except the response is also gibberish, this is as far as I've gotten.

EDIT: By following some of the comments and setting the Serial baud rate to 38400, I managed to get other Reponses to my commands, but it's just a new type of gibberish and it's still not actually responding to my commands.

The thing is, all of the tutorials I've seen online are contradicting each other, some connect the RX and TX pins in reverse to the Arduino, some don't, some specify other pins on the board, some don't bother with the ENABLE pin entirely, some don't use a voltage divider, some connect VCC pin to the 3,3V instead of the 5V, some even skip the AT-Command setup entirely!

One last detail I feel like I should mention, **there's a red light that blinks on and off every two seconds**, I believe that means the module is read to receive commands but I've seen contradicting information about this as well so I'm not sure.

I want to know what I'm doing wrong, and what's the right way to do this?

# Answer
> 4 votes
You have seen contradictory statements, because there are many variables here, that might be different for each of the tutorials.

> some connect the RX and TX pins in reverse to the Arduino, some don't, some specify other pins on the board

There are basically 2 ways to communicate between the Serial Monitor and the HC-05:

* You can connect the HC-05 directly to the USB Serial chip on the Arduino board, thus you would communicate directly with the HC-05. In that case the `TX` and `RX` pins are used, since they are connected to the USB Serial chip. But the labels `TX` and `RX` are referring to the Arduinos chip (Atmega328p at the Arduino Uno). Since serial connections need to be connected alternating (RX to TX and TX to RX), the pin labeled `TX` leads to the `RX` pin of the USB Serial chip and vice versa.

Thus you would connect TX of HC-05 to the TX pin on the Arduino and RX of HC-05 (through the voltage divider) to the RX pin on the Arduino. Also you should program the Arduino with an empty sketch before doing that, so that the Arduino does not interfere in the Serial communication with its own Serial usage.
* Or you can use a `SoftwareSerial` interface and let the Arduino code translate between the devices. The Arduino received from the PC and sends the data to the HC-05. Also it receives from the HC-05 and sends that data to the PC. This is what you were trying. But you absolutely need to specify a different set of pins for the `SoftwareSerial` interface, than 0 and 1. These pins are doing the hardware Serial interface, which is connected to the PC. So change these pin numbers (for example to 2 and 3).

In fact: Whenever you see a code for Uno, Nano or Mega using `SoftwareSerial` on pins 0 and 1, you can be sure, that it is garbage.

> I connect my Arduino to my PC, upload the code, connect my module, set the serial monitor's baud rate to 38400 and...a bunch of gibberish appear on screen

Even when you change the pins as described above, your code still uses 9600 baud for the connection to the PC. When you set the Serial Monitor to 38400 while the code uses 9600 baud for that interface, you will get just gibberish. Either change your Serial Monitor to 9600 baud or change your code to `Serial.begin(38400)`. The last option is better, since that makes sure, that you are using the same baudrate for both interfaces.

> some don't bother with the ENABLE pin entirely

The ENABLE pin seems to have a pulldown resistor on the HC-05 board, which pulls it to ground, when nothing is connected. Ground means data mode, HIGH command mode. So when they don't connect anything, they want to stay in data mode. Though this also depends on if the specific HC-05 board has a pulldown or pullup resistor there. Pulldown is more likely, but since there is no one single producer of these modules, you cannot be sure. Since you want to get into AT mode, you should use command mode and connect it to 3.3V. For normal operation it would go to ground. Though you can also connect it to a digital output pin of the Arduino and let the code decide in which mode the module should be.

> some don't use a voltage divider

The chip on the HC-05 board is a 3.3V device. The actual breakout boards, that can be bought everywhere, mostly only add a voltage regulator from 5V to 3.3V, an LED for status display and break out the necessary pins. The data pins are mostly directly connected to the chip. There are many resources, that claim the HC-05 to be 5V tolerant, but also many that antagonize that. To be sure not to destroy the HC-05, you should also use a voltage divider.

> some connect VCC pin to the 3,3V instead of the 5V

This is only done, when the used board does not have a 5V to 3.3V voltage regulator. Depends on the exact board, that you own.

> some even skip the AT-Command setup entirely!

When they don't need to configure the HC-05 in a special way, why would they go into command mode. That might be different for you.

---
Tags: arduino-uno, c++, bluetooth, hc-05, voltage-divider
---


# Question
Title: Error compiling for board Arduino Uno SIM7000
I'm using **botletics / SIM7000-LTE-Shield** with Arduino Uno, I selected all examples but all end up with the same Error

```
C:\Users\lenovo\Documents\Arduino\libraries\SIM7000\Adafruit_FONA.cpp: In member function 'boolean Adafruit_FONA::postData(const char*, uint16_t, const char*, const char*, const char*)':
C:\Users\lenovo\Documents\Arduino\libraries\SIM7000\Adafruit_FONA.cpp:2045:3: error: expected ';' before 'readline'
readline(10000);
^~~~~~~~
exit status 1
Error compiling for board Arduino Uno.

```

# Answer
> 1 votes
I cloned botletics comparatively gigantic repo. They've modified the Adafruit library without changing the name.

The problem appears to be that you are working out of the current master branch. Switch to the latest tag, 1.1.0, and the SMS\_Response example will compile just fine. I didn't try all of the others.

Direct link to the zip file for the 1.1.0 tag.

---
Tags: arduino-uno
---


title: Coding for RTC and stepper motor

text:
# Question
Title: Coding for RTC and stepper motor
How easy is it to create a code using an RTC to rotate the stepper motor one way at a specific time and back the other way at a specific time? and that time being charged different months of the year. how would I go about this?

I want to make an automatic chicken door, to open in the morning and close at night.

Thanks

# Answer
> -1 votes
I am assuming that you want to make a clock. To do that you need to find a gear ratio where 1 revolution of the motor equals 60 seconds, and then make the gear ratios for the minutes and horse from that. Then you can use the RTC to spin the motor by 6 degrees every second. If you are not making a clock, please be more descriptive.

---
Tags: stepper, rtc
---


title: Crash when disabling bluedroid

text:
# Question
Title: Crash when disabling bluedroid
i have an ESP32 and i want to use deepsleep when it's not used. Before sending it to sleep i clean up everything, so disconnect, deinitialize and disable everything i build before. But i get a crash when i try to disable bluedroid. Does anyone have an idea why this happens?

```
void bt_deinit() {

    Serial.println("Deinit AVRC");
    if (esp_avrc_ct_deinit() != ESP_OK)
        Serial.write("Failed to deinit avrc");

    Serial.println("Deinit A2DP");
    if (esp_a2d_source_deinit() != ESP_OK)
        Serial.println("Failed to deinit a2dp");

    Serial.println("disable bluedroid");
    if (esp_bluedroid_disable() != ESP_OK)
        Serial.println("Failed to disable bluedroid");

    Serial.println("Deinit bluedroid");
    if (esp_bluedroid_deinit() != ESP_OK)
        Serial.println("Failed to deinit bluedroid");

    Serial.println("Stop BT");
    if (btStop() == false)
        Serial.println("Failed to stop bt");
}

```

output:

```
Port closed
Uploading to I/O board
Opening port
Port open
Hello there!
Bluetooth init success
good night
Deinit AVRC
Deinit A2DP
disable bluedroid
/home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/queue.c:719 (xQueueGenericSend)- assert failed!
abort() was called at PC 0x4008de6f on core 0

Backtrace: 0x40091918:0x3ffce3b0 0x40091b49:0x3ffce3d0 0x4008de6f:0x3ffce3f0 0x4013bfb6:0x3ffce430 0x4013c5f6:0x3ffce460 0x400fdbe2:0x3ffce480 0x400fdc35:0x3ffce4a0 0x400fe12e:0x3ffce4c0 0x400f6bd9:0x3ffce4e0 0x4008e559:0x3ffce510

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:9720
ho 0 tail 12 room 4
load:0x40080400,len:6352
entry 0x400806b8
Hello there!
Bluetooth init success

```

it works fine if i just do not deinitialize everything and send him directly to sleep. But this is not the elegant way.

# Answer
decoded backtrace in your question is missing, one of the choices to see stack trace is https://github.com/littleyoda/EspStackTraceDecoder

i dont know exactly if this is your case or not, but calling esp\_ble\_gap\_stop\_scanning() before esp\_bluedroid\_deinit() possibly avoids your crash.
> 1 votes

---
Tags: bluetooth, esp32
---


title: nuttx hex too large

text:
# Question
Title: nuttx hex too large
I have a teensy 4.1, and I am trying to install NUTTX the Real Time Operating System ( RTOS ). Teensy is a supported platform. I am trying install nuttx compiled from source, and upload it using the teensy loader program. my current issue is that the hex file is too large. the file size is 229Kb, which shouldn't be an issue where the flash size for a teensy 4.1 is 8MB.

I have been following the steps on these websites: this one where Nuttx is installed on a teensy 3, and the documentation for nuttx on their website

any tips or recommendations to install nuttx on a teensy 4.1 would be greatly appreciated.

# Answer
OK, so I pressed the reset button and the teensy loader program reset, and reloaded the hex file. Now it lists as I would expect it to, using 1% of the flash space. and uploads without error.
> 1 votes

---
Tags: bootloader, teensy
---


# Question
Title: What is the advantage of a 3MP OV3660 sensor on the ESP32 M5Stack camera if it can only save upto 2MP images?
I am making a self-contained stills camera and the ESP32-based modules seem well-suited to my project due to the easy incorporation of a TFT viewfinder screen and TF card slot in one package. I am not interested in saving video or web streaming. I have worked with the TTGO ESP32 camera that uses the OV2640 2MP sensor and can save full 2MP UXGA (1600x1200) resolution stills (albeit with mandatory JPEG compression turned on - I have only managed to get 1.3 MP images without compression).

I see now there is a version of ESP32 camera that uses the OV3660 3MP sensor (called 'M5Stack Timer Camera'). However, the specs for that camera https://docs.m5stack.com/#/en/unit/timercam say it can save upto a maximum of UXGA - i.e. 2MP images.

So what is the advantage of having a 3MP sensor chip if you can only save 2 MP images? Or is there a way of saving the full 3MP sensor resolution (i.e. 2048 x 1536) stills from this camera?

Thanks

# Answer
I contacted the M5Stack people directly and they assured me that they made an error in their original web page specs and that the camera does indeed support full 3MP capture. So I bought one of these M5Stack Timer Cams and tested it. I can confirm that the device will save a 3 MP image at full QXGA resolution (2048 x 1536). This option was not available on with the Win10 example app they provide but it was only possible with their official Arduino 'webcam' example. This is a web server WiFi example sketch and one of the options is QXGA and this does work.

So the definitive answer to my question (based on practical experience) is that the advantage of using the OV3660 is that it can provide 3MP pictures and the original specs provided by M5Stack were misleading hence the confusion expressed in my question.

It would also be interesting to hear if anyone has managed to get OV3660 working at full 3MP on other generic ESP32 boards. So far I have seen no other example published on the web.
> 2 votes

# Answer
The limit isn't the camera - it's the memory.

At 3 megapixels you have 3145728 pixels. At 3 bytes per pixel (8 bits each of red green and blue) it requires 9437184 bytes to store the image. That's more than can fit into the 8MB PSRAM.

1600x1200 will probably be one of the standard resolutions that the specific camera in use can capture, and is probably the biggest size that is below 8MB in size for a single frame.

So, what advantage of having a 3 megapixel camera? Well, none to you, other than the cost. It's probably cheaper to use a newer 3 megapixel camera than an older 2 megapixel camera.

---

It is perfectly possible to run at the resolutions you desire though. This resolution is known as `QXGA` and is supported by the OV3660 driver in the ESP32 Camera library. There are some caveats though:

1. You must use JPEG compression. Not only is this to make the image small enough to fit into PSRAM but also to make it possible to write the whole frame into PSRAM fast enough that you don't miss bits of the data.
2. You will not be able to "do" anything with the image other than send it to somewhere else (such as an SD card or a web server). There just isn't enough room to uncompress the image.
> 1 votes

# Answer
The m5stack timer camera X (OV3660) lacks support. There is nothing on how to flash and use micropython in this device. There is a cameratool you can download and take snapshots via serial port, there is the standard arduino software you can flash and that's it. I miss some guides on how to flash micropython on it and make it work with mqtt and more complex setups. I'm not an arduino person, just want to code some python on it.

I bought 2 of those cameras and those are sitting in a shelf for 6 months with 0 use. One day when someone publish a full micropython firmware for that camera, i'll give it a try.

PS: I've tried to compile a micropython firmware with OV3660 support, but no luck on make it work.
> 0 votes

---
Tags: esp32, camera
---


# Question
Title: How to extract code on one DT-06 board to another board?
I have two DT-06 boards DT06 datasheet.

---

The board stock firmware provides Web UI for wifi/network/serial setup. I've replaced the firmware on one board with other sketch; but now I want to revert it to the stock firmware. I cannot find the stock firmware source code anywhere. The DT-06 manufacturer also won't give it out.

Is it possible to extract the stock firmware from another DT-06 board and put it back into the other DT-06 board?

Thank you.

# Answer
> 1 votes
Okay. I found a way to extract the binary file (stock firmware) from one DT-06 and flash it to another modified DT-06, by using esptool command

```
/*To extract firmware */:
esptool.py -p COM4 -b 460800 read_flash 0 0x400000 dt06_backup.bin
/*To flash the backup binary file to another DT-06 */
esptool.py -p com4 write_flash -fm dout 0x00000 dt06_backup.bin

```

---
Tags: firmware
---


title: PWM and Analog Signal Quality

text:
# Question
Title: PWM and Analog Signal Quality
I'm converting a 0-5v PWM signal to an analog signal using an LM358D. I've connected the output to an oscilloscope to look at the signal but I'm not really sure what I'm looking at. The PWM looks ok but I'm unsure of the analog signal.

Here's some images, please let me know what you think.

Both pics are at 50% signal strength. The oscilloscope is set to defaults, simply connected the probe.

Thanks

**EDIT:**

Here's the schematic for the PWM to analog converter. The cap is a tantalum. The dip switch changes the analog from 5v to 10v, the signal looks the same on both and is correct voltage so seems to be ok?

# Answer
Something like this should work:

With this code on a Uno:

```
void setup () { }

void loop () {
  analogWrite (3, analogRead (A0) / 4);
}

```

For slightly more details see my post about doing that.
> 1 votes

# Answer
> The PWM looks ok but I'm unsure of the analog signal.

The “analog signal” looks like the PWM smoothed by a first-order low-pass filter. It still has some oscillations, 584 mV peak-to-peak. If you can tolerate that, then it's perfectly fine. If not, then increase the time constant of your filter.

A first-order low-pass filter behaves, in its stop band, like an integrator. Thus, a square signal is turned into a triangle. You are seeing exactly the expected behavior.

> The oscilloscope is set to defaults

There are no “default” settings in the oscilloscope. You probably used the “autoset” button instead. This button tries to find some settings that let you see *something* on the screen. I mean, some kind of signal, not just straight line. If the signal is almost flat, the autoset will increase the gain until you can see it is not flat. In this case, it increased the gain by a factor 10 (200 mV / division instead of 2 V used previously). It also added a negative offset in order to avoid the trace going out of the screen. See the small pentagon on the far left with a “1” inside? On the first picture this tells you where the zero (the reference potential) is relative to your signal. On the second picture, the polygon pointing at the bottom of the chart tells you the zero is off-scale.

If you want to really appreciate the smoothing action of the filter, you have to look at its input (the PWM signal) and its output (the “analog” signal) using the exact same settings. Connect the input, hit “autoset”, and look. Then connect the output, *do not* change the settings (do not hit “autoset”) and look at the output.

Better yet: forget the autoset button, adjust the settings manually and mind their values.

Better yet: as you have a two channel scope, display *both* signals simultaneously, using the exact same settings on both channels.
> 1 votes

---
Tags: pwm, digital-analog-conversion
---


# Question
Title: PIR motion sensor (HC-SR501) false results with NodeMCU
I have a PIR sensor which I use to detect the motion and turn ON and OFF the lights on the basis of it.

I have PIR connected with NodeMCU (ESP8266) based board. I find that sometimes it trigger false positive value. Even when there is no motion. As per my understanding I think any of the following reasons can be there:

1. I have NodeMCU close to it. So may be because NodeMCU heatness triggers it.
2. Some hot air blow near it. But I don't know. It trigger the false positive even in mid-night.
3. It can be trigger by mosquitoes.
4. I have my other electric wires going from near by.

I am considering these scenarios correct? If yes then how can I prevent from them?

I tried to put it in a box and make it tightly pack. but still its false trigger. I checked even with multiple sensors and have same problem.

**Any suggestions to protect this?** I also check people put capacitor to smooth it. And put some resistance on Vin.

My Vin of PIR is connected to 5v and OUTPUT pin to D2.

For reference I am having this code for checking.

```
#define SIGNAL_PIN D2

void setup()
{
  Serial.begin(115200);
  pinMode(SIGNAL_PIN, INPUT_PULLUP);
//  digitalWrite (SIGNAL_PIN, LOW);
}

void loop() {

    static uint32_t lastSeenHigh = millis();
    static bool pirState = false;
    Serial.println(digitalRead(SIGNAL_PIN));

    // If it's active then record that fact along with the time
    if (digitalRead(SIGNAL_PIN) == HIGH) {
        lastSeenHigh = millis();
        pirState = true;
    } else {
        if ((millis() - lastSeenHigh) > 10000) {
            pirState = false;
        }
    }

    if (pirState == true) {
        Serial.println("Pir Is active");
    }
//
    if (pirState == false) {
      Serial.println("PIR sensor inactive");
    }
    delay(1000);
}

```

# Answer
I had the same issue. PIRs have very sensitive circuitry and can be triggered by the WiFi signal from the ESP8266. The answer is to move them apart and with some decoupling of the power supply lines you should see much better performance. My PIR and ESP are now a couple of metres apart and I use shielded cable to connect them together.
> 1 votes

# Answer
I had the same issue. I tried various solutions on the net. Finally i solved my issue like this.

* Supplied the PIR sensor 3.3 v (from the NodeMcu board) instead of 5v (my main PS is 5V)
* Connected VCC (3.3v) cable to "HIGH PIN" of trigger pins instead of main (+) pin.
* It's not generate false positive signals about 2 hours.

Actually, I'm applied that solution -\> https://www.youtube.com/watch?v=2HbbQIqJHoE
> 1 votes

# Answer
I was also going through the same issue. But finally, the issue got resolved.

The issue is the PIR sensor that comes with ESP8266 can work with 3.3V as well as 5V. By default, the wiring is connected to the 5V which may work fine for the Arduino device but not for ESP8266.

I just removed the red cable (power cable) from the connector and connected to the other side where you can see H. That side also there are 3 pins. Remove the jumper completely and connect to the first PIN from top.

Just make sure you leave the GND and OUTPUT as it is, but only the RED wire will be connected to the first pin on the other side of the PIR sensor.
> 1 votes

# Answer
I glued some aluminum foil onto a piece of a cereal box and folded it around the PIR sensor. Works like a charm!
> 1 votes

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


# Question
Title: Why am I receiving random input values in my Arduino?
I want to use a switch for my Arduino using digitalRead(), but I keep receiving random inputs. Whenever I connect energy to that pin, it always returns HIGH, but otherwise it goes completely random.

I have tried using a resistor for the input pin, but that didn't seem to help. I am using an Elegoo UNO, and the input pin I am using is pin 2. Here's my code in case you need it:

```
const int switchPin = 3;

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

void loop() {
  // put your main code here, to run repeatedly:
  if (digitalRead(switchPin) == HIGH){
    Serial.println("on");
  }

  else{
    Serial.println("off");
  }
}

```

# Answer
> 24 votes
You're getting noise pickup on the input pin when the button is not pressed. You need a pull-down resistor, about 10 kΩ to ground, to quiet the noise when the switch is open.
Or even easier, use the built-in pull-up resistor in the Arduino, which is ~10 kΩ to +5 V, wire your button to ground instead of +5 V, and reverse the `if` tests to test for logic LOW instead of HIGH, to detect a button press. You'd change your pinmode statement to:

```
pinMode(switchPin, INPUT_PULLUP);  // engage the input pullup

```

and your test to:

```
 if (digitalRead(switchPin) == LOW ){ // Negative logic

```

No additional (external) hardware is needed!

# Answer
> 3 votes
Your code mentions pin 3 while you describe using pin 2. Perhaps that has to do with your error.

Otherwise, check the following things:

* do you use long cables or is it near strong magnetic or static objects.
* for your code since you only read if it is high, see if the button is connected to 5 V and pin 2 or 3 whichever one you use

You can try adding a resistor between your I/O pin and the ground.

Another test I prefer to do is:

Take a working jumper cable, test it with a voltmeter, or see if you can make an LED light up when connected to it (use the Arduino 5 V, ground and a resistor for this (resistor to not let your LED explode like that zeppelin).

With the working jumper cable or breadboard cable, connect one end to the pin you plan to use. Then run the program and connect the other end to ground, then 5 V, and then ground and so forth to see if it responds well.

This is based on an Arduino Uno. If you use another type of Arduino, make sure to use the proper voltage pin. You can always add a resistor between the wire and the Arduino for extra safety.

# Answer
> 3 votes
Here is what you can do

1. Check if the switch is connected to the defined input pin. The Arduino starts form pin 0 and sometimes we can misread while connecting.
2. Check if the serial monitor has same baud rate as defined in the program.
3. Check the voltages around switch using a multimeter.
4. Still not getting a solution? Attach a pull-down resistor.
5. Still not getting a solution? Invert the logic and current flow as suggested by JRobert.

# Answer
> 0 votes
Few things that can be checked and used.

1. If you are using a normal push button then check the connections properly as two of the pins are internally connected two each other. So we need 2 pins that are not connected so check it with DMM.
2. You need a Pull-UP or pull-Down resisters attached to the input pin.

The value of a resistor depends on your requirement like if you have long wires or more noise you need a strong pullup or pulldown resister like 1k. And the best way is to test it out first with an internal pull-up resistor which is considered a week pullup and Atmega328p has its value of around 20k. `pinMode(switchPin, INPUT_PULLUP);`
3. As TeD has stayed check that you are using the same digital pin in your hardware and code.
4. And last a simple counter type debouncing logic will help to denounce the button input signals. as shown in the below code.

```
#define switchPin 2
byte debounce_counter = 150;

void setup() {
  pinMode(switchPin, INPUT_PULLUP);
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(switchPin) == HIGH) {
    debounce_counter++;
  }
  else {
    debounce_counter--;
  }

  if (debounce_counter >= 240)
  {
    debounce_counter = 150;
    Serial.println("OFF");
  }
  else if (debounce_counter <= 60)
  {
    debounce_counter = 150;
    Serial.println("ON");
  }
}

```

You can also check other methods and libraries for debouncing the input signals which uses the millis function.

---
Tags: arduino-uno, input, resistor
---


title: pull-up or pull-down

text:
# Question
Title: pull-up or pull-down
Do you have to build the circuit on an external board every time you decide there is a need for a pull-up or pull-down circuit? If not, then what is the alternative and how can you use it?

# Answer
> 4 votes
This depends on what you are doing.

The IO hardware of the Uno (more specific the Atmega328p, which is the used chip) has internal pullup resistors, that can be used, when the pin is configured as input. This can be done in one line:

```
pinMode(pin_number, INPUT_PULLUP);

```

This is true for all AVR based chips.

Other, more complex and capable chips also have an internal pulldown resistor (as I remember this is true for the ESP32 for example). In this case you can do

```
pinMode(pin_number, INPUT_PULLDOWN);

```

If you are using special hardware of the Arduino, it depends on the hardware itself, since in most cases the normal IO hardware is internally not connected to the pin, when using this hardware. For example: The internal pullup resistor will not be active, when doing an analog measurement with the ADC (like via `analogRead()`).

---
Tags: arduino-uno, hardware
---


# Question
Title: DC motor with slow speed to actuate mirrors
I am thinking to use Arduino to control a DC motor and apply a small torque to move the mirrors of my interferometer experiment. I have the components from the Arduino Starter Kit K000007, just to understand how it works because I am approaching it just now.

The mirror mount has a knob with a 2mm Hex hole and each revolution corresponds to a displacement of 50 microns: I would need a speed around 1/50 revolution/second, or even less. Is it possible to move the motor that slow? Moreover, I should use a coupler to interface the motor with the knob, basically some joint to connect the shaft to a 2mm Hex bar or something: could you suggest a way to do so?

# Answer
> 0 votes
DC motors are made for spinning. Trying to spin it in sub full revolution steps is not really possible. But you can use a geared DC motor, where the rotor after the gear is slow enough for your purpose. Also this can give you enough torque for moving the knob (since small DC motors are often rather weak by their own). You can find geared DC motors with many different values (torque, voltage, speed, gear ratio, size...) at the typical online sellers. The small ones are rather cheap, so you might just buy some and test out, whats fitting for you. Otherwise you would need to set exact requirements for torque and speed (and maybe other parameters) and then search for a fitting one.

Also keep in mind, that you need something like a driver circuit for the motor. Since you will want to drive it in both directions, a H-bridge is needed. You can build those yourself with transistors, or buy a small chip, which incorporates the complete H-bridge (make sure to use one with MOSFETs in it, since they are more efficient). Also don't forget the flyback diode to avoid killing the electronics with the induction voltage from the motor.

> I should use a coupler to interface the motor with the knob, basically some joint to connect the shaft to a 2mm Hex bar or something: could you suggest a way to do so?

Yes, you need some kind of coupler. But we cannot really suggest something here. It depends totally on your exact setup. This mechanical part will be something, that you have to design. There are different kinds of couplers available online, but I don't know, if they are good for your purpose.

Also maybe you should make sure to make the coupler flexible on the other axes than the rotation axis. That way the motor will not stall when a small disalignment happens, and the vibrations from the motor might not get transmitted to your mirror as much. I know this principle from my 3D printer, which uses a coupler like this one:

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


# Question
Title: Neo 6m outputting something i as a noob can't understand
So i connected my ublox neo 6m gps breakout board GY-GPS6MV2 to the arduino software serial and got this result, i used resistors and only supplied 3.3v to the board, gps encode library couldn't give me anything out of this. if possible please help and if this is the wrong forum please suggest a better one. also the board thinks that the date for some reason is Mar 17 2011 16:18:34\*59. which is pretty wierd.

```

$GPTXT,01,01,02,HW UBX-G60xx 00040007 FFF9FFFFp*5D

$GPTXT,01,01,02,ROM CORE 7.03 (45969) Mar 17 2011 16:18:34*59

$GPTXT,01,01,02,ANTSUPERV=AC SD PDoS SR*20

$GPTXT,01,01,02,ANTSTATUS=DONTKNOW*33

$GPRMC,,V,,,,,,,,,,N*53

$GPVTG,,,,,,,,,N*3⸮$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$GPTXT,01,01,02,HW UBX-G60xx 00040007 FFF9FFFFp*5D

$GPTXT,01,01,02,ROM CORE 7.03 (45969) Mar 17 2011 16:18:34*59

$GPTXT,01,01,02,ANTSUPERV=AC SD PDoS SR*20

$GPTXT,01,01,02,ANTSTATUS=DONTKNOW*33

$GPRMC,,V,,,,,,,,,,N*53

$GPVTG,,,,,,,,,N*3⸮$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$⸮$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$GPTXT,01,01,02,HW UBX-G60xx 00040007 FFF9FFFFp*⸮$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$⸮$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$GPTXT,01,01,02,HW UBX-G60xx 00040007 F⸮$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$GPTXT,01,01,02,HW UBX-G60xx 00040007 FFF9FFFFp*5D

$GPTXT,01,01,02,ROM CORE 7.03 (45969) Mar 17 2011 16:18:34*59

$⸮$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

$GPTXT,01,01,02,HW UBX-G60xx 00040007 FFF9FFFFp*5D

$GPTXT,01,01,02,ROM CORE 7.03 (45969) Mar 17 2011 16:18:34*59

$GPTXT,01,01,02,ANTSUPERV=AC SD PDoS SR*20

$GPTXT,01,01,02,ANTSTATUS=DONTKNOW*33

$GPRMC,,V,,,,,,,,,,N*53

$GPVTG,,,,,,,,,N*30

$GPGGA,,,,,,0,00,99.99,,,,,,*48

$GPGSA,A,1,,,,,,,,,,,,,99.99,99.99,99.99*30

$GPGSV,1,1,00*79

$GPGLL,,,,,,V,N*64

$GPTXT,01,01,02,u-blox ag - www.u-blox.com*50

```

**Here is the full unedited output after 40 mins** https://drive.google.com/file/d/148W\_6shE0U2lprimApvtvG1i3Vf2-Izx/view?usp=sharing

edit:- i also connected the tx pin to the rx and vice versa and used a resistor as told by an tutorial on the tx pin from the arduino or the rx pin of the board. it is also sending many gptxt messages which some say on other forums are usally send when some error occurs or the board restarts. idk why it is coming on my board.

# Answer
> 2 votes
someone on ublox portal recommended me to connect the boards vcc to 5v's and when i did that, it stopped rebooting, and after 20 mins got a lock, thanks for your help.

the guy on ublox portal

> Post a photo of the board and a link of where you bought it so that we can point out that 5V is needed. The reboot symptom is usually caused by an inadequate voltage source --- when the 6m starts, current draw is low, when it finishes initial startup, it goes to work looking for sats and current draw jumps up. The higher current draw on a poor power source causes supply voltage to drop too.low which then causes the 6m to reset and restart and will happily repeat the cycle forever. Use a good DVM or oscilloscope to verify the inadequate voltage source.

after connecting the board to 5v supply the problem seemed to be fixed

---
Tags: arduino-uno, gps, eeprom, tinygps
---


# Question
Title: Arduino Uno with Sensor, Bluetooth Module and tftlcd
In code attached below I am using tftlcd display of 2.4 inch in which i want to show clock as home page, when user click on tftlcd screen then a screen appears which can show three options to user which are about the sensors user want to use. There are three sensors in this code: Pulse oximeter, glucose meter, pedometer. After choosing some option(sensor) the data of sensor will appear on screen. I have write code for all this procedure which is given below:

```
//include all libraries
#include <Wire.h>
#include <SPFD5408_Adafruit_GFX.h>
#include <SPFD5408_Adafruit_TFTLCD.h>
#include <SPFD5408_TouchScreen.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"

//Exit buttons
bool backsensed = false;
bool resetsensed = false;

//Include Max30102 lib
MAX30105 particleSensor;

//Define LCD pins
#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin

//pedometer
const int xpin = A3;
const int ypin = A4;
const int zpin = A5;
byte p[8] = {0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F,
  0x1F
};
float threshold = 100;
float xval[100] = {0};
float yval[100] = {0};
float zval[100] = {0};
float xavg, yavg, zavg;
int steps, flag = 0;
//pulseoxi
#define MAX_BRIGHTNESS 255
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
uint16_t irBuffer[100]; //infrared LED sensor data
uint16_t redBuffer[100];  //red LED sensor data
#else
uint32_t irBuffer[100]; //infrared LED sensor data
uint32_t redBuffer[100];  //red LED sensor data
#endif
int32_t bufferLength; //data length
int32_t spo2; //SPO2 value
int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
int32_t heartRate; //heart rate value
int8_t validHeartRate; //indicator to show if the heart rate calculation is valid
byte pulseLED = 11; //Must be on PWM pin
byte readLED = 13; //Blinks with each data read

// LCD Calibrate values
#define TS_MINX 100
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

// For better pressure precision, we need to know the resistance between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

int BLUE = tft.color565(50, 50, 255);
#define TFT_BLACK   0x0000
#define TFT_DARKBLUE 0x0010
#define VIOLET 0x8888
#define TFT_RED     0xF800
#define TFT_GREEN   0x07E0
#define TFT_CYAN    0x07FF
#define TFT_MAGENTA 0xF81F
#define TFT_YELLOW  0xFFE0
#define TFT_WHITE   0xFFFF
#define TFT_GREY    0x5AEB
#define TFT_BLUE    0x001F
#define GOLD 0xFEA0
#define BROWN 0xA145
#define SILVER 0xC618
#define LIME 0x07E0
#define BLUE  0x001F

//button screen
int currentpcolour;
int currentpage;
bool running;

//Minimum and maximum pressure to sense the touch
#define MINPRESSURE 10
#define MAXPRESSURE 1000

//clock
float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0;
float sdeg = 0, mdeg = 0, hdeg = 0;
uint16_t osx = 120, osy = 120, omx = 120, omy = 120, ohx = 120, ohy = 120;
int16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0, x00 = 0, yy00 = 0;
uint32_t targetTime = 0;
uint16_t xpos;
uint8_t conv2d(const char* p) {
  uint8_t v = 0;
  if ('0' <= *p && *p <= '9')
    v = *p - '0';
  return 10 * v + *++p - '0';
}
uint8_t hh = conv2d(__TIME__), mm = conv2d(__TIME__ + 3), ss = conv2d(__TIME__ + 6);
boolean initial = 1;
char d;

//for buttons
void drawHome()
{
  tft.fillScreen(TFT_BLACK);
  tft.drawRoundRect(0, 0, 319, 240, 8, TFT_YELLOW);     //Page border

  tft.fillRoundRect(60, 180, 200, 40, 8, TFT_DARKBLUE);
  tft.drawRoundRect(60, 180, 200, 40, 8, TFT_YELLOW);  //PEDO

  tft.fillRoundRect(60, 130, 200, 40, 8, TFT_DARKBLUE);   //Glu
  tft.drawRoundRect(60, 130, 200, 40, 8, TFT_YELLOW);

  tft.fillRoundRect(60, 80, 200, 40, 8, TFT_DARKBLUE);
  tft.drawRoundRect(60, 80, 200, 40, 8, TFT_YELLOW); //Pulse oxi and heart rate

  tft.setCursor(25, 20);
  tft.setTextSize(3);
  tft.setTextColor(TFT_WHITE);
  tft.print("Welcome Here..");
  tft.setCursor(25, 50);
  tft.setTextSize(2);
  tft.setTextColor(TFT_YELLOW);
  tft.print("Choose Your Sensor");
  tft.setTextColor(TFT_WHITE);
  tft.setCursor(110, 195);
  tft.print("Pedometer");

  tft.setCursor(80, 145);
  tft.print("Glucose Sensor");

  tft.setCursor(80, 95);
  tft.print("Pulse Oximeter");
  //  delay(500);

  }

  void setup()
{
  tft.reset();
  tft.begin(0x9341);
  tft.setRotation(1);
  currentpage = 0; //clock page
  tft.setTextColor(TFT_WHITE);// text color
  tft.fillScreen(TFT_BLACK);// background color

  xpos = tft.width() / 2;
  tft.drawCircle(xpos, 120, 125, TFT_YELLOW);
  tft.fillCircle(xpos, 120, 118, TFT_BLUE);
  tft.fillCircle(xpos, 120, 110, TFT_BLACK);
  for (int a=95; a<104; a++){
  tft.drawCircle(xpos, 120, a, TFT_WHITE);}

  for (int i = 0; i < 360; i += 30) {
    sx = cos((i - 90) * 0.0174532925);
    sy = sin((i - 90) * 0.0174532925);
    x0 = sx * 114 + xpos;
    yy0 = sy * 114 + 120;
    x1 = sx * 100 + xpos;
    yy1 = sy * 100 + 120;
    tft.drawLine(x0, yy0, x1, yy1, TFT_YELLOW);
  }
  for (int i = 0; i < 360; i += 6) {
    sx = cos((i - 90) * 0.0174532925);
    sy = sin((i - 90) * 0.0174532925);
    x0 = sx * 102 + xpos;
    yy0 = sy * 102 + 120;
    x00 = sx * 92 + xpos;
    yy00 = sy * 92 + 120;
    // Draw minute markers
    tft.drawPixel(x0, yy0, TFT_GREEN);
    tft.drawLine(x0, yy0, x00, yy00, TFT_BLACK);
    tft.drawLine(x0+1, yy0+1, x00+1, yy00+1, TFT_BLACK);
    // Draw main quadrant dots
    if (i == 0 || i == 180) tft.fillCircle(x0, yy0, 2, TFT_WHITE);
    if (i == 90 || i == 270) tft.fillCircle(x0, yy0, 2, TFT_WHITE);
  }
  tft.fillCircle(xpos, 121, 3, TFT_WHITE);
  targetTime = millis() + 1000;
  //touch event
  tft.setCursor (80, 250);
  tft.setTextSize (1);
  tft.setTextColor(TFT_BLACK);
  tft.println("Touch to proceed");
  waitOneTouch(); // Wait touch
  drawHome(); //buttons screeen
}

void loop(){
  if (currentpage == 0){
  if (targetTime < millis()) {             //clock code
    targetTime = millis() + 1000;
    ss++;
    if (ss == 60) {
      ss = 0;
      mm++;
      if (mm > 59) {
        mm = 0;
        hh++;
        if (hh > 23) {
          hh = 0;
        }
      }
    }
    sdeg = ss * 6;                     // 0-59 -> 0-354
    mdeg = mm * 6 + sdeg * 0.01666667; // 0-59 -> 0-360 - includes seconds, but these increments are not used
    hdeg = hh * 30 + mdeg * 0.0833333; // 0-11 -> 0-360 - includes minutes and seconds, but these increments are not used
    hx = cos((hdeg - 90) * 0.0174532925);
    hy = sin((hdeg - 90) * 0.0174532925);
    mx = cos((mdeg - 90) * 0.0174532925);
    my = sin((mdeg - 90) * 0.0174532925);
    sx = cos((sdeg - 90) * 0.0174532925);
    sy = sin((sdeg - 90) * 0.0174532925);
    if (ss == 0 || initial) {
      initial = 0;
      // Erase hour and minute hand positions every minute
      tft.drawLine(ohx, ohy, xpos, 121, TFT_BLACK);
      ohx = hx * 62 + xpos + 1;
      ohy = hy * 62 + 121;
      tft.drawLine(omx, omy, xpos, 121, TFT_BLACK);
      omx = mx * 84 + xpos;
      omy = my * 84 + 121;
    }
    // Redraw new hand positions, hour and minute hands not erased here to avoid flicker
    tft.drawLine(osx, osy, xpos, 121, TFT_BLACK);
    osx = sx * 90 + xpos + 1;
    osy = sy * 90 + 121;
    tft.drawLine(osx, osy, xpos, 121, TFT_RED);
    tft.drawLine(ohx, ohy, xpos, 121, TFT_CYAN);
    tft.drawLine(omx, omy, xpos, 121, TFT_WHITE);
    tft.drawLine(osx, osy, xpos, 121, TFT_RED);
    tft.fillCircle(xpos, 121, 3, TFT_RED);
    tft.setCursor(xpos-30, 50);
    tft.setTextSize(2);
    tft.print("Glucoxy");

  // Draw MINI clock face "SECOND"
  tft.drawCircle(xpos, 155, 20, TFT_YELLOW);
  tft.drawCircle(xpos, 155, 18, TFT_BLUE);
  tft.drawCircle(xpos, 155, 17, TFT_CYAN);
  tft.drawCircle(xpos, 155, 16, TFT_CYAN);
  tft.fillRect(xpos-10, 149,22,15,TFT_BLACK); //erase
  if(ss<10){tft.setCursor(xpos-10, 149); tft.setTextSize(2);
  tft.print('0'); tft.setCursor(xpos+2, 149);}
  else{
  tft.setCursor(xpos-10, 149);}
  tft.setTextSize(2);
  tft.print(ss);
  // Draw MINI clock face "Minutes"
  tft.drawCircle(xpos+35, 117, 20, TFT_YELLOW);
  tft.drawCircle(xpos+35, 117, 18, TFT_BLUE);
  tft.drawCircle(xpos+35, 117, 17, TFT_CYAN);
  tft.drawCircle(xpos+35, 117, 16, TFT_CYAN);
 tft.fillRect(xpos+25, 111,22,15,TFT_BLACK); //erase
  if(mm<10){tft.setCursor(xpos+25, 111); tft.setTextSize(2);
  tft.print('0'); tft.setCursor(xpos+37, 111);}
  else{
  tft.setCursor(xpos+25, 111);}
  tft.println(mm);
  // Draw MINI clock face "Hour"
  tft.drawCircle(xpos-35, 117, 20, TFT_YELLOW);
  tft.drawCircle(xpos-35, 117, 18, TFT_BLUE);
  tft.drawCircle(xpos-35, 117, 17, TFT_CYAN);
  tft.drawCircle(xpos-35, 117, 16, TFT_CYAN);
  tft.fillRect(xpos-45, 111,22,15,TFT_BLACK); //erase
  if(hh<10){tft.setCursor(xpos-45, 111); tft.setTextSize(2);
  tft.print('0'); tft.setCursor(xpos-33, 111);}
  else{
  tft.setCursor(xpos-45, 111);}
  tft.setTextSize(2);
  tft.print(hh);
  //tft.setCursor(xpos-65, 111);
  //tft.println(':');
  if (hh>=0 && hh<12) d='A'; else {d='P';}
  tft.drawRoundRect(xpos-14,72,29,21,5,TFT_CYAN);
  tft.fillRect(xpos-11, 75,23,15,TFT_BLACK); //erase
  tft.setCursor(xpos-11, 75);
  tft.setTextSize(2);
  tft.print(d);
  tft.println('M');
  }
  }
  //home page
  if (currentpage == 1){
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();     // Read touchscreen
  digitalWrite(13, LOW);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  {if (p.z > 10 && p.z < 1000)
    {
      if (p.x > 736 && p.x < 855 && p.y > 255 && p.y < 725  && p.z > MINPRESSURE && p.z < MAXPRESSURE)
      {
        Serial.println("Pedometer");
        tft.fillRoundRect(60, 180, 200, 40, 8, TFT_WHITE);
        delay(70);
        tft.fillRoundRect(60, 180, 200, 40, 8, TFT_WHITE);
        tft.drawRoundRect(60, 180, 200, 40, 8, TFT_YELLOW);
        tft.setCursor(65, 195);
        tft.println("  Pedometer");
        delay(70);
        currentpage = 2;
        startPedo();
      }
      else if (p.x > 563 && p.x < 683 && p.y > 275 && p.y < 750)
      {
        Serial.println("Glucose Sensor");

        tft.fillRoundRect(60, 130, 200, 40, 8, TFT_WHITE);   //rgb led
        delay(70);
        tft.fillRoundRect(60, 130, 200, 40, 8, TFT_WHITE);   //rgb led
        tft.drawRoundRect(60, 130, 200, 40, 8, TFT_YELLOW);   //rgb led
        tft.setCursor(105, 145);
        tft.print("Glucose Sensor");
        delay(70);
        currentpage = 3;
        startGlu();
      }
      if (p.x > 403 && p.x < 525 && p.y > 271 && p.y < 725)
      {
        Serial.println("Pulse Oximeter");
        currentpage = 4;
        tft.fillRoundRect(60, 80, 200, 40, 8, TFT_WHITE);
        delay(70);
        tft.fillRoundRect(60, 80, 200, 40, 8, TFT_WHITE);
        tft.drawRoundRect(60, 80, 200, 40, 8, TFT_YELLOW);
        tft.setCursor(80, 95);
        tft.print("Pulse Oximeter");
        delay(70);
       // startPulse();

      }
    }
  }
  if (currentpage == 2) //pedo
  {
    senseBack();
    if (backsensed)
    {
      currentpage = 1;
      drawHome();
    }
    sensereset();
    calibrate();
  }
  if (currentpage == 3) // glucose
  {
     senseBack();
     if (backsensed)
     {
      currentpage = 0;
      drawHome();
     }
    sensereset();
  }

  if (currentpage == 4)  //pulse oxi
  {
    senseBack();
     if (backsensed)
     {
      currentpage = 1;
      drawHome();
     }
    sensereset();
    pinMode(pulseLED, OUTPUT);
  pinMode(readLED, OUTPUT);
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed  // Initialize sensor
  {
    Serial.println(F("MAX30105 was not found. Please check wiring/power."));
    while (1);
  }
  Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
  while (Serial.available() == 0) ; //wait until user presses a key
  Serial.read();
  byte ledBrightness = 60; //Options: 0=Off to 255=50mA
  byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
  byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
  byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int pulseWidth = 411; //Options: 69, 118, 215, 411
  int adcRange = 4096; //Options: 2048, 4096, 8192, 16384
  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
  startPulse();
  }
}

}
// Wait one touch
TSPoint waitOneTouch() {
  TSPoint p;
  do {
    p= ts.getPoint();
    pinMode(XM, OUTPUT); //Pins configures again for TFT control
    pinMode(YP, OUTPUT);
  } while((p.z < MINPRESSURE )|| (p.z > MAXPRESSURE));
  return p;
}
void sensereset()
{
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();     // Read touchscreen
  digitalWrite(13, LOW);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  if (p.x < 199 && p.y < 293 && !running)
    resetsensed = true;
  else
    resetsensed = false;
}
void startPedo()        //-------------------pedometer function--------------------------
{
  int acc = 0;
  float totvect[100] = {0};
  float totave[100] = {0};
  float xaccl[100] = {0};
  float yaccl[100] = {0};
  float zaccl[100] = {0};
  for (int a = 0; a < 100; a++)
  {
    xaccl[a] = float(analogRead(xpin) - 345);
    delay(1);
    yaccl[a] = float(analogRead(ypin) - 346);
    delay(1);
    zaccl[a] = float(analogRead(zpin) - 416);
    delay(1);
    totvect[a] = sqrt(((xaccl[a] - xavg) * (xaccl[a] - xavg)) + ((yaccl[a] - yavg) * (yaccl[a] - yavg)) + ((zval[a] - zavg) * (zval[a] - zavg)));
    totave[a] = (totvect[a] + totvect[a - 1]) / 2 ;
    Serial.println("totave[a]");
    Serial.println(totave[a]);
    delay(100);
    if (totave[a] > threshold && flag == 0)
    {
      steps = steps + 1;
      flag = 1;
    }
    else if (totave[a] > threshold && flag == 1)
    {
      // Don't Count
    }
    if (totave[a] < threshold   && flag == 1)
    {
      flag = 0;
    }
    if (steps < 0) {
      steps = 0;
    }
    Serial.println('\n');
    Serial.print("steps: ");
    Serial.println(steps);
    delay(1000);
  }
  delay(1000);
  //print results on lcd
  tft.setCursor(130, 145);
  tft.setTextSize(3);
  tft.setTextColor(TFT_WHITE);
  tft.print(steps);

  }
void calibrate()            //<----------------------calibrate funtion--------------------->
{
  float sum = 0;
  float sum1 = 0;
  float sum2 = 0;
  for (int i = 0; i < 100; i++) {
    xval[i] = float(analogRead(xpin) - 345);
    sum = xval[i] + sum;
  }
  delay(100);
  xavg = sum / 100.0;
  Serial.println(xavg);
  for (int j = 0; j < 100; j++)
  {
    yval[j] = float(analogRead(ypin) - 346);
    sum1 = yval[j] + sum1;
  }
  yavg = sum1 / 100.0;
  Serial.println(yavg);
  delay(100);
  for (int q = 0; q < 100; q++)
  {
    zval[q] = float(analogRead(zpin) - 416);
    sum2 = zval[q] + sum2;
  }
  zavg = sum2 / 100.0;
  delay(100);
  Serial.println(zavg);
}
void senseBack()
{
  digitalWrite(13, HIGH);
  TSPoint p = ts.getPoint();     // Read touchscreen
  digitalWrite(13, LOW);

  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  if (p.y < 305 && p.x < 285 && p.x > 239 && !running)
  {
    backsensed = true;

  }
  else
    backsensed = false;
}
void startGlu()                 //-------------------------------startGlu-------------------------
{
  }
void startPulse()             //--------------------------------startpulse-----------------------
{
  bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps

  //read the first 100 samples, and determine the signal range
  for (byte i = 0 ; i < bufferLength ; i++)
  {
    while (particleSensor.available() == false) //do we have new data?
      particleSensor.check(); //Check the sensor for new data
    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample(); //We're finished with this sample so move to next sample
    Serial.print(F("red="));
    Serial.print(redBuffer[i], DEC);
    Serial.print(F(", ir="));
    Serial.println(irBuffer[i], DEC);
  }
  //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
  maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
  //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
  while (1)
  {
    //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
    for (byte i = 25; i < 100; i++)
    {
      redBuffer[i - 25] = redBuffer[i];
      irBuffer[i - 25] = irBuffer[i];
    }
    //take 25 sets of samples before calculating the heart rate.
    for (byte i = 75; i < 100; i++)
    {
      while (particleSensor.available() == false) //do we have new data?
        particleSensor.check(); //Check the sensor for new data
      digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read
      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample(); //We're finished with this sample so move to next sample
      //send samples and calculation result to terminal program through UART
      Serial.print(F("red="));
      Serial.print(redBuffer[i], DEC);
      Serial.print(F(", ir="));
      Serial.print(irBuffer[i], DEC);
      Serial.print(F(", HR="));
      Serial.print(heartRate, DEC);
      Serial.print(F(", HRvalid="));
      Serial.print(validHeartRate, DEC);
      Serial.print(F(", SPO2="));
      Serial.print(spo2, DEC);
      Serial.print(F(", SPO2Valid="));
      Serial.println(validSPO2, DEC);
    }

    //After gathering 25 new samples recalculate HR and SP02
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
    //print results on lcd
    tft.setCursor(130,145);
  tft.setTextSize(3);
  tft.setTextColor(TFT_WHITE);
  tft.print(heartRate);

  }

}

```

Please see above code whether it works perfect as i want. I am getting error when i try to compile this code which is given below

My questions are:

1. whether this code is right, if not then point out my mistakes.
2. Solution of error shown in image.

# Answer
> 1 votes
The Arduino Uno doesn't have enough SRAM, the current Rev3 has just 2 KB. You can circumvent that by using less variables, use `#define xpin` instead of `const int`, etc. Here is an article about how to reduce memory usage, give it a try.
Another option is to use a different Microcontroller with more SRAM, with at least 3KB like a Arduino Mega, ESP32. But first try to optimize your program, if you don't have another unused board lying around anyway.
**EDIT:**
You might also take a look at the header files if you can optimize anything there.

# Answer
> 1 votes
Arduino Mega has **8192 bytes** of SRAM which will solve your problem.

Reduce the RAM usage (ref)

# Answer
> -1 votes
Look at this post, where I have implement the clock using a tft touch-enabled screen, with touch-enabled choice boxes for setting the time. I used a Teensy 3.2, which handles the memory requirements nicely. From the compile report

```
Compiling 'Teensy_LCDClockV4' for 'Teensy 3.2 / 3.1'
Using previously compiled file: C:\Users\Frank\AppData\Local\Temp\VMBuilds\Teensy_LCDClockV4\teensy31\Release\pch\Arduino.h.gch
Program size: 117,320 bytes (used 45% of a 262,144 byte maximum) (4.14 secs)
Minimum Memory Usage: 5936 bytes (9% of a 65536 byte maximum)

```

So you might have some trouble fitting it into a typical Arduino board

---
Tags: arduino-uno, sensors, memory-usage
---


title: 4 Digit 7 segment display flickering

text:
# Question
Title: 4 Digit 7 segment display flickering
I am attempting to make an Arduino counter using a 4 digit 7 segment display. The problem I am encountering is the display flickers. I am using an Arduino Uno and 5641AS digit display (so common cathode). Here is my program:

```
#include "SevSeg.h"
SevSeg sevseg;

int buttonPress{}; // Variable used in Serial monitor, simulates button press to increment counter
void setup(){
  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = true;

  bool updateWithDelays = false;
  byte hardwareConfig = COMMON_CATHODE;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(90);
  Serial.begin(9600);
  sevseg.setNumber(0);
  sevseg.refreshDisplay();
}
void loop(){
  static int number = 0;

  if (Serial.available() > 0) { // Serial monitor input for buttonPress
    buttonPress = Serial.read();
  }
    Serial.println("The value of buttonPress is:  ");
    Serial.println(buttonPress);
    if (buttonPress == 10){ // Increment counter if buttonPress Serial monitor input = 10
    number += 15;
    buttonPress = 0;
    sevseg.setNumber(number); // Display the number on 4 digit 7 segment display
    }

    sevseg.refreshDisplay(); // Refresh display
}

```

I suspect this issue has to do with `sevseg.refreshDisplay()`, I have tried moving it in the program with no avail. My wiring is correct, as the program displays the correct digits. Thank you!

# Answer
With the help of Majenko and jsotola in the comments, I've got it fixed! It was the text I was displaying in the Serial Monitor that was slowing the display down. Here is the updated program that works:

```
#include "SevSeg.h"
SevSeg sevseg;

int buttonPress{}; // Variable used in Serial monitor, simulates button press to increment counter
void setup(){
  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = true;

  bool updateWithDelays = false;
  byte hardwareConfig = COMMON_CATHODE;
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
  sevseg.setBrightness(90);
  Serial.begin(9600);
  sevseg.setNumber(0);
  sevseg.refreshDisplay();
}
void loop(){
  static int number = 0;

  if (Serial.available() > 0) { // Serial monitor input for buttonPress
    buttonPress = Serial.read();
  }
// THE NEXT TWO LINES HAVE BEEN COMMENTED OUT FOR IT TO WORK
   // Serial.println("The value of buttonPress is:  ");
   // Serial.println(buttonPress);
    if (buttonPress == 10){ // Increment counter if buttonPress Serial monitor input = 10
    number += 15;
    buttonPress = 0;
    sevseg.setNumber(number); // Display the number on 4 digit 7 segment display
    }

    sevseg.refreshDisplay(); // Refresh display
}

```

I'm leaving the program modifications here in case anyone else gets the same problem.
> 2 votes

---
Tags: display, 7-segment
---