title: RAM cost of entering functions

text:
# Question
Title: RAM cost of entering functions
A friend has told me I shouldn't rely on functions because, during execution, they occupy a significant amount of RAM.

Is that true or, if it isn't, what's the maximum suggested level of function nesting at runtime?

# Answer
> 2 votes
> A friend has told me I shouldn't rely on functions because, during execution, they occupy a significant amount of RAM.

I wouldn't say "significant", but *some* RAM is used, yes.

Every time a function is called any registers used in the execution of that function are placed onto the stack. Also some parameters to the function may be passed on the stack (depending on the ABI for the architecture you're using). Further, any local variables used inside the function also go on the stack.

These are only temporary allocations and are released again when the function exits.

Depending on your program the "call stack" can be insignificant compared to the local variables.

> what's the maximum suggested level of function nesting at runtime?

Low enough that you don't run out of memory. When you have plenty of memory then your call stack is irrelevant. When you only have a couple of hundred bytes, or a hardware stack (like on the low-end PIC microcontrollers) with a limited depth, then keeping your program flatter can be better.

The main reason for flattening a program is usually for execution speed rather than for memory use.

# Answer
> 2 votes
I guess avoiding functions may have been relevant with dumb compilers, a few decades ago. Compilers today are pretty good at optimizing and, since recently, the Arduino environment enables “link time optimization”. This means the optimizer can see the whole program at once, which enables:

* function inlining across compilation units (and the optimizer does this pretty aggressively)
* saving, in the function prologue, only the registers that really need to be saved.

In most cases, the “optimal” size for a function is whatever size optimizes the readability of the code. In the rare cases where you would need to merge a function into its callers for performance purposes, you can qualify the function as

```
inline __attribute__((always_inline))

```

But this only makes sense after you disassembled the program and noticed the compiler did not make the right optimization choices. A quite infrequent situation.

---
Tags: programming, memory-usage, sram
---


title: When are global constuctors executed?

text:
# Question
Title: When are global constuctors executed?
Apologies if this has been discussed before but I couldn't find anything.

I have written a simple LED class. For illustration (it is actually a bit more complex) but it goes something like;

```
class LED {
    LED(byte pin);
  private:
    int _pin;
};

```

And the constructor is simply;

```
LED::LED(byte pin) {
    _pin = pin;
};

```

and I create a global instance of this class at the top of my code thus;

```
LED redLED(5);

```

It is necessary to create this as a global object because (a) I can't create the object in the setup() function because it would go out of scope and (b) I can't create in the loop() function because I don't want to create an infinite number of these objects.

This all seems to work OK but it just leaves me wondering exactly when this constructor gets executed? I suppose that it must be before setup()?

Answered!

Many thanks to all the respondents. So when using the Arduino IDE the build process must silently insert the main() procedure. I was not aware that it did this. I guess that *most* of the time you can get away with not knowing when the global constructors are called.

It is good practice (I think) to create a "wrapper" class for all/any external (or perhaps internal) hardware devices that are connected to your arduino. And it is thus perhaps tempting (but risky) to do initialisation work in the constructor.

So given what I now know, it is better to create an "init()" method for such classes that can be called from setup(). Even if just to do the the pinmode() call.

Thanks again.

# Answer
The global constructors run right after the initializations performed by the C runtime startup code, and right before `main()` gets called.

In a nutshell, the C runtime initialization code:

* does some low-level initializations (e.g., setup the memory)
* calls the global constructors
* calls `main()`, which in turn
    + calls `init()` to do the Arduino-specific initializations
    + calls `setup()`
    + repeatedly calls `loop()`

The fine details are probably platform-specific. For AVR-based boards, they are documented in the avr-libc manual.
> 2 votes

# Answer
It is executed before the `main()` is called (in the `main()` there is `setup()` called and then `loop()` is called in infinite loop).

It has its own sections for the constructors and destructors: http://beefchunk.com/documentation/sys-programming/binary\_formats/elf/elf\_from\_the\_programmers\_perspective/node4.html
> 0 votes

# Answer
```
class LED {
private:
  const byte _pin;
public:
  LED(const byte pin);
};

```

With an even simpler c'tor:

```
LED::LED(const byte pin) : _pin(pin) {};

```

To be a bit on-topic: The initializer list is even executed before the constructor body, and is thus the way to initialize constants.

Question remains whether it's guaranteed that this works:

```
class LED {
private:
  const byte _pin;
public;
  LED(const byte pin) : _pin(pin) {pinMode(_pin,OUTPUT);}
  set(bool state) {digitalWrite(_pin, state); }
};

```

( Can pinMode be called that early, or should one invent an init() method? )

My experience says : works well ...
> 0 votes

---
Tags: c++
---


# Question
Title: ESP32 light strips showing incorrect colours
I bought some individually addressable LED strips (a large reel). To keep the cost down they are WS2811 and it's one chip per 6 leds. I don't know the cheapness or LED styl makes any difference to the problem but I'm just putting it out there.

They support 24V so to be safe I'm running them at 23V. I have the data line hooked up to pin 13 of the ESP, and a ground connection to the power supply to create a common ground. I am using Alexa to control the colours. This is the code:

```
#include <WiFi.h>
#include <Espalexa.h>
#include <FastLED.h>
#include <Adafruit_NeoPixel.h>

FASTLED_USING_NAMESPACE

#define NUM_LEDS 120
#define LED_TYPE WS2811
#define LED_PIN 13
CRGB leds[NUM_LEDS];

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_RGB + NEO_KHZ400);

#define ESPALEXA_ASYNC
Espalexa espalexa;

#define RELAY_PIN 12

boolean connectWifi();

void colorLightChanged(uint8_t brightness, uint32_t rgb);

const char* ssid = "****";
const char* password = "****";
boolean wifiConnected = false;

void setup()
{
  Serial.begin(115200);
  delay(2000);

//  FastLED.addLeds<LED_TYPE, LED_PIN>(leds, NUM_LEDS);
//
  pinMode(LED_PIN, OUTPUT);
  pinMode(RELAY_PIN, OUTPUT);

  digitalWrite(RELAY_PIN, HIGH);
//
//  for (int i = 0; i < NUM_LEDS ; i++) {
//    leds[i] = CRGB(0, 0, 0);
//  }
//  FastLED.show();

  strip.begin();
  strip.show();

  wifiConnected = connectWifi();

  if(wifiConnected){
    espalexa.addDevice("Lights", colorLightChanged);

    espalexa.begin();

  } else
  {
    while (1) {
      Serial.println("Cannot connect to WiFi. Please check data and reset the ESP.");
      delay(2500);
    }
  }
}

void loop()
{
   espalexa.loop();
   delay(1);
}

void colorLightChanged(uint8_t brightness, uint32_t rgb) {
  for (int i = 0; i < NUM_LEDS; i++) {
//    leds[i] = CRGB((rgb >> 16) & 0xFF, (rgb >>  8) & 0xFF, rgb & 0xFF);
//    FastLED.setBrightness(brightness);
      strip.setPixelColor(i, (rgb >> 16) & 0xFF, (rgb >>  8) & 0xFF, rgb & 0xFF);
  }
//  FastLED.show();
    strip.show();

  if(brightness == 0) { //lights off
    digitalWrite(RELAY_PIN, LOW);
  }
  else { //lights on
    digitalWrite(RELAY_PIN, HIGH);
  }

//  Serial.print("Brightness: ");
//  Serial.print(brightness);
//  Serial.print(", Red: ");
//  Serial.print((rgb >> 16) & 0xFF); //get red component
//  Serial.print(", Green: ");
//  Serial.print((rgb >>  8) & 0xFF); //get green
//  Serial.print(", Blue: ");
//  Serial.println(rgb & 0xFF); //get blue
}

boolean connectWifi(){
  boolean state = true;
  int i = 0;

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");
  Serial.println("Connecting to WiFi");

  Serial.print("Connecting...");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    if (i > 40){
      state = false; break;
    }
    i++;
  }
  Serial.println("");
  if (state){
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  }
  else {
    Serial.println("Connection failed.");
  }
  return state;
}

```

I've tried both Neopixel and FastLED with the same outcomes. Those outcomes are totally wrong colours: This is supposed to be `cyan` except it's mostly yellow with a bit of blue.  This is supposed to be `purple`  And I think you get the idea. The lights strips light up with wrong colours (I've had whats supposed to be `gold`, be `purple`), blotches of colours or just make some look really similar (on Alexa, warm white to cool white look almost identical apart from a change in brightness).

I don't know what could be causing this though. I've made sure theres a common ground, I've made sure the pin on the ESP is right (i.e. just a plain output pin with no other fancy stuff), I've tried 2 different libraries and still no luck.

Could anyone help me out?

EDIT: These are these the strips I bought if it helps: https://www.superlightingled.com/65ft20m-roll-ws2811-dc24v-36ledsm-addressable-led-light-strips-digital-full-dream-color-chasing-flexible-led-strips-p-3163.html

# Answer
> 1 votes
That strip seems to be BGR instead or RGB.

Use `NEO_GRB` instead in your initializer. So:

```
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_BGR + NEO_KHZ400);

```

---
Tags: esp32, neopixel, led-strip
---


# Question
Title: Ignoring the first high output from the sensor
If the vibration sensor with Arduino detects two high inputs within 1 minute, I want the led to flash in one second.

My ability to write Arduino code is very low; I tried with `millis()` but I couldn't.

I want it to ignore the first high entrance.

Thank you for all the information you will give.

```
const byte sensor = 7;
const byte LED = 13;
unsigned long sensorMillis;
unsigned long ledTurnedOnAt;
unsigned long high_1 = 60000UL;
bool ledState = false;

void setup() {
  pinMode(sensor, INPUT);
  pinMode(13, OUTPUT);
}

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

  if (digitalRead(sensor) == HIGH) {
    sensorMillis = currentMillis;
    ledstate = true;
  }

  if (ledstate == HIGH) && ((unsigned long)(currentMillis - ledTurnedOnAt) <= high_1) {
    digitalWrite(8, HIGH);
    delay (1000);
    digitalWrite(8, LOW);
  }

  ledstate = false;
}

```

# Answer
One simple solution could be:

Start by noticing the first time you get the `HIGH` input whit a simple if statement:

```
if (digitalRead(sensor) == HIGH) {
}

```

where `sensor` is the pin of the sensor according to your code.

When this statement is `True`, you are interested in remain here until one of two things happens:

* either you interrupt some kind of loop with another `HIGH` input,
* or the time you have set is passed.

One way of knowing elapsed times will be with the `millis()` function, that returns the milliseconds since the board began running. We should get the elapsed time the first time we enter the loop:

```
if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
}

```

Then, as I have said, we need to remain here for a specific amount of time. We could use the `while` loop, but, which condition needs to be `true`?

So we have a start time, lets said `x` and you need to stay in the loop for, let's say, `y` milliseconds. This is the same as saying that you want to stay in the loop until the time we enter the loop and a specific amount of milliseconds, `x+y`. When the `millis()` function gives us a greater number, we should exit the loop:

```
if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
  while (millis() <= (startTime+1000))
//                              ^ The second you are interested, 1000 milliseconds.
}

```

Now, we have to check if there is another interrupt during this time, by using the same statement of the beginning:

```
if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
  while (millis() <= (startTime+1000)) {
    if (digitalRead(sensor) == HIGH) {
      // 2 interrupts in less than 1000 millis!
    }
  }
}

```

Summarizing is nicer to declare a global with the specific time we want, instead of the `1000` value we are using now:

```
const long maxTimeInterval = 1000;

```

And changing it in our code (that is inside the `loop()`)

```
if (digitalRead(sensor) == HIGH) {
  long startTime = millis();
  while (millis() <= (startTime+maxTimeInterval)) {
    if (digitalRead(sensor) == HIGH) {
      // 2 interrupts in less than 1000 millis!
      digitalWrite(LED, HIGH);
    }
  }
}

```

Hope this helps!
> 2 votes

# Answer
```
const int sensor = 7;
const int LED = 13;
unsigned long sensorMillis;
unsigned long ledTurnedOnAt;
unsigned long high_1 = 60000UL;
bool ledState = false;
void setup() {
  pinMode(sensor, INPUT);
  pinMode(LED, OUTPUT);
  delay(1000); //Warm up Time
}

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

  if (digitalRead(sensor) == HIGH) {
    sensorMillis = currentMillis;
    ledstate = true;
  }

  if (ledstate == HIGH) && ((unsigned long)(currentMillis - ledTurnedOnAt) <= high_1) {
    digitalWrite(8, HIGH);
    delay (1000);
    digitalWrite(8, HIGH);
  }

  ledstate = false;
}

```

I haven't checked this because I don't have my hardware. However, I added a delay of 1 second in the setup as a warm up time. This in theory should ignore the first high. Hope it helped.
> 1 votes

# Answer
Or what about adding another global boolean;

```
bool firstTime = true;

```

and then amend you loop() code as follows;

```
if (digitalRead(sensor) == HIGH) {
    if (firstTime) firstTime = false;
    else {
        sensorMillis = currentMillis;
        ledstate = true;
    }
  }

```
> 0 votes

---
Tags: sensors, led, millis
---


# Question
Title: Which Protocol to use to control WiFi (esp 32) enabled Led Light
I am developing a Wifi based Led light (for learning purpose). I have little knowledge about web server, clients, Web protocols. I will be using ESP32 as Controller cum WiFi module.

There are two ways to control Led light over WiFi.

Locally Remotely // as of now am focusing on locally

Android/iOS app will be handling all the control part (Flutter app)

Which protocols can I use to control Led light, locally? will set up multiple esp32 at that time its hard to control the device both devices will have different ip

Kindly help! if anyone give good example it would be helpful

# Answer
You can use your ESP as a server by the following code and then put your DigitalWrite(1, HIGH) line in the code like the following:

```
 String line = client.readStringUntil('\r');
 Serial.print(line);
if(line=="ledon")
{
DigitalWrite(1, HIGH);
}

```

and at this point you just can call the following link to turn the led on

```
http://192.168.*.**/ledon

```

or whatever the starting of your ipv4 is.
> 1 votes

---
Tags: arduino-uno, esp32, iot, home-automation
---


title: utf8 to hex macro

text:
# Question
Title: utf8 to hex macro
I would like to replace utf8 characters to byte values for easier character display handling. The actual replacement table comes from the lcd datasheet therefore it is not utf8 to ascii conversion. Hence I would like to define some macros, where I put the utf8 character, and it returns some matching hex code.

Here is the bare minimum code:

```
#define IV('┌') 0xC9
#define IV('°') 0xB2

char line0[4] = {0xC9, '4', 0xB2, 0}; // works
char line1[4] = {IV('┌'), '4', IV('°'), 0}; // do not work

void setup() {}
void loop() {}

```

It does not compile and I must be missing something obvious or rather basic. Any help is much appreciated.

# Answer
> 1 votes
```
#define IV('┌') 0xC9

```

That *really* isn't how macros work. What goes in the brackets is a named parameter that is then used in the body of the macro. You can't have multiple macros named the same like that.

The simplest thing to do is just make a set of macros named after what the character is. For example:

```
#define CHR_DEGREE 0xc9
#define CHR_BOX_TL 0xB2

char line1[4] = {CHR_BOX_TL, '4', CHR_DEGREE, 0};

```

# Answer
> 0 votes
After some googling I came up with this solution. I really hope someone finds a more elegant way to express it. These embedded ternary operators are really error prone.

```
#define IV(i) ( \
(i)=='┌' ? 0xc9 : \
(i)=='⎩' ? 0x15 : \
(i)=='⎭' ? 0x17 : \
(i)=='⎰' ? 0x18 : \
(i)=='°' ? 0xb2 : \
(i)=='™' ? 0xd0 : \
(i)=='Ξ' ? 0xd8 : \
(i) )

char line2[21] = {0x15, '_', 0xd8, '_', 0x17, 0xd0, '1', 0xc9, '5', 0x18, '5', '0', '0', 0xb2, ' ', ' ', ' ', ' ', ' ', 0}; //original
char line4[21] = {IV('⎩'), '_', IV('Ξ'), '_', IV('⎭'), IV('™'), '1', IV('┌'), '5', IV('⎰'), '5', '0', '0', IV('°'), ' ', ' ', ' ', ' ', ' ', 0}; //wanted

void setup() {}
void loop() {}

```

---
Tags: c++
---


title: How to set SPI speed for ATmega1284P?

text:
# Question
Title: How to set SPI speed for ATmega1284P?
I am using MightyCore and platformio. My config file looks like this

My fuses are set as:

```
E:FD
H:D6
L:8F

```

I have controller running at 16 MHz and SCK frequency is 8 MHz. My display is showing white color and that is it. I know to make it function properly I have to use 1 MHz SPI clocking. If I program CKDIV8 fuse my controller doesn't start. I dunno why, kind of black magic going on there for me. My lack of knowledge is not helpful there.

I tried to use the following tricks:

Setting SPI speed using TFT library

```
// earlier in main.cpp
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
// later in setup()
tft.setSPISpeed(1000000); // has no effect on SCK

```

Trying to set it directly via SPI class instance:

```
// in setup()
SPI.setClockDivider(SPI_CLOCK_DIV128); // no effect

```

Or statically:

```
// in setup()
SPIClass::setClockDivider(SPI_CLOCK_DIV128); // still no effect

```

Also I tried to pass `DEFAULT_SPI_FREQ` build flag with frequency preset.

I ran out of ideas.

Schematic is here:

# Answer
Per this issue setSPISpeed has to be made after initR like this:

```
tft.initR(INITR_BLACKTAB);
tft.setSPISpeed(1000000);

```
> 1 votes

---
Tags: spi
---


# Question
Title: Returning struct from function generates 'does not name a type' compilation error
I have a `main.ino` file that contains

```
struct EulerAngles {
  double roll, pitch, yaw;
};

void setup() {
  EulerAngles angles;
  angles = anglesCalc();
  Serial.print(angles.yaw);
}

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

```

and an `angles.ino` file that contains

```
EulerAngles anglesCalc(){
   EulerAngles a;
   // calculate a
   return a;
}

```

When I compile the program, I get a compile error in the `main.ino` file:

```
   code/so_examples/main.ino:5:1: error: 'EulerAngles' does not name a type
 void setup() {
 ^~~~~~~~~~~
code/so_examples/main.ino: In function 'void setup()':
code/so_examples/main.ino:7:12: error: 'anglesCalc' was not declared in this scope
   angles = anglesCalc();
            ^~~~~~~~~~
code/so_examples/main.ino:7:12: note: suggested alternative: 'angles'
   angles = anglesCalc();
            ^~~~~~~~~~
            angles
[Build] Error occurred.

```

How do I fix this? Note that struct is declared before all else, so this answer does not seem to apply. I am using the Stino plugin for Sublime Text as the IDE.

# Answer
There is an open issue with the Stino Arduino plugin for Sublime Text which means that structs are not handled properly.

Thank you to Jura and Edgar Bonet for helping me to answer this question.
> 1 votes

# Answer
I would avoid having multiple .ino files, because of the issues raised in the other answers. If you want to split your code into multiple files, the scheme that works reliably is to have:

* a single .ino file, named like the containing folder, holding the “main” program (this is Arduino-specific)
* a pair of .h/.cpp files for each “module” implementing a sub-feature of the program (this is common C++ practice).

Within the .h/.cpp pair, the .h file *declares* everything the compiler needs for understanding code that *uses* the feature: type definitions (including classes) and function prototypes. The .cpp file holds the actual implementation.

Applying this scheme to your case would give:

`my-sketch.ino` (actually, with the name of the containing folder):

```
#include "angles.h"

void setup() {
  EulerAngles angles;
  angles = anglesCalc();
  Serial.print(angles.yaw);
}

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

```

`angles.h`:

```
struct EulerAngles {
  double roll, pitch, yaw;
};

EulerAngles anglesCalc();

```

`angles.cpp`:

```
#include <Arduino.h>
#include "angles.h"

EulerAngles anglesCalc() {
   EulerAngles a;
   // calculate a
   return a;
}

```

Note that including `<Arduino.h>` is only useful if the code uses the Arduino core API. Otherwise you can omit it. The main sketch does not need to include `<Arduino.h>` because it is implicitly included in the .ino file by the Arduino IDE. There is no such implicit inclusion when the IDE processes .cpp files.
> 0 votes

# Answer
Try to add `struct` at the first of function, such as:

```
struct EulerAngles anglesCalc(){
   EulerAngles a;
   // calculate a
   return a;
}

```
> -1 votes

---
Tags: c++, compilation-errors
---


# Question
Title: Replacing the IC (atmega328) if lifespan has been arrive
Consider if the lifespan of atmega328 has been wear out.

It said on datasheet of atmega how many times we can upload sketch about 10.000times (cmiiw), should i change the arduino or only the microcontroller after 10.000 times have been arrive? what if that times has been arrive? What happened with that IC? If it will starting problem, can we change only the microcontroller (atmega328PU)?? Or any there's thing or stuff we must change too?

Should i burn the bootloader to that IC after replace it?

# Answer
You only need to change the IC, not the entire board. The microcontroller IS the IC.

Also, you will not see any degradation, it will just 'suddenly' fail, or starting to fail sometimes, without any warning or counter that counts up/down to 10,000.

Also keep in mind that this number is the MINIMUM guaranteed value, most ICs will go much further.

The best way to prevent getting into problems related with this issue is:

* When you have a finished project and it works, just keep that IC for that project.
* In case you fear getting into this problem during development, only change it if you are sure you have problems (i.e. you cannot upload your sketch anymore).
* Think before uploading 100 times per day a sketch for debugging purposes (add `Serial.print` lines, or even better, use a PC to debug all non Arduino related code.
> 3 votes

---
Tags: atmega328, uploading
---


# Question
Title: Is it possible for Arduino as ISP board to flash an ISP master board?
I have a setup of 2 Arduino Leonardo boards. Let's refer to them as Board A and Board B.

Board A is a master SPI board that is constantly communicating via SPI to an array of sensors. At some point, board A will need to be flashed with a new sketch. That's where Board B comes in.

I want to use Board B go use an Arduino as ISP sketch to go and flash a new sketch onto board A. Problem is that Arduino as ISP uses SPI, which conflicts with the code on board B since board B is a master device communicating to other sensors via SPI.

Is it possible for board B to flash board A via ISP?

# Answer
Yes, you can flash an MCU using ISP even if the MCU acts as an SPI device (be it master or slave). The programmer puts the MCU into reset mode, so at the time the sketch is uploaded, SPI will be disabled anyway. Another thing you need to think of are the other SPI devices (the sensors or what ever the MCU controls). They can pick up the SPI signals sent by the programmer and occasionally write on the bus themselves, therefore disturb communication on the MISO line, which would be critical. There are two options to handle this:

1. Simply disconnect any SPI slaves during code upload
2. Make sure there are pullups on the CS lines so they have a defined state (they might be floating while the MCU is in reset). Some slaves might require pulldowns to be deactivated, but that's uncommon.
> 2 votes

---
Tags: spi, isp, icsp
---


# Question
Title: Extend program space by getting rid of bootloader on NANO
I just have a complex program that runs on a NANO. Now when I use my printlns for debugging I am running out of memory.

I read about using a programmer to get rid of the bootloader that uses 2K space on a NANO. I bought an USBTinyIsp and got it to work successfully... almost I can program the nano as I wanted, but I do not get any additional space.

When programming with debug printlns I run into the same message as before which states the same maximum space within (I guess it was 30700).

Why is this the case? I thought the bootloader gets overridden when using a programmer and so frees 2K of programmable space.

Please note: I am not asking how to optimize my program code! Thank you for taking notice ;)

Thank you very much.

# Answer
It's enforcing this line from the arduino:avr boards.txt

```
nano.menu.cpu.atmega328.upload.maximum_size=30720

```

To be clear, the board is assumed to have a bootloader, even if you're not using it to get the code onto the board, that is upload via programmer.

You could edit that and change some fuses yourself. But you could also probably just use MCUdude MiniCore, choosing an option that does not use a bootloader, e.g. `ATmega328P` with `No bootloader`, which gives you maximum upload of 32768:

```
328.menu.bootloader.no_bootloader.upload.maximum_size=32768

```

Keep in mind that in either case you'll have needed to set the fuses for not having a bootloader. As weird as this sounds, choosing the `No Bootloader` option in MCUdude MiniCore for the `ATmega328P`, and then doing `Burn Bootloader` sets these fuses for you, despite the name not actually burning a bootloader in this case. If you were to edit the maximum upload size for the Nano board, you would need to manually set the fuses similarly to what Burn "Bootloader" does for the MiniCore ATMega328P with No-bootlader option.
> 6 votes

---
Tags: arduino-nano, bootloader, flash, isp, programmer
---


# Question
Title: How to increase the detection distance on Arduino KY-032 obstacle Avoidance sensor?
We've got an Arduino KY-032 obstacle avoidance sensor, and have spent a decent time searching and researching to find a detailed data sheet/manual to figure out how it works; but there aren't any detailed information on the module.

One of the few instructions here says that the potentiometers on the chip are used to adjust the distance, but I've tried all different settings and the maximum I can get is 10 centimeters. I've tried different surfaces with different reflectivity levels, but it doesn't really differ much.

Any idea how to increase the distance on this? Anything to do with the enable jumper?

**Update:** Here's the related code to the obstacle detection:

```
void loop() {
  // check the network connection once every 10 seconds:
  val = digitalRead (buttonpin) ;// digital interface will be assigned a value of 3 to read val
  if(full==1 && val==LOW) {
    Serial.print("Bin Full");
    delay(5000);
  } else {
    if (val == LOW) {
      // When the obstacle avoidance sensor detects a signal, LED flashes
      digitalWrite (Led, HIGH);
      delay(2000);
      if(digitalRead(buttonpin)==LOW) {
        delay(2000);
        if(digitalRead(buttonpin)==LOW) {
          full = 1;
        }
      }
      count++;
      //printCurrentNet();
      sendData();
    } else {
      digitalWrite (Led, LOW);
      if(full==1) {
          count = 0;
      }
      full = 0;
    }
  }
}

```

# Answer
The IR sensor module incorporates an internal 38KHz bandpass filter. The pot near the GND pin fine tunes the frequency of that signal, which is used to illuminate the IR LED.

The other pot adjusts the duty cycle of the signal. This controls the brightness of the IR LED. Both adjustments effect the sensitivity and range of the device.

To achieve maximum sensitivity, it is absolutely necessary to use the 'EN' or 'Enable' pin. When used correctly, however, additional optical shielding of the IR LED is required. This can be done with a small cardboard tube commonly used as packing material or any of a variety of other materials.

If the Enable function is not used, the jumper must be installed on the board. The Enable pin cannot be used if the jumper is in place.

For more information, see: http://irsensor.wizecode.com/
> 2 votes

# Answer
The wizecode page has some nice info. However the R5 pot (near the EN jumper) does not change the duty cycle but directly the current to the IR LED - still affects the brightness though. Too much current seems to trigger false positives - depends on your additional optical shielding. I put some black heat shrink tubing over the sensor - with a hole punched in for the sensor to see though. Also the R6 pot does not really "fine tune" the frequency, more like "coarse tune" - even a small nudge can detune by a kHz, greatly reducing the sensitivity.

If you use the EN jumper, a suddenly appearing object gives a short pulse, but then the disturbance signal suppression kicks in turns sensitivity down and 'unsees' the object. Also slowly appearing objects are not recognized for that reason. Only very near objects (a few cm) give a strong enough signal to overcome that sensitivity attenuation.

What I found somewhat irritating: Setting EN to LOW lets the IR LED steady on instead of off, which I would have expected. That might irritate the sensor more than necessary. Also draws more power (maybe even a lot, depending on R5 current setting).

Funny enough, you can get a somewhat analog behaviour from this sensor if you measure how long it takes from activating the EN pin to the sensor output getting low. The nearer the object is, the faster it reacts. Near objects take ~190us, farther objects more than 400us. Not nearly a linear behaviour though. Also depends on distance, size, angle, IR reflectivity and IR LED power. However it can detect a person in more than 1m distance.
> 3 votes

# Answer
These Obstacle sensors don't always work as expected.I bought 3 of them, but only 2 worked properly.The other only worked to a distance of about 6-7cm.
By the way, the code seems to be fine, but there is no way to tell for sure without complete code.
> 1 votes

# Answer
Check This: http://irsensor.wizecode.com/

> When the GREEN JUMPER is installed on the board (see picture), the IR LED will flicker continuously at 38kHz. If the Enable (EN) function will not be used, the jumper must be installed . When the jumper is removed, pin 4 of the 555 timer is held LOW (RESET) by R3, a 22K pull-down resistor. Then, if a HIGH condition is applied to the EN pin, the reset condition will be relieved and the 555 timer will begin to oscillate. The Enable function cannot be used if the GREEN JUMPER is in place. You must remove the jumper on the board in order to use the EN (Enable) pin.
> 1 votes

# Answer
Well, the range of the sensor should be: "2-40cm" I would suggest using the code below and changing the potentiometers to see if it makes any difference.

```
int Led = 13 ;// define LED Interface
int buttonpin = 3; // define the obstacle avoidance sensor interface

void setup ()
{
  pinMode (Led, OUTPUT) ;// define LED as output interface
  pinMode (buttonpin, INPUT) ;// define the obstacle avoidance sensor output interface
}
void loop ()
{
  if (digitalRead (buttonpin) == HIGH) // When the obstacle avoidance sensor detects a signal, LED goes on.
  {
    digitalWrite (Led, HIGH);
  }
  else
  {
    digitalWrite (Led, LOW);
  }
}

```
> 0 votes

---
Tags: sensors, ir, proximity
---


# Question
Title: Troubleshooting WS2812b LED strip with toggle on/off button
I have a very rudimentary setup with an arduino nano, an LED strip, a pushbutton and a resistor.

I was trying to use the pushbutton as a toggle, using this code

```
#include <stdio.h>
#include <stdlib.h>
#include<FastLED.h> // header file

#define NUM_LEDS 14 // number of led present in your strip
#define DATA_PIN 12 // digital pin of your arduino

CRGB leds[NUM_LEDS];

const int button = 2;            // GPIO 8 for the button
int status = false;

void setup() {
  //Serial.begin(9600);
  pinMode(button, INPUT);         // define button as an input
  pinMode(DATA_PIN, OUTPUT);           // define LED as an output
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}

void loop() {
  if (digitalRead(button)==true) { // if button is pressed
    // flip status
    //Serial.println("Changing status");
    status = !status;
    //Serial.println(status);
    toggle(status);
  }

  while (digitalRead(button) == true) {
    //Serial.println("while loop");
    delay(50);
    //Serial.println(status);
  }//

  delay(50);
} // begin again

void toggle(bool status) {
  if (status == true) {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::White;  //set the all leds to white
    }
    FastLED.show();
  } else {
    for (int i = 0; i < NUM_LEDS; i++) {
      leds[i] = CRGB::Black;  //set the all leds off
    }
    FastLED.show();
  }
}

```

This is my circuit

I am powering this from a battery (PNY model 12200, 2200 mAh, Output 5 V=1A) via USB into the arduino board. I am having some issues. Mainly, the lights would go on by themselvs after a while, maybe not full power but still would be on. Not sure where the problem is, any hints appreciated.

I also sometimes get the lights turned off, maybe I'm feeding current into the wrong place and a safety mechanism either on the arduino or the battery stick turns everything off to protect itself?

# Answer
The manual for the T2200, which I think is what you're referring to, says:

> Note: If the PowerPack does not automatically power on when a device is connected press the power button. The PowerPack will turn off after 90 seconds when there are no devices connected.

This is a common feature for USB battery banks meant for charging phones and similar devices. It *probably* shuts off when the current drops below some set limit, say 50mA for more than 90s. But it could also be looking every 90s for the average current over the course of 10ms. They just don't say. Given their description it sounds likely that it regularly turns on for some short time to probe for a load. All in all, not knowing the specifics of this may drive you nuts. Part of the thing to keep in mind is that someone using this thing to charge a cellphone wouldn't necessarily notice or care if it cut in and out every few seconds. If you want to use this to power an Arduino it's worth getting a good handle on how it behaves through some experimentation. Some of these power banks do have a way to disable their load detection and auto-shutoff feature; I did not see anything about that for this model.

The Nano, the official one anyway, has a 500mA PTC polyfuse on the USB VBUS ("5V"). Your code says `#define NUM_LEDS 14`. The WS2812b LEDs use something on the order of 50mA each at max output. You should probably measure what you're actually drawing, with the intensity you are commanding them to be, to be sure you're a good margin below 500mA. If you are in fact using 14 of them, and if it's possible that all can go full brightness, then you are perhaps trying to use something like 735mA, quite a bit above 500mA. You way find that it's necessary to route 5V around your Arduino to your LED strip, ideally through its own over-current protection.

Each time you power on or reset your project there's going to be some time before the sketch sets the pin connected to WS2812 data signal to output and some defined level. It may be a good idea to add an external pull resistor on the LED data signal, probably to GND, so that during power-up and reset the LED strip data signal is not picking up noise and trying to interpret it as color data and changing your load on your power source in the process. Having the powerbank potentially turning your project on and off gives extra opportunities for this to happen. If you trip the polyfuse, either by commanding the LEDs to draw too much or having the floating data pin do likewise, the voltage on the Nano side of it will drop. When the voltage drops it may trip the AVR microcontroller's brownout detector, which in turn will reset it the AVR, again bringing about a floating data pin on your LED strip.
> 1 votes

---
Tags: arduino-nano, led-strip, ws2812
---


# Question
Title: Which relay module to buy and what is the difference between 1 channel and 2 channel relay boards
I wanted to d a simple circuit using Arduino to control the lights in my house. But i do not know which relay module to use my house runs on standard 220v ac. Can anyone tell me weather this relay board will be enough

https://www.roboelements.com/wp-content/uploads/2018/10/1-Channel-5V-Relay-Module-for-Arduino-with-Optocoupler.jpg

Or should I buy a 2 channel one? And another thing what is the difference between 1 channel and 2 channel relay board.

I'm a complete beginner, so please help me out.

# Answer
> 1 votes
Yes, you can use those. You have to watch a few things:

* Input voltage: 5V, perfect for Arduino
* Output voltage: 220 V, perfect for 220V AC
* Output amperage: 10A, what you control should use max 10 A, and I would use max 5A, and also consider switching on current into account. However, 10A is a lot of current.

The difference between 1 and 2 channels relay boards, is just that there are either 1 or 2 of them, meaning you can control 1 or 2 motors independently from each other.

---
Tags: arduino-uno, relay, electronics, electricity
---


# Question
Title: What are the Arduino hardware options for experimenting with IoT?
Just starting to learn about Arduino and IoT. I'd like to know what the Arduino hardware options are to try the following:

1. Use FreeRTOS as SO
2. WiFi and BLE connectivity
3. Solderless board
4. Test OTA features
5. Experiment integration with different IoT Cloud platforms e.g. Azure IoT Hub
6. Build custom IoT devices

# Answer
> 1 votes
There are many options; which one is "best" for you I leave up to your own research, that could start here:

There's a list of Arduino's based on the SAMD21 that are supported by the FreeRTOS\_SAMD21 library here; pick any one with WiFi and BLE.

There are probably a zillion clones out there that could also do what you want, and there is also a FreeRTOS port for the ESP32 (ESP-IDF FreeRTOS, and maybe other ones as well).

---
Tags: wifi, iot, ble
---


# Question
Title: Arduino - ServoMotor Control and SoftwareSerial
My two arduino communicating serially with XBee. The receiver arduino also controls the servo motor. Servo works stably when there is no xBee connection. But when Arduino's serial communication, there is a problem in the operation of the servo motor. Servo motor stuttering while rotate, so stuttering occurs.

Can you help me?

My Coordinator Code:

```
#include <SoftwareSerial.h>
#define xBeeRxPin 10
#define xBeeTxPin 9
int deger3;
int deger4;
String d1,d2,d3;
SoftwareSerial xBeeSerial(xBeeRxPin, xBeeTxPin);

void setup() {
  Serial.begin(38400);
  xBeeSerial.begin(38400);
}void loop() {

  deger3 = analogRead(A0);
  deger4 = analogRead(A2);

  String deger5 =  (String)deger3 + ";" + (String)deger4 ;

  xBeeSerial.println(deger5);

  delay(50);
}

```

My Receiver Code:

```
#include <SoftwareSerial.h>
#include <Servo.h>
#define xBeeRxPin 10
#define xBeeTxPin 9
SoftwareSerial xBeeSerial(xBeeRxPin, xBeeTxPin);
String d1,d2,d3;

const int trigPin = 4;
const int echoPin = 3;
long duration;
int distance;
Servo myServo;

void setup() {
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  xBeeSerial.begin(38400);
  Serial.begin(38400);
  myServo.attach(11);
}
void loop() {
  for(int i=15;i<=165;i++){
    myServo.write(i);
     delay(10);
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, 11200);
    distance= duration*0.034/2;

    if(xBeeSerial.available()>0){
      d1=xBeeSerial.readString();
    }
  }

  for(int i=165;i>15;i--){
    myServo.write(i);
     delay(10);
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
    duration = pulseIn(echoPin, 11200);
    distance= duration*0.034/2;

    if(xBeeSerial.available()>0){
      d1=xBeeSerial.readString();
  }
 }
}

```

# Answer
When SoftwareSerial enters an interrupt each time it receives a character and busy-waits (delays) to time in each data sample as the bits in the character come in. No other interrupt service routines can run while this is happening. It also turns off interrupts when it sends.

The servo library for the AVR uses timer interrupts to generate the servo position signals.

When characters are being received, SoftwareSerial will interfere with the generation of the servo position signal because only one interrupt service routine can run at a time.

You may be able to mitigate the problem adding significant delay between characters sent, reducing the total number of characters sent. This would limit the interference and give servo time to get back to its correct position from however far it managed to deviate over the course of an inbound serial character.

There are also alternative libraries that use the AVR's Input Capture feature on an ICP pin to do some of the work of serial in hardware, and that may work for you. Here's one example library.

@ocrdu has rightly prompted me to add that there are servo libraries that will do the servo signal generation in hardware.
> 1 votes

---
Tags: arduino-uno, servo, softwareserial, xbee
---


# Question
Title: Converting c string to integer to unsigned char
I'm grappling with types between two different libraries.

The gist is that I'm using the ArduinoWebsockets library to receive information coming from my API that I then want to render out to an LED matrix. An example message would look like this:

```
1
2
4
8
16
32
64
128

```

It's important to point out that the data here is a list of **string** version of numbers, not integers.

I.e. if you look at the binary version of `1` from the list, it's actually `110001` which is the ASCII code for the character `1`.

This is because the message coming back from the websocket server is pulled out as a `const char *`.

The LED matrix function I'm calling has a signature of:

```
void Write_Max7219(unsigned char address, unsigned char dat)

```

So I need to send in the values as `unsigned char`s.

I want to:

* parse this information line by line
* convert the ASCII character for the number into its integer equivalent
* pass the value to a different function to write the data to an LED matrix

I'm not sure how exactly to do this. I've been grappling with the type const char pointer vs regular char pointer and how to properly parse the return delimited string.

Any help would be greatly appreciated!!

# Clarification

Based on some of the comments I don't think I explained the reason I'm trying to do this conversion very well. Here's (hopefully) a better explanation:

The reason I want to convert it is because I'm not displaying the number character as a string, I want to use the binary representation to control the lights in a row of the matrix.

The number 1 or 0b00000001 would light up only the rightmost led on the 8 led row of the matrix.

The idea is that I could send over rows of numbers where each row corresponds to the row on the LED matrix.

e.g.

```
1   -> 0b00000001
2   -> 0b00000010
4   -> 0b00000100
8   -> 0b00001000
16  -> 0b00010000
32  -> 0b00100000
64  -> 0b01000000
128 -> 0b10000000

```

But the messages I get from the websocket server are coming through as the string representations of the numbers (ASCII or UTF) vs the numbers themselves, so I can't just pass the numbers into the function for the LED matrix because the underlying binary is different.

The conversion is so that I can use the binary representation of 1 (0b00000001) vs the binary representation of '1' ( 00110001).

# UPDATE AND RESOLUTION

So I've been on a big troubleshooting journey. When @ocrdu said:

> BTW I would try to get the websocket to send the correct single bytes instead of string representations of numbers, if at all possible.

I thought "yeah, that's the real way of fixing it and understanding what's going on", so I started tracing the issue back. Without going into all of the detail it turns out that the problem I was having was actually starting at the test client.

I use firecamp and websocat as websocket client testing tools. I was trying to send the binary data via both tools, but when I dug in via Wireshark I found that the data in flight coming from the client itself was made up of the hex values for the encoded characters of the `1`s and `0`s.

After researching and asking a separate stackoverflow question I figured out a way of sending the actual binary data from the client, specifically `printf`.

e.g.:

```
 printf "\x01\x02\x03\x04\x05\x06\x07\x08" | websocat -b ws://localhost:3002

```

Now that this works I can start going back through the rest of my Arduino code and have it parse the binary data directly instead of converting the encoded values to their binary counterpoints.

All of that said, I do appreciate all of the help. I may not have needed to do the conversions for this particular instance, but I want to get better with my C types, conversions, and general understanding so the knowledge gained here is still beneficial. Thanks everyone :bows:

# Answer
Not sure if or why you want to convert `char*` to `int`, but if you need to, there are `atoi()`, `atol()`, `strtol()`, `strtoul()` to consider, or rolling your own function.

Pros and cons are discussed here. Main thing to note is that `atoi()` and `atol()` have no error handling, but if the `char*` you feed them is completely under control and predictable, that need not be a problem.

BTW I would try to get the websocket to send the correct single bytes instead of string representations of numbers, if at all possible.
> 3 votes

---
Tags: string, pointer
---


# Question
Title: First time using Kuman 3.5" TFT screen model SC3A-NEW-UK with Arduino
I bought online this LCD Touchscreen Kuman SC3A-NEW-UK. It uses ILI9486 drivers, but it didn't include any instructions manual, and kumantech.com seems to be devoid of complete technical documentation about SC3A-NEW-UK model.

I am trying to figure out:

* Which are the minimum connections I have to make between Arduino UNO and the LCD screen.
* Which "Arduino's C++" (AKA G++ ?) library I need to use in order to display stuff programatically

## To summarize

Just in case it wasn't noticable: I am trying to make a "Hello World" for my SC3A-NEW-UK's LCD Touchscreen from an Arduino UNO board. In other words: just print "Hello World" to see if it works.

## What I tried so far

Searching on the Internet wasn't enough. Searching "ILI9486" on Google led me to this Github project:

https://github.com/schreibfaul1/ESP32-TFT-Library-ILI9486

To see if I can use it, I tried downloading a whole ZIP from this Github project, and inside the Arduino IDE, I tried adding the downloaded library using the option "Include .ZIP library". If I copy-paste the code example provided within README.md (the following) and compile:

```
#include "Arduino.h"
#include "SPI.h"
#include "tft.h"

// defaults can be changed in tft.begin
// CS=22, DC=21, MOSI=23, MISO=19, SCK=18

TFT tft;
//-------------------------------------------------------------------------------------
void setup() {
    SPI.begin();
    tft.begin();
    tft.setRotation(1); //landscape
    tft.fillScreen(TFT_BLACK);
    tft.setFont(Garamond34x42);
    tft.setTextColor(TFT_CYAN);
    tft.setCursor(20,30);
    tft.print("Hello World!");
}
//-------------------------------------------------------------------------------------
void loop(void) {
    for(uint8_t rotation=0; rotation<4; rotation++) {
        tft.setRotation(rotation);
        tft.fillScreen(TFT_BLACK);
        tft.setCursor(20,30);
        tft.print("Hello World!");
        delay(3000);
    }
}
//-------------------------------------------------------------------------------------

```

...it results in this compile error:

```
In file included from C:\Users\MyUser\ArduinoProjects\test_external_library\test_external_library.ino:3:0:

C:\Users\MyUser\Documents\Arduino\libraries\Arduino-TFT-Library-ILI9486-master\src/tft.h:5:16: fatal error: FS.h: No such file or directory

compilation terminated.

exit status 1
Error compiling for board Arduino/Genuino Uno.

```

Line 5 at `tft.h` says:

```
#include "FS.h"

```

...and I have no idea what this FS library is supposed to be, so I don't think I can use that Github project at all... I am tempted to assume that Github's project is dead.

**So, perhaps I am fine just using the IDES's built-in `TFT` library, perhaps like this? I don't know...:**

```
#include <SPI.h>
#include <TFT.h>
#define CS   10
#define DC   9
#define RESET  8

#define TFT_CYAN    0x07FF
#define TFT_BLACK   0x0000

// Initialization inspired in code example found at
// https://www.arduino.cc/en/Guide/TFT
TFT tft = TFT(CS, DC, RESET);
int dummy_second_cnt = 0;

void setup() {
    // I don't know what's SPI for, anyway...
    // just found it in the code example present at GitHub's library's README.md
    // ...(which I am not trying to use at this point, so it's useless in this code example... commented-out for reference, just in case)
    //SPI.begin();

    tft.begin();
    tft.background(0,0,0);
    tft.setRotation(1);
    tft.fillScreen(TFT_BLACK);
    tft.setTextColor(TFT_CYAN);
    tft.setCursor(20,30);
    tft.print("Hello LCD Screen");

    delay(3000);
}

void loop() {
    tft.fillScreen(TFT_BLACK);
    tft.setCursor(20,30);
    tft.print("Seconds: ");
    tft.print(dummy_second_cnt);
    dummy_second_cnt++;
    delay(1000);
}

```

**This compiled in Arduino IDE, no problem, but I still don't know if it will work well with my screen.** I am also confused about initialization of the TFT object and how would I have to wire the LCD screen to the Arduino depending on this initialization:

```
TFT tft = TFT(CS, DC, RESET);

```

...i mean, my LCD screen has CS and RESET pins, but what is DC supposed to be here? (in this context, I don't think it stands for "Direct Current"... but there's no DC pin reference in my LCD screen written "AS IS"... ?? This brings me more confusion...

...specially having in mind that I don't know how am I supposed to wire the LCD screen to the Arduino yet. It seems the LCD pins have been designed to fit in directly to the Arduino board without thinking too much about it (like the shape is the same), but that would make the screen getting all the Arduino UNO's pins for itself, so I don't think so...

These are the `LCD_*` pins present at my LCD screen:

* LCD\_RST (Reset I guess)
* LCD\_CS
* LCD\_RS
* LCD\_WR (Write I guess)
* LCD\_RD (Read I guess)

(and the following I guess are 8-bit digital pins):

* LCD\_D0
* LCD\_D1
* LCD\_D2
* LCD\_D3
* LCD\_D4
* LCD\_D5
* LCD\_D6
* LCD\_D7

It also has 5V, 3V3 and GND pins (Which I guess are for power)

...so, powering the screen shouldn't be a big deal, but, how am I supposed to connect everything else? I am completely misguided about how am I supposed to interact with the screen from Arduino code... what is RS pin for? Should I use 4-bit or 8-bit mode? (I think 4-bit would imply connecting 4 digital pins for the screen, and 8-bit the whole 8 pins from screen to the Arduino UNO board)? Should I use LCD\_RD and LCD\_WR? Well you have a picture of my confusion.

Searching for documentation in the internet only leads me to partial examples. Not even using the model Ref ( SC3A-NEW-UK ) or the driver's ref ( ILI9486 ) as keywords for searching in Google leads me to clear documentation about howto wire stuff, or which specific libraries should I use...

Even though I know how to control Input/Output in Arduino code to interact with analog/digital input and output pins at will with C++ in Arduino code (but even so, I think I'm still an Arduino n00b), this LCD screen's physical interface is very confusing to me...

**Can you help me to overcome this confusion, please?** I'd rather have my mind clear before making any physical wiring and fry something...

**PD:** I have read somewhere that this SC3A-NEW-UK Touchscreen is made to shield Arduino MEGA boards (by fitting the PINs directly into it), but mine is an Arduino UNO Board! (perhaps I shouldn't have bought This LCD model, then?)... but I have sets of wires, pinboards and stuff... I don't want to give up the idea of harnessing this LCD screen using an Arduino UNO. I don't care about shielding feature, I just want to wire it and make it work. I will figure out how to shield electronics later on.

---

**EDIT:** Based on VE7JRO's answer, I managed to map the connections by seeing where the connections would go if I just fit the connections shielding the Arduino UNO, the way VE7JRO suggested:

```
+--------------+------------------+
| Arduino UNO  |    LCD Screen    |
+--------------+------------------+
|     GND      |        GND       |
+--------------+------------------+
|      5V      |         5V       |
+--------------+------------------+
|     3.3V     |       3.3V       |
+--------------+------------------+
|      A0      |      LCD_RD      |
+--------------+------------------+
|      A1      |      LCD_WR      |
+--------------+------------------+
|      A2      |      LCD_RS      |
+--------------+------------------+
|      A3      |      LCD_CS      |
+--------------+------------------+
|      A4      |      LCD_RST     |
+--------------+------------------+
|      A5      |       NONE       |
+--------------+------------------+
|       8      |      LCD_D0      |
+--------------+------------------+
|       9      |      LCD_D1      |
+--------------+------------------+
|    2 TO 7    | LCD_D2 TO LCD_D7 |
+--------------+------------------+
|      10      |       SD_SS      |
+--------------+------------------+
|      11      |       SD_DI      |
+--------------+------------------+
|      12      |       SD_DO      |
+--------------+------------------+
|      13      |      SD_SCK      |
+--------------+------------------+

```

I put `NONE` for A5 input, because that pin of LCD screen doesn't have any name on it. There are another ones without name as well, that I didn't include in this table. I believe (perhaps I'm wrong believing it, I don't know) that those pins without name have no use.

The bad thing about this layout is that it consumes almost all the Arduino pins, so I would not be able to attach additional circuits. However, perhaps I should not be worrying about earning connections yet, before testing the screen.

I still don't know much of the details about what pins do what for the screen, but I have read somewhere that `LCD_D0` to `LCD_D7` are meant to receive digital data in some kind of 8-bit parallel mode. But I also heard that there is a 4-bit mode. If I could use that mode with this screen, I would be able to have 4 free digital pins for anything else...

**Ok, I got the connections mapped. Next step would be trying those three libraries that VE7JRO suggested.**

---

**EDIT2:** I tested VE7JRO's code. LCD Screen did draw the interface as expected. But buttons didn't respond. I found out the code sample needs further calibration.

So, I started printing through the Serial the coordinates of the object `TSPoint p`, to find out if there was something wrong ~~with the `z` coordinate. And indeed, there was: setting `MINPRESSURE` and `MAXPRESSURE` according to what I saw in Serial Monitor while I pressed and I didn't pressed, fixed this. However, there's another more issue...~~

~~...when I tell Serial to print if the boolean operation `down && on_btn.contains(pixel_x, pixel_y)` results in either `true` or `false`, it prints it is false... while I am touching ON button. `down` is true for sure (after I calibrated `MINPRESSURE` and `MAXPRESSURE` constants); **so that must mean `on_btn.contains(pixel_x, pixel_y)` is returning false for some reason.** If I figure out why, I will be able to accomplish that the ON Button does what it's supposed to when I press it. And that will mean I will have completed calibration process. I would bet perhaps `pixel_x` and `pixel_y` need calibration as I already did with pressure detection based on `z`; or perhaps `contains` method is not reliable and I have to figure out some other methodology... I will tell you after I try~~

**All stroken through is based on assumption that Z is depth, and Y is height; Actually, it seems to be the other way around...**

After somemore trial-and-error research, it seems that Z is height, and Y is depth (at least within the `TSPoint` object's properties `x`, `y` and `z`, which values seem way more reliable than the `pixel_x` and `pixel_y` values, which purpose seems to be if the pixel is contained in the button's squares and nothing else)... I still don't get why is there the need to use this within the function `Touch_getXY(void)`:

```
if (pressed) {
    pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
    pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
}

```

...because their values when I touch the screen with the touchpen are very weird. I tried to guess which ranges they go, and they don't make sense when I move around the screen. Perhaps it's because this strange "Z instead of Y" mapping from the `TSPoint` object. Perhaps `pixel_x` and `pixel_y` don't need to make an intuitive sense, perhaps it's just some intrincated in-bound logic that only makes sense within electronics' low-level scope, or within `Adafruit_GFX_Button.press` method, I don't know... but **`x`, `y` and `z` readings from `TSPoint` object seem very accurate**, despite Y being Z and Z being Y...

...perhaps reading any documentation I can find about `Adafruit_GFX_Button` class, its properties and methods (specially `contains`) will lead me to comprehend clearly what's wrong...

**...also, it might be time to focus on searching those test sketches that VE7JRO talked me about:**

> There are 22 test sketches that come with the MCUFRIEND\_kbv library. One of them scans your display and outputs configuration information (sorry, it's been a while since I tested my screen). Another sketch will draw little boxes in each corner and sides. This is used to get the x y coordinates of the edges of your particular screen (it might be called TouchScreen\_Calibr\_native.ino).

---

**EDIT3**

X is Y? Y is Z? Z is X? *I don't know what to think anymore!* The last I tried, changing the formula for `pixel_x` and `pixel_y` to:

```
pixel_x = map(p.x, 1023, 0, 0, tft.width());
pixel_y = map(p.y, 1023, 0, 0, tft.height());

```

...and the constants for the pins:

```
const int XP = 6, XM = A2, YP = A1, YM = 7;

```

This seems to make `z` the pressure axis within `TSPoint` object, but ends up in strange behaviours:

* `x` seems numb (no matter if I press the touchscreen with touchpen or not, neither it's position: it always prints 65 to 70!
* `z` seems indeed sensitive to touch pressure, but **it's like its sensitivity is different depending on the touchpen's position on screen** (altough I'm not a robot, I think I was using more or less the same amount of force with my hand). It prints 0 when i do not touch the screen.
* `y` **seems sensible to both horizontal and vertical position at the same time!** This blows my head.

I don't know what to think anymore...

* Did I short-circuit something for not paying attention to the script's constants in my previous tests?
* Was the screen broken from the begginning?
* Is it a calibration error with values in the script?
* Might the libraries I am using be broken, or have some kind of bug with my TFT?

**This is becoming overwhelmingly more difficult than I thought...**

...according to some article I found(in Spanish, sorry), the `Touchscreen`'s initialization's params:

```
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

```
* `XP` is supposed to be the pin for `LCD_D6`: `6` in the Arduino.
* `YP` is supposed to be the pin for `LCD_WR`: `A1` in the Arduino.
* `XM` is supposed to be the pin for `LCD_RS`: `A2` in the Arduino.
* `YM` is supposed to be the pin for `LCD_D7`: `7` in the Arduino.
* The fifth parameter is supposed to be the resistance measured between `LCD_D6` and `LCD_RS` with the screen unplugged. Unfortunately, my multimeter can't measure it for some reason (I put it in 2000 Ohms mode for reading resistance: I always get '1', the same than when I don't connect anything... like if multimeter's contacts aren't working well, I don't know)... so I left the default 300 value.

I did initializate it well, as far as I know... **except the fifth parameter**. Would a wrong resistence value make such a big difference in calibration, up to the point this strange behaviours I have seen do happen?

**Damn, I am so close... what am I doing wrong?**

# Answer
> 2 votes
> Which are the minimum connections I have to make between Arduino UNO and the LCD screen.

The TFT screen plugs right on top of your Arduino Uno. I have a "cheaper" model with the same size screen and identical pins as your screen (exact same text printed beside the pins).

Before you plug it in, I have a few pieces of advise.

* It's possible to install the screen one or 2 pins "out of proper alignment", so plug it in before you apply power. Verify the correct pins are in the correct "holes", using the location of the `5V`, `3V3` and `GND` pins as a guide.
* This screen used lots of power, especially when you are using a test sketch that turns all the pixels on / off and cycles through various graphics / text output to the screen. My Uno's voltage regulator was getting pretty warm after 10 minutes, and I was suppling it with 8 VDC to the barrel jack power input. Using a 12 VDC supply would exacerbate the heat issue, so please be careful.

> Which "Arduino's C++" (AKA G++ ?) library I need to use in order to display stuff programatically?

I used the `MCUFRIEND_kbv` library, `Adafruit_GFX` library and the Adafruit `TouchScreen` library, all available in the Arduino IDE Library manager.

There are 22 test sketches that come with the `MCUFRIEND_kbv` library. One of them scans your display and outputs configuration information (sorry, it's been a while since I tested my screen). Another sketch will draw little boxes in each corner and sides. This is used to get the x y coordinates of the edges of your particular screen (it might be called `TouchScreen_Calibr_native.ino`).

Getting the screen to display anything is step 1. Step 2 is to calibrate the edges of the screen. Step 3 is to get the touch screen part of it to work.

Here is a sketch I used to test the screen by changing the color of a "box". Touching each of the 2 buttons on the screen changes the "box" color. I've left in all the config data I saved (see the end of this sketch). Your screen is different than mine, so running the test sketches from the library first is where I would start.

```
// SEE BOTTOM OF SKETCH FOR MORE DATA / test results.
#include <Adafruit_GFX.h>
#include <MCUFRIEND_kbv.h>
MCUFRIEND_kbv tft;
#include <TouchScreen.h>
#define MINPRESSURE 200
#define MAXPRESSURE 1000

// ALL Touch panels and wiring is DIFFERENT
// copy-paste results from TouchScreen_Calibr_native.ino
// OEM: const int XP = 6, XM = A2, YP = A1, YM = 7; //ID=0x9341
// OEM: const int TS_LEFT = 907, TS_RT = 136, TS_TOP = 942, TS_BOT = 139;
// MINE - WORKS.
const int XP = 7, XM = A1, YP = A2, YM = 6; //320x480 ID=0x9488
const int TS_LEFT = 929, TS_RT = 204, TS_TOP = 963, TS_BOT = 213;

TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

Adafruit_GFX_Button on_btn, off_btn;

int pixel_x, pixel_y;     //Touch_getXY() updates global vars
bool Touch_getXY(void)
{
    TSPoint p = ts.getPoint();
    pinMode(YP, OUTPUT);      //restore shared pins
    pinMode(XM, OUTPUT);
    digitalWrite(YP, HIGH);   //because TFT control pins
    digitalWrite(XM, HIGH);
    bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
    if (pressed) {
        pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width()); //.kbv makes sense to me
        pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
    }
    return pressed;
}

#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

void setup(void)
{
    Serial.begin(9600);
    uint16_t ID = tft.readID();
    Serial.print("TFT ID = 0x");
    Serial.println(ID, HEX);
    Serial.println("Calibrate for your Touch Panel");
    if (ID == 0xD3D3) ID = 0x9486; // write-only shield
    tft.begin(ID);
    tft.setRotation(0);            //PORTRAIT
    tft.fillScreen(BLACK);
    on_btn.initButton(&tft,  60, 200, 100, 40, WHITE, CYAN, BLACK, "ON", 2);
    off_btn.initButton(&tft, 180, 200, 100, 40, WHITE, CYAN, BLACK, "OFF", 2);
    on_btn.drawButton(false);
    off_btn.drawButton(false);
    tft.fillRect(40, 80, 160, 80, RED);
}

/* two buttons are quite simple
 */
void loop(void)
{
    bool down = Touch_getXY();
    on_btn.press(down && on_btn.contains(pixel_x, pixel_y));
    off_btn.press(down && off_btn.contains(pixel_x, pixel_y));
    if (on_btn.justReleased())
        on_btn.drawButton();
    if (off_btn.justReleased())
        off_btn.drawButton();
    if (on_btn.justPressed()) {
        on_btn.drawButton(true);
        tft.fillRect(40, 80, 160, 80, GREEN);
    }
    if (off_btn.justPressed()) {
        off_btn.drawButton(true);
        tft.fillRect(40, 80, 160, 80, RED);
    }
}

/*
Read Registers on MCUFRIEND UNO shield
controllers either read as single 16-bit
e.g. the ID is at readReg(0)
or as a sequence of 8-bit values
in special locations (first is dummy)

reg(0x0000) 00 00  ID: ILI9320, ILI9325, ILI9335, ...
reg(0x0004) 00 54 80 66 Manufacturer ID
reg(0x0009) 00 00 61 00 00  Status Register
reg(0x000A) 00 08 Get Power Mode
reg(0x000C) 00 06 Get Pixel Format
reg(0x0061) 00 00 RDID1 HX8347-G
reg(0x0062) 00 00 RDID2 HX8347-G
reg(0x0063) 00 00 RDID3 HX8347-G
reg(0x0064) 00 00 RDID1 HX8347-A
reg(0x0065) 00 00 RDID2 HX8347-A
reg(0x0066) 00 00 RDID3 HX8347-A
reg(0x0067) 00 00 RDID Himax HX8347-A
reg(0x0070) 00 00 Panel Himax HX8347-A
reg(0x00A1) 00 93 30 93 30  RD_DDB SSD1963
reg(0x00B0) 00 00 RGB Interface Signal Control
reg(0x00B4) 00 02 Inversion Control
reg(0x00B6) 00 02 02 3B 3B  Display Control
reg(0x00B7) 00 06 Entry Mode Set
reg(0x00BF) 00 00 00 00 00 00 ILI9481, HX8357-B
reg(0x00C0) 00 0E 0E 0E 0E 0E 0E 0E 0E  Panel Control
reg(0x00C8) 00 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0 B0  GAMMA
reg(0x00CC) 00 03 Panel Control
reg(0x00D0) 00 00 00  Power Control
reg(0x00D2) 00 00 00 00 05  NVM Read
reg(0x00D3) 00 00 94 88 ILI9341, ILI9488
reg(0x00D4) 00 97 00 00 Novatek ID
reg(0x00DA) 00 54 RDID1
reg(0x00DB) 00 80 RDID2
reg(0x00DC) 00 66 RDID3
reg(0x00E0) 00 00 07 0C 05 13 09 36 AA 46 09 10 0D 1A 1E 0F GAMMA-P
reg(0x00E1) 00 00 20 23 04 10 06 37 56 49 04 0C 0A 33 37 0F GAMMA-N
reg(0x00EF) 00 00 00 00 00 00 ILI9327
reg(0x00F2) 00 58 04 12 02 22 22 FF 0A 90 14 88 Adjust Control 2
reg(0x00F6) 00 00 00 00 Interface Control

-----

TouchScreen.h GFX Calibration
Making all control and bus pins INPUT_PULLUP
Typical 30k Analog pullup with corresponding pin
would read low when digital is written LOW
e.g. reads ~25 for 300R X direction
e.g. reads ~30 for 500R Y direction

Testing : (A1, D7) = 23
Testing : (A2, D6) = 34
Diagnosing as:-
XM,XP:  (A1, D7) = 23
YP,YM:  (A2, D6) = 34
ID = 0x9488

cx=904 cy=951 cz=418 LEFT, TOP, Pressure
cx=907 cy=584 cz=535 LEFT, MIDH, Pressure
cx=910 cy=229 cz=504 LEFT, BOT, Pressure
cx=554 cy=948 cz=608 MIDW, TOP, Pressure
cx=563 cy=230 cz=674 MIDW, BOT, Pressure
cx=228 cy=947 cz=946 RT, TOP, Pressure
cx=228 cy=583 cz=1038 RT, MIDH, Pressure
cx=225 cy=230 cz=929 RT, BOT, Pressure
MCUFRIEND_kbv ID=0x9488  320 x 480

const int XP=7,XM=A1,YP=A2,YM=6; //320x480 ID=0x9488
const int TS_LEFT=929,TS_RT=204,TS_TOP=963,TS_BOT=213;
PORTRAIT CALIBRATION     320 x 480
x = map(p.x, LEFT=929, RT=204, 0, 320)
y = map(p.y, TOP=963, BOT=213, 0, 480)
Touch Pin Wiring XP=7 XM=A1 YP=A2 YM=6
LANDSCAPE CALIBRATION    480 x 320
x = map(p.y, LEFT=963, RT=213, 0, 480)
y = map(p.x, TOP=204, BOT=929, 0, 320)
*/

```

# Answer
> 0 votes
You sound very much the same as me when I got this screen, it took me a while, There is one of 'Dronebot's sessions on Youtube where he is connecting this screen which may get you started. I got drivers and information on lcdwiki.com with examples in the library folder. I believe you get either a Uno to Mega version of this screen as the pinout is different for each, if you have the box for the screen, under the bar code it has the item description tell you which version you have.Uno or Mega. On the lcdwiki site you'll find drivers for both under the pics of each screen and for of loads of other screens LCD OLED and TFT's. there is in the library folder when you download /install a fair few examples to have a play with and get the hang of this DRONEBOT, and LCDWIKI sites have a fair bit of info and both worth a visit. As of yet I can't get any of Adafruits examples going because of driver differences

---
Tags: c++, lcd, connector
---


# Question
Title: LCD 16x2 shows one line cut and the 7th column also cut
My 16x2 LCD shows one line cut and the 7th column also cut:

Applying pressure:

# Answer
My LCD module looks so similar to yours I decided risk to taking it apart for the purposes of taking pictures for to go along with the description. It went back to together fine.

The black part I suggested pushing down on I'm going to call a "bezel", even though I'm not sure that's technically the correct term for it.

The pink color showing between the PCB and bezel is probably a "zebra strip" or elastomeric connector. They conduct signals from LCD controller mounted on the PCB up to the LCD glass itself. Sometimes they don't make good contact and so some segments of the LCD don't respond or respond poorly. They may make better contact when you apply pressure to them. If some or all of the segments start responding when you do that, it's a fairly good indication that this is a problem, though not an Arduino problem as such, it's a problem encountered with some frequency by Arduino users.

If you may need to replace the strips, or clean them, or adjust the bezel to apply more pressure to them. Or just get another LCD module.

Back of one of my LCD modules that looks a lot like yours:

If you look at the back side of the board you *may* find that you can unclip the bezel; though it could also be soldered or glued etc. If/when you do unclip it, the zebra strips and LCD glass will probably come free, perhaps with polarization filters as well. You'll want to pay attention to the orientation of the *everything* so you know what you're doing when you put it back together.

I unclipped my the bezel on mine and the zebra strips (pink; they're not always pink) stayed with it. It is no *so* easy to see the "zebra" pattern on these particular strips. Often they more alternating gray/white pattern.

Here's the PCB showing the contacts that the zebra strips mate to an the LED backlight spreader. Apologies for the dust.

The strip pattern is a little easier to see in this image. You can also see the pattern of the conductors on the LCD glass.

You can try cleaning the strips and the glass and PCB where the make contact. I would be careful *what* you clean with; look for trustworthy recommendations. In any case, keep your finger grease off of everything, either by using gloves or just washing and drying your hands before working on it.
> 2 votes

---
Tags: lcd
---


title: Initializing Array of structs

text:
# Question
Title: Initializing Array of structs
I defined myself a struct:

```
typedef struct {
  unsigned char current;
  unsigned char start;
  unsigned char target;
  unsigned long startTime;
  unsigned int duration;
} led;

```

I was able to initialize an instance of that like this:

```
led h_red = {0,0,255,0,300};

```

However, when I try to have them in an array:

```
led leds[LEDS];
leds[0] = {0,0,0,0,0};
leds[1] = {0,0,0,0,0};
leds[2] = {0,0,255,0,300};

```

I get this error

```
signal:28:1: error: 'leds' does not name a type
 leds[0] = {0,0,0,0,0};
 ^~~~
signal:29:1: error: 'leds' does not name a type
 leds[1] = {0,0,0,0,0};
 ^~~~
signal:30:1: error: 'leds' does not name a type
 leds[2] = {0,0,255,0,300};
 ^~~~

```

And I have no idea what I'm doing wrong here. You can see the full change here on GitHub

# Answer
> ```
> led h_red = {0,0,255,0,300};
>
> ```

Here, you are defining a variable, and at the same time giving it an initial value. This is called an *initialization*.

> ```
> led leds[LEDS];
>
> ```

Here you are defining an array. Since it is in global scope, and not explicitly initialized, it is implicitly initialized to all bytes zero.

> ```
> leds[0] = {0,0,0,0,0};
>
> ```

Here, you are trying to give a value to an element of the array that has already been defined previously. This is thus *not* an initialization, but an *assignment*. Unlike initializations, assignments cannot exist outside a function. If you want to assign initial values, you can do it in `setup()`.

Alternatively, you can initialize the array while you define it:

```
led leds[LEDS] = {
    {0, 0,   0, 0,   0},
    {0, 0,   0, 0,   0},
    {0, 0, 255, 0, 300}
};

```
> 10 votes

# Answer
I've upvoted @Edgar Bonet's answer, because it is correct.

I want to add some more examples and explanations though.

## Key summary:

In C and C++, you can NOT have code *logic* outside of functions. The global context outside of functions is intended for *declarations*, *definitions*, and some *initializations*/*constructors* only. All code *logic* must be *inside of a function*. Code *logic* includes post-construction variable assignments, `if` statements, etc.

## Examples:

### 1. NOT allowed:

**Therefore, you can NOT do the following, since it attempts to do non-initializing *assignments* outside of all function scopes.**

Notice also that in C++ (which Arduino is), you don't need to use `typedef` for structs either, so I've removed that from the `struct` definition. I'm also using the stdint.h types, which are considered safer and "best practice" for data types, as they specify the exact type size in bits. Use `uint8_t` in place of `unsigned char`, `uint32_t` instead of the Arduino Uno's `unsigned long`, and `uint16_t` instead of the Arduino Uno's `unsigned int`. Also, in C++ in particular, `constexpr` or enums are preferred over `#define` to set variable constants.

```
constexpr uint8_t NUM_LEDS = 3;

struct Led {
  uint8_t current;
  uint8_t start;
  uint8_t target;
  uint32_t startTime;
  uint16_t duration;
};

Led leds[NUM_LEDS];
// NOT OK: Variable (re)assignments are NOT allowed outside of functions in
// C and C++.
leds[0] = {0, 0,   0, 0,   0};
leds[1] = {0, 0,   0, 0,   0};
leds[2] = {0, 0, 255, 0, 300};

void setup()
{
}

void loop()
{
}

```

### 2. IS allowed:

**You CAN, however, have variable *initializations* outside of functions, so long as they occur at the same time as *construction*, so this is perfectly valid:**

```
Led leds[NUM_LEDS];
// This form of aggregate initialization during construction is just fine in the
// global scope outside of all functions.
Led leds[NUM_LEDS] = {
    {0, 0,   0, 0,   0},
    {0, 0,   0, 0,   0},
    {0, 0, 255, 0, 300},
};

void setup()
{
}

void loop()
{
}

```

### 3. Also IS allowed:

**Or, you can just move your reassignments into a function, such as `setup()`:**

```
Led leds[NUM_LEDS];

void setup()
{
    // This variable (re)assignment is just fine since it's inside
    // of a function.
    leds[0] = {0, 0,   0, 0,   0};
    leds[1] = {0, 0,   0, 0,   0};
    leds[2] = {0, 0, 255, 0, 300};
}

void loop()
{
}

```

### 4. Full, runnable example on a PC:

**Here's a full, runnable example on a PC, with printing to verify the contents of the struct were changed:**

Run it online yourself on OnlineGDB here, or from my eRCaGuy\_hello\_world repo here: struct\_array\_initialization.cpp:

```
#include <stdint.h>
#include <stdio.h>

// Get the number of elements in a C-style array
#define ARRAY_LEN(array) (sizeof(array)/sizeof(array[0]))

constexpr uint8_t NUM_LEDS = 3;

struct Led {
  uint8_t current;
  uint8_t start;
  uint8_t target;
  uint32_t startTime;
  uint16_t duration;
};

// To initialize once at construction. This form of aggregate initialization
// can be used anywhere: both inside and outside functions.
Led leds[NUM_LEDS] = {
    { 1,  2,  3,  4,  5},
    { 6,  7,  8,  9, 10},
    {11, 12, 13, 14, 15},
};

// Print the full contents of an array of `Led` structs
void printLeds(const Led ledArrayIn[], size_t ledArrayLen)
{
    for (size_t i = 0; i < ledArrayLen; i++)
    {
        printf("ledArrayIn[%lu]\n"
               "current   = %u\n"
               "start     = %u\n"
               "target    = %u\n"
               "startTime = %u\n"
               "duration  = %u\n\n",
               i,
               ledArrayIn[i].current,
               ledArrayIn[i].start,
               ledArrayIn[i].target,
               ledArrayIn[i].startTime,
               ledArrayIn[i].duration);
    }
}

int main()
{
    printf("Hello World\n\n");

    printLeds(leds, ARRAY_LEN(leds));

    printf("==============\n\n");

    // Do this to set or change the structs at any time AFTER construction!
    // This variable (re)assignment is only allowed inside of a function, NOT
    // in the global scope outside of all functions!
    leds[0] = {10, 20,  30,  40,  50};
    leds[1] = {60, 70,  80,  90, 100};
    leds[2] = { 0,  0, 255,   0, 300};

    printLeds(leds, ARRAY_LEN(leds));

    return 0;
}

```

Sample output:

```
Hello World

ledArrayIn[0]
current   = 1
start     = 2
target    = 3
startTime = 4
duration  = 5

ledArrayIn[1]
current   = 6
start     = 7
target    = 8
startTime = 9
duration  = 10

ledArrayIn[2]
current   = 11
start     = 12
target    = 13
startTime = 14
duration  = 15

==============

ledArrayIn[0]
current   = 10
start     = 20
target    = 30
startTime = 40
duration  = 50

ledArrayIn[1]
current   = 60
start     = 70
target    = 80
startTime = 90
duration  = 100

ledArrayIn[2]
current   = 0
start     = 0
target    = 255
startTime = 0
duration  = 300

```

## Other references:

1. https://en.cppreference.com/w/cpp/language/aggregate\_initialization
2. \[my answer\] https://stackoverflow.com/questions/61240589/how-to-initialize-a-struct-to-0-in-c/61240590#61240590
> 1 votes

---
Tags: array, struct
---


# Question
Title: Recognize peak in specific frequency area
I am wondering if it is possible to attach a microphone to an Arduino board and make the Arduino recognize a volume peak in a specific range of frequencies.

I want it to detect a specific peak (for example 0,1 dB) in the range of 1000 hz to 5000 hz.

# Answer
You can filter the signal and look at the power that lies within the frequency range you are interested about. You could use an FFT for that, but it is quite computationally expensive. If you go for the FFT, you would probably end up sampling the mic in small bursts (a few milliseconds sampled every few tens of milliseconds), as the Arduino would spend most of its time processing the data.

A better option is probably to work in the time domain, rather than the frequency domain. If you do not need to know exactly how much power lies in each frequency bin, and are only interested in the total power within the window of interest, then the FFT is computing too much stuff you do not need. A less computationally expensive option would be to run the samples through a digital band pass filter tailored to the band you want. You can then compute the power from the output of the filter and low-pass it:

```
raw_sample = sample_the_microphone_somehow();
filtered_signal = bandpass_filter(raw_sample);
instantaneous_power = filtered_signal * filtered_signal:
smoothed_power = low_pass_filter(instantaneous_power);

```

But you would still need a beefy Arduino if you want to be able to acquire and process the samples at a reasonable rate: at least twice the highest frequency that comes out of the microphone.

A still better option could be to do the filtering in the analog domain, before the signal reaches the Arduino. If you can at least remove the frequency components above 5 kHz, then the Arduino would only need to sample at 10 kS/s, and run a digital high pass filter to remove the part of the signal below 1 kHz. This should be easy enough even for an AVR-based Arduino.

For the implementation of the filters, you may want to try this online filter builder
> 1 votes

# Answer
An alternative to the FFT is the Goertzel algorithm. It is intended to only detect a single frequency, so may not suit your purpose of working with a range.

But it may be more practical and require less intensive processing. Although intended to only detect a single frequency, it will of course give results near a given frequency, depending on the sampling rates and detection thresholds.

I have previously used an Arduino Goertzel algorithm library, but there doesn't appear to be anything available through the Library Manager at the moment; a web search shows some hits though.

The beauty of the Goertzel algorithm is that it only needs to keep a small amount of data in memory, so may have some benefit on smaller processors over more data intensive techniques like FFT.

I would try implementing one or more Goertzel detectors across your range (eg one at 3kHz or two at 2kHz and 4kHz) to see if they are sensitive enough.
> 1 votes

# Answer
You could sample the sound from the microphone and then apply a Fast Fourier Transformation (FFT).

An FFT lets you decompose a sequence of samples into components of different frequencies, usually into "buckets" that each have a small frequency band. You can then have a look at these buckets to see if there is a peak in a specific frequency range.

There are several examples and libraries for this on Arduinos, like EasyFFT and arduinoFFT.

*PS. Edgar Bonet's answer is better; I may have become a bit lazy at coming up with computationally efficient ways of doing things because of my using "beefy" Arduinos exclusively.*
> 0 votes

---
Tags: frequency
---


title: ATtiny85-DHT11-TM1637

text:
# Question
Title: ATtiny85-DHT11-TM1637
I have tried many combinations and I can get the Attiny85 to display on the TM1637 just fine, but I cannot get ant readings from the DTH11, tried different pins, libraries. I upload code via UNO as isp and that works fine. Tried same code on UNO and it works.

This is my first question on here, I usually figure things, but also first ATtiny85 adventure.

```
#include <TM1637Display.h>
#include "DHT.h"
#define CLK 4
#define DIO 3
#define DHTPIN 2  //
#define DHTTYPE DHT11
int MTD (2000);
TM1637Display display = TM1637Display(CLK, DIO);
DHT dht(DHTPIN, DHTTYPE);

const uint8_t celsius[] = {
  SEG_A | SEG_B | SEG_F | SEG_G, SEG_A | SEG_D | SEG_E | SEG_F
}; // oC
const uint8_t Fahrenheit[] = {
  SEG_A | SEG_B | SEG_F | SEG_G, SEG_A | SEG_E | SEG_F | SEG_G
}; // oF
const uint8_t Humidityh[] = {
  SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, SEG_C | SEG_D | SEG_E | SEG_F | SEG_B
}; // HU

void setup() {
  dht.begin();
  display.setBrightness(7);
}

void loop() {
  delay(1000);
  float Humidity = dht.readHumidity();
  float TemperatureC = dht.readTemperature();
  float TemperatureF = dht.readTemperature(true);

  display.showNumberDecEx(TemperatureF, 0b10000000, false, 2, 0);
  display.setSegments(Fahrenheit, 2, 2); delay(MTD);
  display.showNumberDecEx(Humidity, 0b10000000, false, 2, 0);
  display.setSegments(Humidityh, 2, 2); delay(MTD);
  display.showNumberDecEx(TemperatureC, 0b10000000, false, 2, 0);
  display.setSegments(celsius, 2, 2); delay(MTD-1000);
}

```

# Answer
Found \<TinyDHT.h\> and all works ok, just what I wanted.
> 3 votes

---
Tags: attiny, temperature-sensor, 7-segment
---


title: Fast PWM: Resolution in hertz

text:
# Question
Title: Fast PWM: Resolution in hertz
I am trying to get a nice sounding varying PWM to DAC, and intend to use a Sallen Key as part of an active low pass filter.

I set the Fast PWM at a max of 255 (WGM1\[0-3\] = 5) and set/clear OC1A upon comparing with OCR1A `(1<< COM1A1)`

I also update the value of OCR1A in 64 distinct steps, changing those steps around 15'000 times a second to create a specific sinusoidal shape.

As the chip works at 16 Mega Hertz, does this mean that one cycle of PWM is `16'000'000/256=` 62.5 Kilo Hertz? If not, what is its resolution

Thank you!

# Answer
> 1 votes
With the help of the comments, I decided to use variable PWM max values to match absolutely with the frequency. This resulted in a crispier sound that *actually doesn't need the Sallen Key anymore*.

For example, a low C natural, or `261.6Hz`, updated `32` times for `8` full cycles of PWM give us, for a 16MHz chip, an period and amplitude of `238`.

This means that having a prescaler of `8` (`CS01`), a period (`OCR0A`) AND a max potential duty cycle (`ICR1`) of `238`, and going through 32 iterations of the sound sought for, I got the sound that I wanted and none of the wave groove that comes with a pulse duty cycle cut short.

Sure, it means less granularity when it comes to a Bb with a max duty cycle of 133, however it worked for me.

---
Tags: pwm, dac
---


# Question
Title: EBay "Development Programmer Board for ATtiny"
Has anyone tried these? Does the ATtiny have a bootloader? What software is used to program the chip? Arduino compatible?

Looks a lot more convenient than programming the ATtiny via an Uno.

http://m.ebay.com/itm/201536595756

/Ola

# Answer
If you don't have experience working with AVRs at a low level then stay away from that. It doesn't provide any connection for a programmer and relies on the Micronucleus bootloader already being in place.

If you really want to experiment with ATtiny development then go with either an Adafruit Trinket or a Digistump Digispark (both of which already have Micronucleus loaded), or get an AVR programmer and (optionally) a ATtiny13/25/45/85 development board that includes a 6- or 10-pin programming header
> 4 votes

# Answer
TL;DR: **It's basically a bigger digispark with a socket and different header.**

Just for completeness:

It depends on the product description, recently I ordered two of your link and some of these. Those seem to be the same board as you asked for, but in your link the "Package includes" only mentions the board without MCU, which would render the question pointless.

Like Ignacio already said correctly, without proper equipment you wont get this to work with the Arduino IDE. Once you have a bootloader (e.g. micronucleus) on it (the MCU), you can use it like a digispark.

In fact the USB connection works just like on the digispark and ist **not only for power**.

The mounted ATtiny85 was preflashed with micronucleus v1.6 and registered as vendor=16d0, product=0753, which means you could even start with it right away, with Arduino IDE and the digistump board manager.

Personally I use these for prototyping small projects with those tinies on the go where you often don't need a programmer. Once you're done or want to do more you can always remove the bootloader and continue with a real programmer. Or you want to reflash while using the reset pin for I/O, also handy.
> 2 votes

# Answer
This board supports Attiny25/45/85 MCUs. It is possible to use bootloader with this board. It can be a low speed (1.5MBps) USB device. More info can be found in this article: https://makbit.com/web/firmware/breathing-life-into-digispark-clone-with-attiny-mcu/
> 2 votes

# Answer
I just used one of those boards in conjunction with a cheap tinyISP board to program a DIP8 attiny85 using ISP from Arduino IDE.

The pinout matches if you put the IDC cable the right way around. I used a 10-pin IDC cable - I think you'd have to use at least an 8-pin IDC because a 6-pin wouldn't fit with the extra pins on the programmer board, unless you only soldered on the 6 header pins that you need for ISP.

If you program the digistump bootloader onto the attiny85 then you should be able to use the USB socket on that board to reprogram it. But if it's a blank attiny85 then you have to use ISP to program it in the first place.

Here's how I hooked them up:

You can see from the silkscreen that the pins are clearly designed to match up to the Arduino ISP pinout:
> 2 votes

# Answer
I don't see than much usefulness in these boards.

Negatives:

* The USB port is only for power. Not for programming.
* You have to buy an ATTiny chip to put into the socket. It's **not** included.
* There is no way to put this into a breadboard.
* There isn't even a way to get to the output pins. So you have to put the chip into this programmer, program it, remove it from the programmer, and place it back into the circuit.
* It seems to use an 8-pin header to break out the 8 pins on the ATtiny. You'd have to use some female jumper wires to connect to them.

Positives:

* There is a voltage regulator, so you can connect a higher voltage to the VIN pin
* There is an 8-pin ISP header, so you can easily connect a ISP programmer, like an USB-ASP

So in conclusion, some minor plus sides, and some major downsides.

Just place the 8-pin DIP ATtiny in a breadboard.
> 0 votes

# Answer
The socket is important. One of the huge benefits of using these 8 pin packages is the ability to plug and pull over and over again. Sadly there are few development boards not obsessed with USB. Thankfully this one's is a power header and can be removed easily enough. The Digi/Ada offerings and their clones are not socketed. They are also simple enough to do your own boards.

You can program the x5's with the SparkFun Tiny AVR programmer, based on a design by D.A.Mellis using leads, or by transplanting the mcu. And you can do it from an Arduino, either way you are making up or sourcing a lead, as squid style flying leads are tedious.

Otherwise there is a 2k or so bootloader that can be used, which would be most useful for the 85. Without serial support from USB or FTDI this will be hard.

**Software**

1. Arduino with core from https://github.com/SpenceKonde/ATTinyCore
2. avra and avrdude from the command line for assembler, you could also compile C/C++ from the command line but this is not common.
3. AVR plugin for Eclipse.
4. Sloeber stand alone Eclipse based Arduino IDE, some quirks.
5. Atmel Studio 7 based on Visual Studio, requires Windows, requires genuine "Microchip" programmer. Note this is free and includes an emulator.
6. There is some effort to get this possible with C-Lion by JetBrains.

.
> 0 votes

---
Tags: attiny, programmer
---


# Question
Title: Problems in calculating and printing long unsigned integers
I have this code which provides an erroneous unsigned long number.

CODE:

```
char buff[100];

int unsigned long bytes;

bytes = 48 * 70 * 144;

sprintf(buff,"%lu bytes\n", bytes);

BTPort.print(buff);

```

OUTPUT: 20088 bytes

BUT: The correct value is 483840

# Answer
This is because the default numeric type is `int`, which on Arduino is just 16 bits (and signed).

So 48 * 70 * 144 is 0x76200 in hex, which truncated to 16 bits is 0x6200, or 25088. This calculation is done by the preprocessor, not the compiler, so doesn't know (or care) about the destination variable type.

You need to force the values to be calculated as unsigned long by appending `UL` to them:

```
bytes = 48UL * 70UL * 144UL;

```
> 2 votes

---
Tags: atmega2560, mathematics
---


# Question
Title: FastLED-driven strip acts weird when using PN532
A LED-strip (WS2812B, 46 pieces, PIN 8) and an Adafruit PN532 RFID shield (IRQ 2) are attached to my Arduino Mega 2560.

The GRB based strip seems to be working fine with FastLED in the beginning, I can confirm this by cycling through all three base colours in `setup()`.

Once I call `nfc.readPassiveTargetID(...)` and use an NFC tag on it, things start to get weird. Whenever I comment out the line, it works properly again. The colors RGB are randomly swapped (as if I had passed a different color ordering), brightnesses may change randomly as well, and sometimes a few LEDs in the beginning or end of the strip have different brightness/color as the rest.

As I have put the brightness down to 32, I'm sure it's not a power problem.

My assumption is that there is either some memory corruption, or some PIN interference with the two libraries, although I don't know why it would do it. Please find my code below, any help is appreciated.

```
  #include <FastLED.h>
  #include <Adafruit_PN532.h>

  #define LED_COUNT 46
  #define LED_DATA_PIN 8
  CRGB leds[LED_COUNT];

  #define PN532_IRQ (2)
  #define PN532_RESET (3) // Not connected

  Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

  void setLeds(CRGB color) {
    Serial.print("setLeds("); Serial.print(color.r, DEC ); Serial.print(","); Serial.print(color.g, DEC ); Serial.print(","); Serial.print(color.b, DEC ); Serial.println(")");
    for (int i = 0; i < LED_COUNT; i++) {
      leds[i] = color;
    }
    FastLED.show();
  }

  void ledStartSequence() {
    setLeds(CRGB::Black);
    for (int crtLed = 0; crtLed < 23; crtLed++) {
      leds[crtLed] = CRGB::Blue;
      leds[crtLed + 23] = CRGB::Blue;
      FastLED.show();
      delay(20);
    }
    Serial.println("Red");
    setLeds(CRGB::Red);
    delay(1000);
    Serial.println("Green");
    setLeds(CRGB::Green);
    delay(1000);
    Serial.println("Blue");
    setLeds(CRGB::Blue);
    delay(1000);

    Serial.println("Off");
    setLeds(CRGB::Black);
  }

  void initLeds() {
    FastLED.addLeds<WS2812B, LED_DATA_PIN, GRB>(leds, LED_COUNT);
    FastLED.setBrightness(32);
  }

  void initSerial() {
    Serial.begin(9600);
    Serial.println("Hello!");
  }

  void initNFC() {
    nfc.begin();
    uint32_t versiondata = nfc.getFirmwareVersion();
    Serial.print(versiondata);
    if (! versiondata) {
      Serial.print("Error: Didn't find PN53x board");
      while (1); // halt
    }
    // Got ok data, print it out!
    Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX);
    Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC);
    Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC);

    nfc.SAMConfig();
  }

  void setup() {
    initSerial();
    initLeds();
    initNFC();
    ledStartSequence();
  }

  void loop(void) {
    Serial.println("Waiting for an ISO14443A Card ...");
    setLeds(CRGB::Red); // only displayed correctly in the first iteration
    uint8_t success;
    uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
    uint8_t uidLength;

    success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
    /*
     *  Here's where things start to go nuts!
    */
    delay(1000);
    setLeds(CRGB::Green); // usually not displayed correctly
    delay(1000);
    setLeds(CRGB::Blue); // usually not displayed correctly
    delay(1000);
  }

```

# Answer
After spending way too much time on the code, I figured that it had to do with something entirely different:

The RFID reader created an RF interference on the data wire towards the LED strip... Shielding it properly did the trick, no matter which pin is being used.

Thanks for the help anyway.
> 1 votes

---
Tags: arduino-mega, led
---


# Question
Title: Rasberry Pi Controlling Arduino - Reads "Ghost" Input - Doesn't Complete Logic Loop
I am using an Arduino Atmega2560 clone, I have used it many times before with satisfactory results - although I haven't used it with my Rpi before.

My Raspberry Pi is model 4 (B I think?).

```
#define knap 49
#define motorOutput 8

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(knap, INPUT);
  pinMode(motorOutput, OUTPUT);
  digitalWrite(motorOutput, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:
  int knapSensor = digitalRead(knap);
  Serial.print(knapSensor);
  if (knapSensor == 1) {
    int knapSensor = digitalRead(knap);
    Serial.print("aktiveret");
    digitalWrite(motorOutput, HIGH);
    delay(500);
    digitalWrite(motorOutput, LOW);
  }
}

```

Now I have double checked, the motor and the button is wired correctly. There is no hardware issue, aside from the cables being sh- quality.

Problem is, whenever I run this program two things will happen;

Either it starts fine by displaying "0000..." on the serial monitor.

Then when I press the button it goes to "AktiveretAktiveretAktiveret..." even when I depress the button.

Or, it will just display "AktiveretAktiveretAktiveret...".

In either case the motor won't work.

Once again, I have done tests where I have removed the power from the breadboard and replaced the voltage pin for the motor with the voltage pin leading from the button.

First thing didn't change the input (i.e still "AktiveretAktiveret,") the latter started the motor.

I.e this isn't about bad wiring.

EDIT:

Added schematics and changed the code

# Answer
Your button needs a pulldown resistor to work reliably.

See the discussion and solution here

The resistor, with a value of around 10K (but any value between 3K and 20K will probably do), needs to be between the input pin or your Arduino and ground to give it a defined value when the button is released.

Putting a resistor between the Arduino pin and ground will make sure the pin reads "low" when no button is pressed. When the button is pressed, it will be connected directly to +5V and will read high. Only a small current (0.5mA) will flow from +5V to ground through the 10K Ohm resistor in that case. It will not create a short circuit.
> 1 votes

# Answer
What motor are you using? If it works straight from the 5v but not from a GPIO, it could be an issue of insufficient power.

As @StarCat4 mentioned, you also need to add a digitalRead inside your while loop if you want the motor to ever turn off.
> 1 votes

---
Tags: arduino-mega, sensors, motor, button, input
---