title: Powering Peltier using solar panels

text:
# Question
Title: Powering Peltier using solar panels
I am a beginner to electronics and trying to make a portable air conditioner using a Peltier cooling pad (12V). I am planning on using a solar panel to power the Peltier and looking forward to your expert opinion for below; \- Is this possible? -What the specifications I have to consider prior to purchasing the solar panel? \- What is the weight of the solar panel? \- Can I operate the Peltier through an Arduino using Solar panel as the power source( without using batteries to power Arduino and Peltier). My idea is to control the Peltier cooler via Arduino using a phone App. Really sorry if these questions are basic, yet your guidance will be very much helpful for me as well as for the other beginners like me.

# Answer
> 0 votes
A microcontroller like an Arduino needs a constant source of regulated 5V (or 3.3V for some models.) The voltage of a solar panel varies depending on the amount of light, and in low light conditions there won't be enough power to run the Arduino.

So the short answer is no, you won't be able to run the Arduino reliably from a solar panel without a battery. You probably want a battery and a buck/boost voltage regulator that can convert a wide range of voltages to the 5V the Arduino needs.

What do you want the Arduino for? Temperature regulation? You'd probably be better off using a bimetallic thermostat that would turn the power to the Peltier pad on and off without needing electronics.

As for running a Peltier junction cooling pad from a solar panel, that should work. It would depend on the specs of the Peltier unit and of the panel. Again, you'll probably get the maximum cooling if you use a buck/boost voltage regulator to convert the variable output of your solar panel to a steady 12V. You'll need a big enough solar panel to provide the current that your Peltier pad needs.

All the talk about Peltier pads and solar panels is not Arduino-specific, however.

## Edit:

Research solar chargers for 12V batteries. Buy a solar panel made to charge a 12V battery. Make sure you select a solar panel that puts out enough current to run the Peltier panel at full power when it is in the sun. Ideally, select a solar panel that provides several times more current than needed to run the Peltier pad. That way the solar panel will charge the battery AND run the Peltier pad while the sun is shining, and when the sun is behind the clouds or at night, the Peltier pad will continue to run from the battery.

Start from that. Buy a buck/boost power supply that can convert a wide range of voltages to 5V. Use that to power the Arduino.

Buy a digital thermometer (like a DHT11 for example). Follow the instructions to wire it into your Arduino, and write a sketch that measures the temp in the thing you are trying to cool.

Buy a power MOSFET transistor that is made to work from a 5V logic signal. This one, for example: https://www.sparkfun.com/products/10213

Wire the MOSFET so a logic signal from one of the digital pins on the Arduino is connected to the gate of the MOSFET and it switches the power to the Peltier pad on and off. (You should be able to find a wiring diagram online.)

Write a sketch that measures the temp from the digital thermometer every few seconds, and turns on the power to the MOSFET if the temp rises above a threshold temp, and turns it off if it drops below a colder temp. (Say it turns on the MOSFET when the temp rises above 24°C, and turns the MOSFET off when the temp drops to 20°C. (This is really simple code to write.)

Note that if the battery gets too low, it won't provide enough power to the voltage regulator which supplies the Arduino and it will shut down. That will cause the Peltier pad to turn off. Once the solar panel charges the battery up enough, the voltage regulator will start providing 5V to the Arduino again, it will restart, your sketch will start running, and the cycle will continue. When the battery barely has enough power to drive the Arduino, it may restart the Arduino, try to turn on the Peltier pad, and immediately die again, every few seconds. That would be bad, and would put a lot of stress on all the electronics.

You might want to add a voltage sensor¹ to the battery and have the Arduino measure the battery voltage, and not try to power the Peltier pad unless and until the battery has a reasonable charge. Instead it would monitor the battery charge level and wait until there was enough power stored in the battery to run the Peltier pad. You could also have the Arduino detect that the battery charge level was getting low, and shut off the Peltier pad before it got too low.

A lead/acid battery would be a good choice since it's cheap, holds a lot of power, and it's easy to estimate the remaining power in a healthy lead/acid cell from its output voltage.

If you **do** use a lead-acid battery, it's important to add a battery charge level sensor and make your sketch avoid draining the battery too low. Lead-acid batteries are damaged when you discharge them too much.

## Edit #2:

You said in a comment to another answer that you're looking to provide small-scale cooling while traveling in a hot climate: The fact that you're trying to handle travel poses some interesting challenges, and perhaps some opportunities. If you're traveling in a car or truck you could tap the 12V power that is almost always available in a motor vehicle. If you don't have an external source of power then the shifting and turning you will likely experience while traveling will greatly reduce the efficiency of your solar panel. They only give maximum power when the panel is directly perpendicular to (or "normal to") the sun. As the angle of the panel to the sun shifts from the ideal angle the power output of your panel will drop significantly.

---

¹ A voltage sensor could be as simple as a voltage divider that reduces the input voltage from a max of a little under 14V down to 5 V, fed into an analog input on the Arudino. You might need to disconnect the solar panel input before measuring the battery charge level however, since input from the solar panel will make the battery voltage seem higher than it actually is. Also note that your battery charge level estimates are going to be crude, since you should really let a lead-acid battery rest with no input and no output for several minutes before taking a measurements in order to get an accurate reading.

# Answer
> 1 votes
Your first decision is to figure out the heat load on the space. How many BTU/hr you need to remove to keep the temperature you want. Then figure out how large / how many Peltier you need to remove that much heat. Do you need some reserve capacity for unusual circumstances or is a higher inside temperature Ok sometimes? Then you need a power budget - how much power will it take to remove that much heat with Peltier panels. How much PV area will you need to provide that power? If you need cooling when the sun isn't out, your power budget has to include the 24-hour demand, and the intermittent supply, perhaps again with some headroom. Power storage - batteries or the power grid - will be a requirement to match the two. The same storage can power your Arduino. The Arduino's power budget will be minuscule compared to the rest of the installation and you can totally ignore it. Do you have to power your internal network that connects the Arduino to the Internet, too? Figure that in. By this point, you'll have the answers to most of your questions. Just a heads-up: A Peltier beer-cooler is quite doable. A whole house A/C *might* be doable but no practical - you probably won't like the numbers! I'm guessing your project lies somewhere between the two.

---
Tags: arduino-nano, solar, peltier
---


# Question
Title: Multiple libraries were found for "WiFiClient.h" using nodemcu
I am trying to send HTTP requests from nodemcu so I started by uploading the esp8266 library but when I run the following code

```
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>

void setup() {

  Serial.begin(115200);                                  //Serial connection
  WiFi.begin("Iphone de elaa", "27343550");   //WiFi connection

  while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI connection completion

    delay(500);
    Serial.println("Waiting for connection");

  }

}

void loop() {

 if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status

   HTTPClient http;    //Declare object of class HTTPClient

   http.begin("http://localhost:8080/getallcadres/getnbpassage/5");      //Specify request destination
   http.addHeader("Content-Type", "text/plain");  //Specify content-type header

   int httpCode = http.POST("5");   //Send the request
   String payload = http.getString();                  //Get the response payload

   Serial.println(httpCode);   //Print HTTP return code
   Serial.println(payload);    //Print request response payload

   http.end();  //Close connection

 }else{

    Serial.println("Error in WiFi connection");

 }

  delay(30000);  //Send a request every 30 seconds

}

```

i got this error

```
Arduino: 1.8.9 (Windows Store 1.8.21.0) (Windows 10), Board: "Generic ESP8266 Module, 80 MHz, Flash, Disabled, All SSL ciphers (most compatible), ck, 26 MHz, 40MHz, DOUT (compatible), 512K (no SPIFFS), 2, nonos-sdk 2.2.1 (legacy), v2 Lower Memory, Disabled, None, Only Sketch, 115200"

Build options changed, rebuilding all
In file included from C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi\src/WiFiClientSecure.h:41:0,

                 from C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi\src/WiFiServerSecure.h:20,

                 from C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi\src/ESP8266WiFi.h:41,

                 from C:\Users\ELA_HIDRI\Desktop\PFE_ING\nodemcu\nodemcu.ino:2:

C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.h:38:5: error: 'BearSSL::WiFiClientSecure::~WiFiClientSecure()' marked override, but does not override

     ~WiFiClientSecure() override;

     ^

C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.h:41:9: error: 'int BearSSL::WiFiClientSecure::connect(const String&, uint16_t)' marked override, but does not override

     int connect(const String& host, uint16_t port) override;

         ^

C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.h:46:12: error: 'size_t BearSSL::WiFiClientSecure::write_P(const char*, size_t)' marked override, but does not override

     size_t write_P(PGM_P buf, size_t size) override;

            ^

C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi\src/WiFiClientSecureBearSSL.h:58:12: error: 'size_t BearSSL::WiFiClientSecure::peekBytes(uint8_t*, size_t)' marked override, but does not override

     size_t peekBytes(uint8_t *buffer, size_t length) override;

            ^

Multiple libraries were found for "WiFiClient.h"
 Used: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.21.0_x86__mdqgnx93n4wtt\libraries\WiFi
 Not used: C:\Users\ELA_HIDRI\Documents\ArduinoData\packages\esp8266\hardware\esp8266\2.5.2\libraries\ESP8266WiFi
exit status 1
Error compiling for board Generic ESP8266 Module.

```

so what is this error why i am getting it **Edit** i switched to an other version of arduino ide 1.6.5 the error is gone but it looks like it is not connection i got

# Answer
> 6 votes
Simply Switch

```
#include <ESP8266HTTPClient.h>
#include <ESP8266WiFi.h>

```

to

```
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

```

# Answer
> 0 votes
I am new to nodemcu. When I was using ESP8266WiFi.h, I got the error "Error compiling for board NodeMCU 1.0 (ESP-12E Module)" which said that Multiple libraries were found for ESP8266WiFi.h. I solved by simply put the void loop(){} empty function at the end of my code. Now It's working...

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


# Question
Title: Incompatible types in assignment of 'uint8_t {aka unsigned char}' to 'uint8_t [1] {aka unsigned char [1]}'
I'm trying to send custom data. But it doesn't seem to work. I can't find a way to parse my string to a unit8\_t. I tried to follow other people's solutions but they don't seem to work for me.

```
// Declaration
uint8_t myData[] = "";

void loop(){
    myData = *(uint8_t*)atoi("custom string".c_str());
}

```

This is the error message that I keep getting: Incompatible types in assignment of **uint8\_t {aka unsigned char}' to 'uint8\_t \[1\] {aka unsigned char \[1\]}** .

# Answer
`atoi` is for converting a textual representation of a number ("123" for example) into an actual integer.

The c\_str() function gives you a pointer to the internal buffer of the String (assuming you actually have a String) which is no different to a `uint8_t[]` or `uint8_t *` (other than the signedness).

Without knowing exactly what the destination function for this buffer requires it's very hard to help you, but you may want something like:

```
LoRaWan.send((uint8_t *)myString.c_str(), myString.length());

```

If you need to copy the data into a fixed length buffer then you need to first create a buffer of that actual size - then copy the string data into it:

```
// Create a buffer of 32 bytes
uint8_t myBuffer[32];
// Copy at most 32 bytes, but no more than there actually is, into the buffer
memcpy(myBuffer, myString.c_str(), min(myString.length(), 32));

```
> 0 votes

# Answer
Your code is a mess. It's clear you are badly confused between arrays, pointers, and C++ strings.

When you say

```
uint8_t myData[] = "";

```

you make myData of type "array of uint8\_t" and make it contain an empty string. You should not then change that value.

When you say

```
uint8_t *myData;

```

it means that `myData` is a variable of type "pointer to uint8\_t", but it doesn't point to anything yet.

With that declaration, you can later say:

```
myData = "custom string";

```

That points the `myData` pointer to the address of your constant string. I think that's what you want:

```
// Declaration
uint8_t *myData;

void loop(){
    myData = "custom string";
}

```
> 0 votes

# Answer
Firstly, arrays in C and C++ are not assignable. So, your attempts to assign something to `myData` array with `=` operator are bound to fail in any case. Copying data into naked arrays should be done either manually or using library functions.

Secondly, your `myData` array is declared with size `1`. It is just one byte. It is too small to store anything useful. It will not magically "stretch" by itself to accommodate more data. If you need to store more data in that array, it is your responsibility to declare with the appropriate size in advance.

Thirdly, what is `"custom string".c_str()` supposed to mean??? Something looking very similar to that can be expressed in modern C++ as

```
#include <string>
...
using namespace std::string_literals;
"custom string"s.c_str();

```

but I see no reason for that at all. If your input is a C-string, then function `atoi` is directly applicable to C-strings. No need to convert such C-string to `std::string` and then back.

Fourthly, `atoi` is a "dead" function that exists for compatibility with legacy code only. You are not supposed to use `atoi` in your code. A C-style string-to-number conversion functions are functions from `strto...` group. E.g. `strtol` in your case. But in C++ you might have better options, like `std::stoi` and such.
> 0 votes

---
Tags: arduino-ide, c++
---


# Question
Title: How many sensors can be used in arduino for my project?
I'm doing a project on water purity finder. I dont know which arduino board can be used for the project. It uses upto 15 sensor modules excluded display, WiFi module. Can you tell me which board is better for my project.

# Answer
It depends on what kind of sensors you're using. If you use I2C based sensors, and you can configure each with a separate I2C address, you could theoretically drive up to 128 of them. I say theoretically since you might not be able to push the signal across an I2C bus with that many devices on it. You could certainly manage 15 of them however.

The Mega 2560 has tons of I/O lines, so that might be a good choice if you need separate single lines for each sensor.

If you need a separate analog input for each of your sensors, you'd need to use an Arduino with at least 15 separate analog inputs. The Arduino Mega 2560 has 16, so that would work.

If you need 4 bit binary inputs, you'd need 4\*15 or 60 inputs. The Mega 2560 has 54 digital inputs, which would not be enough for that situation.

You might also be able to use some sort of signal multiplexer and enable one sensor at a time.

Tell us which type of sensor you're using and we can provide more concrete help.
> 1 votes

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


# Question
Title: Noise on piezo analog read due to Arduino power supply
I am making a device that measures temperature and vibrations and records the values onto an SD card. It will be a standalone device.

The hardware used: \- Arduino Uno \- PCF8523 RTC clock \- MAX3186 + PT100 RTD temperature sensor \- Adafruit data logger shield \- Typical bare piezo sensor

For the vibrations, a piezo sensor is used. Because it can produce a signal in two directions, I decided to use a voltage divider to offset the signal from GND. Two 5.1K resistors are connected from the piezo negative terminal to 5V and GND. A 1M resistor is placed in parallel with the piezo sensor. The positive terminal is connector to analog input 0.

The sensor is read 100 times per data point, the maximum and minimum values are stored and the final value is set to be the difference between the two (two times the amplitude).

**USB**

**9V wall adapter**

When the system is powered via a laptop USB port, the resting value has a jitter of a few bits. When a 9V wall adapter powers the arduino, the jitter is +/- 30 bits. Any small vibrations disappear in the noise.

**USB with piezo**

**9V with piezo**

**9V without piezo**

I would like some help to find the best way forward.

*edit 29-10 17:53 Added better plots*

*edit 30-10 17:53 Added plots for 2.5V and 3.3V lines*

# Answer
> 4 votes
The 9V wall adapter is in most cases a switched power regulator with a high frequency. That's like a radio transmitter direct beside the wire. So there is nothing mystical, when the smooth USB Voltage does not show problems but the "radio transmitter" does.

There are two ways the power supply can impact: over radio wave or as ripples over the regulated Voltage of your Arduino.

I asked myself, which one it is (or even both)? If you use the extra regulated analog voltage reference (AREF) as the +5V on your Voltage divider, it would be more likely that the problem comes through the air. Then it would help if you activate the shield of the wire by connecting it to GND.

If a rippled supply voltage is the problem, you have to smooth it. Perhaps with a low pass filter (a big Elko between Vcc and GND).

Perhaps you have a solenoid iron core. Then you can wrap the wire to the piezo sensor a few times around it (near the A0 Pin). This technique is often used in computer power supplies to prevent the switching frequencies from escaping to the public power lines.

# Answer
> 1 votes
In addition to what Peter Paul Kiefer suggests, you will also want to place an RC low-pass filter, between the piezo transducer, and the analog input.

You mention that you'll be sampling this value 100 times per second. So the cutoff frequency, for the filter, should be set to 50 Hz (the Nyquist frequency).

---
Tags: arduino-uno, sensors, analogread, piezo
---


# Question
Title: Making a timer accurate to 1 millisecond possible? Using MAX7219 LED
I'm using the Max7219 (8 digits, 7bits) led display to try and make a timer. I have downloaded an example code from the following site to set the led digits:

https://www.brainy-bits.com/arduino-countdown-timer-using-the-max7219-display/

However the original code simply loops as fast as possible and decriment the timer so it is not a true time. I tried to add a 10 ms delay to make it decriment 10ms on the right most digit so the 3rd digit to the right would be seconds, however I found this to be inaccurate and taking slightly longer than 1 second .

**My question is is it possible to make a timer with 1ms accuracy using led display and if so how do I do it?**

```
/* CountDown Timer version 2 using Max7219

Created by Yvan / https://Brainy-Bits.com
This code is in the public domain...
You can: copy it, use it, modify it, share it or just plain ignore it!
Thx!

*/

#define Max7219DIN 7  // Pin 7 connected to DIN (DataIN)
#define Max7219CLK 6  // Pin 6 connected to CLK
#define Max7219CS 5   // Pin 5 connected to CS

#define Buzzer 8  // Pin 8 connected to Buzzer +positive pin
int BuzzTrigger=0;  // Variable to store buzzer trigger value

#include "LedControl.h"  // LedControl Library created by Eberhard Fahle at http://playground.arduino.cc/Main/LedControl

LedControl lc=LedControl(Max7219DIN,Max7219CLK,Max7219CS,1);   // Last number represent the number of Max7219 Modules connected

long int countnumber=24001000 ; // Countdown timer start value HH:MM:SSSS

// Variables to store individual numbers
int  firstnum=0;
int  secondnum=0;
int  thirdnum=0;
int  fournum=0;
int  fivenum=0;
int  sixnum=0;
int  sevennum=0;
int  eightnum=0;

void setup() {
    lc.shutdown(0,false);  // Wake up the display
    lc.setIntensity(0,7); // Set Brightness 0-15
    lc.clearDisplay(0);  // Clear display
    pinMode(Buzzer, OUTPUT);
    digitalWrite(Buzzer, LOW);  //Buzzer Off at startup

}

void loop() {

    for (countnumber; countnumber != -1; countnumber--) {
        String mystring = String(countnumber); // Transform Counter Int to String for manipulation

        // Convert number to a time value
        for (int z = 0; z < 6; z++) {

            if (mystring.substring(z) == "999999") {
                countnumber = (countnumber - 400000);
            }

            if (mystring.substring(z) == "9999") {
                countnumber = (countnumber - 4000);
            }
        }

        //  Display number on Display depending on number of digits remaining
        if (countnumber > 9999999) {
            firstnum = ((countnumber / 10000000) % 10);
            secondnum = countnumber / 1000000 % 10;
            thirdnum = countnumber / 100000 % 10;
            fournum = countnumber / 10000 % 10;
            fivenum = countnumber / 1000 % 10;
            sixnum = countnumber / 100 % 10;
            sevennum = countnumber / 10 % 10;
            eightnum = countnumber % 10;

            lc.setDigit(0, 7, firstnum, false);
            lc.setDigit(0, 6, secondnum, false);
            lc.setDigit(0, 5, thirdnum, false);
            lc.setDigit(0, 4, fournum, false);
            lc.setDigit(0, 3, fivenum, false);
            lc.setDigit(0, 2, sixnum, false);
            lc.setDigit(0, 1, sevennum, false);
            lc.setDigit(0, 0, eightnum, false);
            delay(10); //<<<<<<<<<<< I ADDED THIS
        } else {
            if (countnumber > 999999) {
                //      firstnum = ((countnumber/10000000)%10);
                secondnum = countnumber / 1000000 % 10;
                thirdnum = countnumber / 100000 % 10;
                fournum = countnumber / 10000 % 10;
                fivenum = countnumber / 1000 % 10;
                sixnum = countnumber / 100 % 10;
                sevennum = countnumber / 10 % 10;
                eightnum = countnumber % 10;

                lc.setChar(0, 7, '-', false);
                lc.setDigit(0, 6, secondnum, false);
                lc.setDigit(0, 5, thirdnum, false);
                lc.setDigit(0, 4, fournum, false);
                lc.setDigit(0, 3, fivenum, false);
                lc.setDigit(0, 2, sixnum, false);
                lc.setDigit(0, 1, sevennum, false);
                lc.setDigit(0, 0, eightnum, false);
                delay(10); //<<<<<<<<<<< I ADDED THIS
            } else {
                if (countnumber > 99999) {
                    //          firstnum = ((countnumber/10000000)%10);
                    //          secondnum = countnumber/1000000%10;
                    thirdnum = countnumber / 100000 % 10;
                    fournum = countnumber / 10000 % 10;
                    fivenum = countnumber / 1000 % 10;
                    sixnum = countnumber / 100 % 10;
                    sevennum = countnumber / 10 % 10;
                    eightnum = countnumber % 10;

                    lc.setChar(0, 7, '-', false);
                    lc.setChar(0, 6, '-', false);
                    lc.setDigit(0, 5, thirdnum, false);
                    lc.setDigit(0, 4, fournum, false);
                    lc.setDigit(0, 3, fivenum, false);
                    lc.setDigit(0, 2, sixnum, false);
                    lc.setDigit(0, 1, sevennum, false);
                    lc.setDigit(0, 0, eightnum, false);
                    delay(10); //<<<<<<<<<<< I ADDED THIS
                } else {
                    if (countnumber > 9999) {
                        //             firstnum = ((countnumber/10000000)%10);
                        //             secondnum = countnumber/1000000%10;
                        //             thirdnum = countnumber/100000%10;
                        fournum = countnumber / 10000 % 10;
                        fivenum = countnumber / 1000 % 10;
                        sixnum = countnumber / 100 % 10;
                        sevennum = countnumber / 10 % 10;
                        eightnum = countnumber % 10;

                        lc.setChar(0, 7, '-', false);
                        lc.setChar(0, 6, '-', false);
                        lc.setChar(0, 5, '-', false);
                        lc.setDigit(0, 4, fournum, false);
                        lc.setDigit(0, 3, fivenum, false);
                        lc.setDigit(0, 2, sixnum, false);
                        lc.setDigit(0, 1, sevennum, false);
                        lc.setDigit(0, 0, eightnum, false);
                        delay(10);//<<<<<<<<<<< I ADDED THIS
                    } else {
                        if (countnumber > 999) {
                            //              firstnum = ((countnumber/10000000)%10);
                            //              secondnum = countnumber/1000000%10;
                            //              thirdnum = countnumber/100000%10;
                            //              fournum = countnumber/10000%10;
                            fivenum = countnumber / 1000 % 10;
                            sixnum = countnumber / 100 % 10;
                            sevennum = countnumber / 10 % 10;
                            eightnum = countnumber % 10;

                            lc.setChar(0, 7, '-', false);
                            lc.setChar(0, 6, '-', false);
                            lc.setChar(0, 5, '-', false);
                            lc.setChar(0, 4, '-', false);
                            lc.setDigit(0, 3, fivenum, false);
                            lc.setDigit(0, 2, sixnum, false);
                            lc.setDigit(0, 1, sevennum, false);
                            lc.setDigit(0, 0, eightnum, false);
                            delay(10);//<<<<<<<<<<< I ADDED THIS
                        } else {
                            //              firstnum = ((countnumber/10000000)%10);
                            //              secondnum = countnumber/1000000%10;
                            //              thirdnum = countnumber/100000%10;
                            //              fournum = countnumber/10000%10;
                            //              fivenum = countnumber/1000%10;
                            sixnum = countnumber / 100 % 10;
                            sevennum = countnumber / 10 % 10;
                            eightnum = countnumber % 10;
a
                            lc.setChar(0, 7, '-', false);
                            lc.setChar(0, 6, '-', false);
                            lc.setChar(0, 5, '-', false);
                            lc.setChar(0, 4, '-', false);
                            lc.setChar(0, 3, '-', false);
                            lc.setDigit(0, 2, sixnum, false);
                            lc.setDigit(0, 1, sevennum, false);
                            lc.setDigit(0, 0, eightnum, false);
                            delay(10);//<<<<<<<<<<< I ADDED THIS
                        }

                    }
                }
            }
        }

    }
}

```

new implementation using millis

```
#define Max7219DIN 7  // Pin 7 connected to DIN (DataIN)
#define Max7219CLK 6  // Pin 6 connected to CLK
#define Max7219CS 5   // Pin 5 connected to CS

#include "LedControl.h"  // LedControl Library created by Eberhard Fahle at http://playground.arduino.cc/Main/LedControl

LedControl lc=LedControl(Max7219DIN,Max7219CLK,Max7219CS,1);   // Last number represent the number of Max7219 Modules connected

unsigned long countnumber;

// Variables to store individual numbers
int  firstnum=0;
int  secondnum=0;
int  thirdnum=0;
int  fournum=0;
int  fivenum=0;
int  sixnum=0;
int  sevennum=0;
int  eightnum=0;

void setup() {
  lc.shutdown(0,false);  // Wake up the display
  lc.setIntensity(0,7); // Set Brightness 0-15
  lc.clearDisplay(0);  // Clear display
  Serial.begin(9600);
}

void loop() {

  countnumber = millis();

  firstnum = countnumber / 10000000 % 10;
  secondnum = countnumber / 1000000 % 10;
  thirdnum = countnumber / 100000 % 10;
  fournum = countnumber / 10000 % 10;
  fivenum = countnumber / 1000 % 10;
  sixnum = countnumber / 100 % 10;
  sevennum = countnumber / 10 % 10;
  eightnum = countnumber % 10;

  lc.setDigit(0, 7, firstnum, false);
  lc.setDigit(0, 6, secondnum, false);
  lc.setDigit(0, 5, thirdnum, false);
  lc.setDigit(0, 4, fournum, false);
  lc.setDigit(0, 3, fivenum, false);
  lc.setDigit(0, 2, sixnum, false);
  lc.setDigit(0, 1, sevennum, false);
  lc.setDigit(0, 0, eightnum, false);

}

```

# Answer
You generally cannot rely on a processor for correct time keeping without a real time clock somewhere in your circuit. However, the best way of doing things at certain times, is to call millis() which will return the number of milliseconds since the program started. With that number you can determine how long something has taken (eg. 1 second) and then do something in response. You can, for example, print out how long your loop is taking by setting a long integer to millis() at the start of the sketch and then subtracting it from mills() at the end of the loop and printing out the result.

```
void loop() {
   long start_time = millis();
   delay(500);
   long end_time = mills();
   Serial.println(end_time - start_time);
}

```
> 1 votes

---
Tags: timers, max7219
---


# Question
Title: Help to delimit and read specific contents of incoming HTTP string
I am sending strings to an Esp8266 via web browser.

The below code returns the following in serial monitor if I send in browser:

Send from browser to esp8266 - http://192.168.1.220/s1s2s3s4s5d1
Receive in Arduino Serial monitor - GET /s1s2s3s4s5d2 HTTP/1.1

How do i read only the contents s1s2s3s4s5d1 ? This content can vary in length, numbers could be double digits but alphabets will remain in between.

Please note I am still a novice.

```
// Read the first line of the request
String request = client.readStringUntil('\r');
Serial.println(request);
client.flush();

```

# Answer
I have this

```
if (client.connected()) {
  if (client.available() && client.find(' ')) { // GET /fn HTTP/1.1
    char fn[20];
    int l = client.readBytesUntil(' ', fn, sizeof(fn));
    fn[l] = 0;
    while (client.read() != -1);
    Serial.println(fn);
    client.stop();
  }
}

```
> 1 votes

# Answer
you can try something like this

```
int first_space = request.indexOf(' '); // location of the first space
int second_space = request.indexOf(' ', first_space); // the next space after first

String query_arg = request.substring(first_space,second_space);

```
> 0 votes

---
Tags: esp8266, nodemcu, string, serial-data
---


# Question
Title: Serial communication from Arduino to ESP8266 NodeMCU works, but from NodeMCU to Arduino isn't working
My circuit connection is like: (I am following this tutorial)

Code uploaded to Arduino:

```
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
SoftwareSerial s(5,6);

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

void loop() {
  StaticJsonBuffer<1000> jsonBuffer;
  JsonObject& root = jsonBuffer.createObject();
  root["data1"] = 100;
  root["data2"] = 200;
  if(s.available()>0){
    root.printTo(s);
  }
}

```

Code uploaded to NodeMCU:

```
#include <SoftwareSerial.h>
int D5 = 14, D6 = 12;
SoftwareSerial s(D6,D5);
#include <ArduinoJson.h>

void setup() {
  // Initialize Serial port
  Serial.begin(9600);
  s.begin(9600);
  while (!Serial) continue;
}

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

 Serial.println("JSON received and parsed");
 root.prettyPrintTo(Serial);
 Serial.print("Data 1 ");
 Serial.println("");
 int data1=root["data1"];
 Serial.print(data1);
 Serial.print("   Data 2 ");
 int data2=root["data2"];
 Serial.print(data2);
 Serial.println("");
 Serial.println("---------------------xxxxx--------------------");
}

```

Arduino sends JSON data and NodeMCU parses it as expected.

--------Till this everything is fine. ---------

But my requirement is vice versa. When I create JSON object in nodeMcu and try to parse in arduino, JSON not received.

This time I wrote this code in nodeMcu:

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

int D5 = 14, D6 = 12;
SoftwareSerial s(D6,D5);

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

void loop() {
 StaticJsonBuffer<1000> jsonBuffer;
 JsonObject& root = jsonBuffer.createObject();
 root["data1"] = 100;
 root["data2"] = 200;
 if(s.available()>0){
   root.printTo(s);
 }
}

```

And code in Arduino:

```
#include <SoftwareSerial.h>
#include <ArduinoJson.h>
SoftwareSerial s(5,6);

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

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

  Serial.println("JSON received and parsed");
  Serial.print("Data 1 : ");
  int data1=root["data1"];
  Serial.println(data1);
  Serial.print("Data 2 : ");
  int data2=root["data2"];
  Serial.println(data2);
  Serial.println("---------------------xxxxx--------------------");
 }

```

This code doesn't work. I don't receive anything in serial monitor of arduino. The circuit connection remains the same as before.

Anymore information should I provide ? What modification do I need?

# Answer
> -1 votes
The problem may stem from Arudino boards being 5v logic pins while ESP boards are 3.3v logic pins. 3.3v high might not be enough for Arduino to see the data.

---
Tags: arduino-uno, serial, esp8266, softwareserial, json
---


# Question
Title: Using Library LoRa.h with Wemos D1 R2 for Lora Shield
I have been using Lora Shield for communication between server and multiple sensor with arduino . But recently i must save data received to Cloud . So i choose Wemos D1 R2 that have similar board with arduino . But when i upload example code , LoraReceiver can'nt get data . Can Anyone Solve my problem ?

# Answer
When you change boards you must also update your pin connections in software. When you initialize the Lora Shield, you probably specify a few data pins. Those pin numbers cannot be assumed to remain the same on the new ESP8266 based board. Furthermore, the ESP8266 board is 3.3v logic while Arduinos are 5v logic so you must ensure that the shield and sensors will also work with 3.3v.
> 0 votes

---
Tags: arduino-uno, esp8266
---


title: Print string and integer LCD

text:
# Question
Title: Print string and integer LCD
How do I print a string and integer on an LCD? Here is what I have tried:

```
int number = 2;
int result = (number + number);
lcd.print(number, DEC + " plus " + number, DEC + " equals " + result, DEC);

```

And the result is an error. When I try:

```
lcd.print(number + "look");

```

or

```
lcd.print("1234 " + number);

```

Then the result on the LCD is "34 ", as it deleted the first two numbers!

I want it to print:

1234 2

Please help! Thanks!

# Answer
> 6 votes
The `lcd.print()` method takes a string or a number as an argument, but not both at once. Using the + operator for concatenation is not native to C strings. C strings are basically stored as pointers to the first character of the string. So when you tried `lcd.print("1234 " + number)` and got `"34 "`, what most likely happened is that you advanced the pointer, pointing to the first character of `"1234 "`(i.e. '1') by `number` (i.e. 2), thus making the pointer point to the **3rd** character in the string and thus making `lcd.print()` display `"34 "`. In order to print something that contains both strings and integers, the most straightforward way is to convert each piece to an Arduino string and then concatenate them, using the + operator like you did earlier.

```
    lcd.print(String("1234 ") + String(number));
    lcd.print(String(number) + String(" plus ") + String(number) + String(" equals ") + String(result));

```

These are some examples. You could also use create a sufficiently large `char` buffer and use `sprintf()` from `stdio.h` to build a string made up of integers and strings. Look up a textbook on C/C++ for more details.

# Answer
> 2 votes
I got the same problem and I printed the string and the integer on the same line by moving the cursor like this :

```
   lcd.setCursor(0, 0);    <----------Column 0 , Line 1
   lcd.print("This code failed");
   lcd.setCursor(0, 1);    <----------Column 0 , Line 2
   lcd.print("Error Code = ");
   lcd.setCursor(13, 1); <-change the cursor for the INT. Column 13 , Line 2
   lcd.print(int);

```

# Answer
> 0 votes
What is wrong with this:

```
lcd.print(number, DEC + " plus " + number, DEC + " equals " + result, DEC);

```

It is the number of parameters and the assumption that plus will concatenate string literals.

```
lcd.print("1234 " + number);

```

This gives "34 " when number is 2. Why? This is because that is the result of adding 2 to the string literal pointer, i.e. the string starting at the character "3". Please use separate print statements instead:

```
lcd.print("1234 ");
lcd.print(number);

```

Do not use String to concatenate strings. That is a waste of SRAM, processing and has a risk of heap fragmentation. Simply a bad idea in small scale embedded systems such as AVR.

To understand these errors you should go back and read about strings and string literals in C/C++ (compared to Java :).

Cheers!

# Answer
> 0 votes
```
int a=0;
float b=10.01;

char str[16];

sprintf(str,"a=%d, b=%.2f, c=%d", a, b, 2); // use sprintf() to compose the string str

lcd.print(str);

```

The output will be 'a=0, b=10.01, c=2'

---
Tags: arduino-uno, programming, lcd
---


title: LED Blinking Using Push button

text:
# Question
Title: LED Blinking Using Push button
Whenever I upload the following program I am getting error message showing "expected initializer before interval".

Kindly Help me to solve out this probleme.

```
const byte button=2;
const byte LED=10;
bool blinking =false;//defines when blinking should occur
unsigned long blink Interval=250;// number of milliseconds for blink
unsigned long currentMillis;// variables to track millis()
unsigned long previousMillis;
void setup()
{
    pinMode(button,INPUT);
    pinMode(LED,OUTPUT);
}
void loop()
{
    // this code  blinks the LED
    if(blinking) {
        currentMillis =millis();// better to store in variable, for less jitter

        if((unsignedlong)(currentMillis-previousMillis) >=blinkInterval) { // enough time passed yet?
            digitalWrite(LED,!digitalRead(LED)); // shortcut to toggle the LED
            previousMillis =currentMillis;// sets the time we wait "from"
        }
    } else {
        digitalWrite(LED,LOW); // force LED off when not blinking
    }

    int reading=digitalRead(button);
    delay(50); // crude de-bouncing

    if(reading==LOW) // buttons with pull-up are pressed when LOW
    { blinking =true; }// start blinking
    else
    { blinking =false; }// stop blinking
}

```

# Answer
> 3 votes
It is `blinkInterval`, not `blink Interval`. You have an space in the name in the declaration:

```
unsigned long blinkInterval=250; // number of milliseconds for blink
// ....
if((unsigned long)(currentMillis-previousMillis) >= blinkInterval) {

```

# Answer
> 0 votes
The fully working sketch

```
const byte button=2;
const byte LED=10;
bool blinking =false;
unsigned long blinkInterval=250;
unsigned long currentMillis;
unsigned long previousMillis;
void setup()
{
    pinMode(button,INPUT);
    pinMode(LED,OUTPUT);
}
void loop()
{

    if(blinking) {
        currentMillis =millis();

        unsigned long blinkInterval=100;
        if((unsigned long)(currentMillis-previousMillis) >= blinkInterval) {
            digitalWrite(LED,!digitalRead(LED)); LED
            previousMillis =currentMillis;
        }
    } else {
        digitalWrite(LED,LOW);
    }

    int reading=digitalRead(button);
    delay(100);

    if(reading==LOW)
    { blinking =true; }
    else
    { blinking =false; }
}

```

---
Tags: programming, code-review
---


# Question
Title: OLED display hectic behavior - interference with other parts of the code?
Disclaimer: I'm a total novice to Arduino so please forgive me if the question may seem trivial, I'm trying my best to learn :)

I'm working on a small project where I have a fingerprint sensor, a servo and an OLED display. The goal is to be able to register a fingerprint and then use the fingerprint to move the servo, whilst the OLED display gives instruction / messages to the user.

I noticed a few days ago an issue whereby my OLED wouldn't simply stop working if I had some Serial.println in my code. Without understanding the root cause, by trial and error I got to the conclusion that the issue was with that specific function, so I proceeded to remove it and everything went ok.

Then I noticed that the display stopped working also by adding extremely simple pieces of code that should not be related in ANY way to how the OLED works (at least to the best of my very limited knowledge).

The code below works as expected, each and every call to the oledPrint function yields the expected result on the OLED itself.

```
#include <EEPROM.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_RESET);

#include <Adafruit_Fingerprint.h>
#include <SoftwareSerial.h>

#define ISPRESSED LOW
#define BASE_MAX 200
#define MASTER_MAX 200

SoftwareSerial mySerial(2, 3);

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);

uint8_t id;

const int buttonRegisterPin = 8; // the number of the pushbutton pin - NOTE: RED BUTTON
const int buttonRegisterMasterPin = 7; // the number of the pushbutton pin - NOTE: GREEN BUTTON
const int buttonClearPin = 6; // the number of the pushbutton pin - NOTE: BLACK BUTTON
const int buttonClearMasterPin = 12; // the number of the pushbutton pin - NOTE: YELLOW BUTTON

const int baseState = HIGH;
int ledStatus = HIGH;

int baseCount;
int masterCount;

void setup() {
  //Serial.begin (9600);
  Serial.begin (115200);

  //initialize counters
  initializeCounters();

  //initialize buttons
  initializeButton(buttonRegisterPin);
  initializeButton(buttonRegisterMasterPin);
  initializeButton(buttonClearPin);
  initializeButton(buttonClearMasterPin);

  //initialize the fingerprint sensor
  initializeFingerPrintSensor();

  //initialize the OLED display
  initializeOledDisplay();

}

void loop() {

  bool skip = false;
  oledPrint("Welcome to your fingerprint locker");
  //base registration case
  if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){

    while(!baseRegistration());
    skip = true;
  }

  //master registration case
  if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){

    while(!masterRegistration());
    skip = true;
  }

  //base clear case
  if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
    clearRegistrations(false);
    //do stuff for base clear
    skip = true;
  }

  //master clear case
  if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){

    //do stuff for master clear
    skip = true;
  }
}

/**
 * Initializes a button
 * @Param: buttonPin = number of the pin used by the button
 */
void initializeButton(int buttonPin){
  pinMode(buttonPin, INPUT_PULLUP);
}

/**
 * Initializes the OLED display
 */
void initializeOledDisplay(){
  Wire.begin();
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  delay(2000);
  display.clearDisplay();

  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0, 10);
}

/**
 * initializes the fingerprint sensor
 */
void initializeFingerPrintSensor(){
  finger.begin(57600);

  if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  }
  else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }
}

boolean baseRegistration(){
  boolean check = false;
  int tempBaseCount = baseCount + 1;
/*
  if(tempBaseCount > BASE_MAX){
    oledPrint("Too many users already registered");
    return true;
  }*/
  oledPrint("Starting registration");
  while(check == false){

    oledPrint("Please put your finger on the reader");

    id = tempBaseCount;
    if (id == 0) {// ID #0 not allowed, try again!
       return;
    }

    if(getFingerprintEnroll(tempBaseCount, false)){
      check = true;
    }
  }
  return check;
}

boolean masterRegistration(){
  boolean check = false;
  int tempMasterCount = baseCount + 1;
/*
  if(tempMasterCount > MASTER_MAX){
    oledPrint("Too many master keys already registered");
    return true;
  }
  */
  oledPrint("Starting master key registration");

  while(check == false){

    oledPrint("Please put your finger on the reader");

    id = tempMasterCount;
    if (id == 0) {// ID #0 not allowed, try again!
       return;
    }

    if(getFingerprintEnroll(tempMasterCount, true)){
      check = true;
    }
  }
  return check;
}

boolean clearRegistrations(bool master){
  if(master){
    //to do
  }
  else{
    //increaseBaseCounter(0);
    id = 900;
    int p = finger.deleteModel(id);
    if(p == FINGERPRINT_OK){
     // Serial.println("success");
     // Serial.println(p);
      return true;
    }
   // Serial.println("FAIL");
   // Serial.println(p);
    return false;
  }
}

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

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

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

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

uint8_t getFingerprintEnroll(int count, bool master) {
  int p = -1;
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
    case FINGERPRINT_OK:
      //oledPrint("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      oledPrint("Communication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      oledPrint("Imaging error");
      break;
    default:
      oledPrint("Unknown error");
      break;
    }
  }

  // OK success!

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

  oledPrint("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  p = -1;
  oledPrint("Place the same finger again");
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
    case FINGERPRINT_OK:
      //oledPrint("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      oledPrint("Comunication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      oledPrint("Imaging error");
      break;
    default:
      oledPrint("Unknown error");
      break;
    }
  }

  // OK success!

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

  // OK converted!

  //oledPrint2Lines("Creating model number:", count);

  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    //oledPrint("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    oledPrint("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    oledPrint("Fingerprints did not match");
    return p;
  } else {
    oledPrint("Unknown errro");
    return p;
  }

  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    if(master == false){
      oledPrint2Lines("Registered with id number:", count);
      increaseBaseCounter(count);
    }
    else{
      oledPrint2Lines("Registered master key number:", count - 50);
      increaseMasterCounter(count);
    }
    return 1;
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    oledPrint("Communication error");
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    oledPrint("Could not store in that location");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    oledPrint("Error writing to flash");
    return p;
  } else {
    oledPrint("Unknown error");
    return p;
  }
}

uint8_t readnumber(void) {
  uint8_t num = 0;

  while (num == 0) {
    while (! Serial.available());
    num = Serial.parseInt();
  }
  return num;
}

void oledPrint(char* text){

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println(text);
  display.display();
  delay(2000);
}

void oledPrint2Lines(char* text, int val){

  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.print(text);
  display.print(val);
  display.display();
  delay(2000);
}

void initializeCounters(){
  //address 0 is BASE
  baseCount = EEPROM.read(0);
  Serial.println(baseCount);
  //address 1 is MASTER
  masterCount = EEPROM.read(1);
  if(masterCount < 50)
    masterCount = 50; //will get to 51 once first registered - 51 = master key #1
  Serial.println(masterCount);
}

void increaseBaseCounter(int count){
  baseCount = count;
  EEPROM.write(0, baseCount);
}

void increaseMasterCounter(int count){
  masterCount = count;
  EEPROM.write(1, masterCount);
}

```

However, if I uncomment the code in the baseRegistration and/or masterRegistration functions (see code snippet below), the display starts to act up: some text is displayed, some other isn't, some other again is displayed partially. I just can't find a sensible explanation anywhere, and being used to work on much higher abstraction levels this is to me completely absurd :D

```
boolean baseRegistration(){
  boolean check = false;
  int tempBaseCount = baseCount + 1;
//PART THAT CAUSES ISSUES - STARRT
  if(tempBaseCount > BASE_MAX){
    oledPrint("Too many users already registered");
    return true;
  }
//PART THAT CAUSES ISSUES - END
  oledPrint("Starting registration");
  while(check == false){

    oledPrint("Please put your finger on the reader");

    id = tempBaseCount;
    if (id == 0) {// ID #0 not allowed, try again!
       return;
    }

    if(getFingerprintEnroll(tempBaseCount, false)){
      check = true;
    }
  }
  return check;
}

```

Even more oddly, if I remove the part above from those two functions and I had one more simple call to the fingerprint sensor in the loop function, the OLED just stops working altogether (and again, absolutely crazy for me :P). See below the loop function with the addition of the line that breaks the OLED altogether:

```
void loop() {

  bool skip = false;
  oledPrint("Welcome to your fingerprint locker");
  //base registration case
  if(digitalRead(buttonRegisterPin) == ISPRESSED && skip == false){

    while(!baseRegistration());
    skip = true;
  }

  //master registration case
  if(digitalRead(buttonRegisterMasterPin) == ISPRESSED && skip == false){

    while(!masterRegistration());
    skip = true;
  }

  //base clear case
  if(digitalRead(buttonClearPin) == ISPRESSED && skip == false){
    clearRegistrations(false);
    //do stuff for base clear
    skip = true;
  }

  //master clear case
  if(digitalRead(buttonClearMasterPin) == ISPRESSED && skip == false){

    //do stuff for master clear
    skip = true;
  }

  int fingerprintID = getFingerprintIDez(); //THIS IS THE LINE
  delay(50);

}

```

I just don't know how to proceed, if any of you would be so kind to help a novice out I'd be extremely grateful! Thanks in advance to anyone who could point me in the right direction!!

For the sake of completeness, I'm using the adafruit libraries for the fingerprint sensor as well as the oled.

# Answer
Your program seems to fit well inside the Arduino Uno memory. If your output is displaying correctly through the serial monitor, there also seems nothing wrong with your data sent to the display. Have you tried connecting pull-up resistors to the SDA and SCL lines? Resistors around 3.9k work fine for me when using OLED displays.
> 1 votes

---
Tags: arduino-uno, i2c
---


# Question
Title: Strange compiler error (Segmentation Fault)
You're getting a compiler error. It happens in strange parts of code that really shouldn't be having a problem. The error looks something like:

```
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.15.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp:203:1: internal compiler error: Segmentation fault

}

^

Please submit a full bug report,

with preprocessed source if appropriate.

See http://gcc.gnu.org/bugs.html for instructions.

lto-wrapper.exe: fatal error: C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.15.0_x86__mdqgnx93n4wtt\hardware\tools\avr/bin/avr-gcc returned 1 exit status

compilation terminated.

c:/program files/windowsapps/arduinollc.arduinoide_1.8.15.0_x86__mdqgnx93n4wtt/hardware/tools/avr/bin/../lib/gcc/avr/5.4.0/../../../../avr/bin/ld.exe: error: lto-wrapper failed

collect2.exe: error: ld returned 1 exit status

```

What is it, and how do you fix it?

# Answer
This is a known fault with the compiler in Windows. The annoying thing is that it's the version of the compiler that is included in the Windows Store App version of the Arduino IDE.

It also snuck into the Windows version of the IDE from version 1.8.6 from the Arduino.cc website, with the bundled version of the Arduino AVR core.

There are numerous Github issues open for the problem and navigating the tangled web of them is a bit of a chore, but this one seems to be the most promising for digging into the root cause:

The simplest fix is to downgrade your compiler to 4.9.2. This can be done by using the Boards Manager to install version **1.6.21** of the **Arduino AVR Boards**. This should give you compiler version `4.9.2-atmel3.5.4-arduino2` which doesn't suffer from the problem.
> 3 votes

# Answer
I've been having this kind of error off and on lately for no apparent reason. What eliminated it for me was going into the IDE preferences and changing compiler output to verbose and also show all warnings. What??? I know it's crazy. I was just trying to get more information about the error, but I haven't gotten it since. And I was getting it a lot before.
> 2 votes

# Answer
Sometimes it seems like I have to reboot my PC, as exiting from Arduino and rerunning still doesn't always allow me to compile again.

> > "changing compiler output to verbose and also show all warnings"

This worked for me too.
> 0 votes

# Answer
I put back the settings to its default state again, after a restart and compile. It worked. Not sure whats under this?
> 0 votes

---
Tags: compilation-errors, faq
---


title: Is if statement correct?

text:
# Question
Title: Is if statement correct?
```
if(temperature < baselineTemp)else{
  digitalWrite(2, LOW);
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
}else if(temperature >= baselineTemp+2 && temperature < baselineTemp+4){
  digitalWrite(2, HIGH)
  digitalWrite(3, LOW)
  digitalWrite(4, LOW)
}else if(temperature >= baselineTemp+4 && temperature < baselineTemp+6){
  digitalWrite(2, HIGH)
  digitalWrite(3, HIGH)
  digitalWrite(4, LOW)
}else if(temperature >= baselineTemp+6){
  digitalWrite(2, HIGH)
  digitalWrite(3, HIGH)
  digitalWrite(4, HIGH)

```

# Answer
No, the first lines should be:

```
if(temperature < baselineTemp) {
  digitalWrite(2, LOW);

```

Thus the `else` should be removed; after the first `if` and later `else` or `else if` conditions, statements can be placed.

Next time align your code by selecting it and select ctrl-K.

Also, your code can be much more simplified.

Hence the following (reverse engineered) requirements:

* pin 2 is HIGH when temperature \>= baselineTemp + 2, else LOW
* pin 3 is HIGH when temperature \>= baselineTemp + 4, else LOW
* pin 4 is HIGH when temperature \>= baselineTemp + 4, else LOW

So your entire code can be written as:

```
digitalWrite(2, temperature >= baselineTemp + 2 ? HIGH : LOW);
digitalWrite(3, temperature >= baselineTemp + 4 ? HIGH : LOW);
digitalWrite(4, temperature >= baselineTemp + 6 ? HIGH : LOW);

```
> 1 votes

---
Tags: arduino-uno, programming, c
---


# Question
Title: Using 8bit ports as 8bit I/O variable (while using USB,I2C, SPI and Serial) - keyboard
**I am seeking HW.**

I would like to make keyboard with enhanced functions (RGB backlite, macros, programmed profiles etc) driven by some small MCU (Arduino Micro Pro or something similar).

To support communication, it needs to use **I2C** and **SPI**(for display and other devices), use **USB** (to communicate with PC) and use **Serial** to communicate with other Arduinos/MCUs.

The main function would be scanning keyboard matrix (like from 8x8 to 16x8 in maximal variant). The matrix would use diodes for NKRO (not ghosting, any key combination possible).

It would be really nice to have HW, where I could use 3 full ports as input (or as output) with benefit of reading/writing them with only one assembly instruction for 8bit manipulation, not to cycle over array of pins and manipulate each one independently (digitalRead/digitalWrite, which use tons of instructions to determine ports and pin and then combine them together to obtain one 8bit variable). Something like:

```
byte dataout,datain1,datain2;
PORT_A=dataout;
datain1=PORT_B;
datain2=PORT_C;

```

**Does anyone know, if there is such nonexpensive MCU and which type it is?**

On typical Arduino each port is "poluted" by some importaint communications pins, so none of them can be used as full 8bit I/O.

**Second question: Is there a reason, why are the most used communication pins spread over range of different ports and not collected on one port, while leaving other ports as full 8bit GPIO useable?**

Thank for all answers.

# Answer
I'd go with a Mega2560. Up to 86 IO if you use a board that breaks out all IO pins, otherwise 70 on the Arduino version. With a little attention to the physical chip pin mapping to the board you can have several full 8-bit ports while also using SPI, I2C, and Serial via one of 4 UARTs. I'd recommend keeping Tx(0)/Rx(0) free for comm's with PC via USB adapter for code download/debug. Tx1/Rx1, Tx2/Rx2, Tx3/Rx3 are them free for 0/5V level comm's, or other levels via USB adapter, RS232 adapter, etc.
> 1 votes

# Answer
The expander MCP23S17 (spi), with a CS, is a good extention (16 I/O configurable) That should do it !
> 1 votes

---
Tags: hardware
---


# Question
Title: Is analogWrite() not affected by blocking codes and/or Interrupts?
Well just as the question say, is the analogWrite() function will continue generating near-consistent PWM when it encounters blocking codes or signal interrupts?

Is it the same case for both the classic arduinos(atmega chips) and the new arduinos(SAMD21 chips).

If analogWrite() does get affected by blocking codes, is there a way to create a uninterruptible PWM signal?

# Answer
> is the analogWrite() function continue generating near-consistent PWM when it encounters blocking codes or signal interrupts?

Yes for 'hardware' PWM used by analogWrite on AVR and SAMD Arduinos. The hardware PWM is handled by wave output of Timers, which are MCU peripherals running independently from CPU and other MCU peripherals.

> Is it the same case for both the classic arduinos(atmega chips) and the new arduinos(SAMD21 chips).

yes

> If analogWrite() does get affected by blocking codes, is there a way to create a uninterruptible PWM signal?

N/A
> 3 votes

---
Tags: analogwrite
---


# Question
Title: Setting a number inside a struct causes timer to misbehave
The following code:

```
struct l{
    uint8_t pin;
    uint8_t sensePin;
    float brightnessTarget;
    uint8_t PWMvalue;
    uint8_t inc;
};
typedef struct l led;

led* redLed;
led* whiteLed;
unsigned long secondsOfDay = 79140;
unsigned long minutesOfDay = 0;
unsigned int hoursOfDay = 0;
uint8_t interrupted=0;
uint8_t runPID;
int pin13=0;

void setup() {
  cli();
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;//initialize counter value to 0
  // set compare match register for 1hz increments
  OCR1A = OCR1A_val;// = (16*10^6) / (1*1024) - 1 (must be <65536)
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS10 and CS12 bits for 1024 prescaler
  TCCR1B |= (1 << CS12) | (1 << CS10);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  pinMode(13,OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  sei();
}

void loop() {
  if (runPID){
    PIControl(redLed);
    PIControl(whiteLed);
    pin13 = (~pin13 & 1);
    digitalWrite(13, pin13);
    runPID=0;
  }
}

SIGNAL(TIMER1_COMPA_vect){ //1 second timer fire
  runPID = 1;
}

```

Toggles a pin. However, if I add:

```
redLed->pin = 3;
whiteLed->pin = 4;
redLed->sensePin = 0;
whiteLed->sensePin = 1;

```

In the setup anywhere (before cli(), after sei(), or within the block), the interrupt no longer toggles.

I'm absolutely baffled, and I have no idea what's going on.

Edit: everything but whiteLed-\>sensePin is fine. That line is what is causing the issue (and I still don't understand)

# Answer
This:

```
led* redLed;

```

defines a global variable implicitly initialized to zero (i.e. a NULL pointer). This is an invalid pointer you are not allowed to use until you properly initialize it.

Here:

```
redLed->pin = 3;

```

you are writing to the memory pointed to by this invalid pointer. This invokes what the C and C++ standards call *undefined behavior*. What that means is that, according to the definition of the C++ language, the behavior of your program is not defined. In other words, *anything* can happen. Typically you get a program crash, but even that behavior is not guaranteed.

Do not ever access memory through an invalid pointer.
> 1 votes

---
Tags: interrupt
---


# Question
Title: Can't use Arduino nano as ISP because it can't read the Device signature
I programmed the 8mhz internal oscillator Bootloader to a new Arduino Nano with another Arduino nano running the ISP Sketch, wich worked fine the first time(Arduino as ISP selected as programmer). (I wanted to test it befor i want to burn this Bootloader on an Empty 328p-au uC.) But now since I received the 328p-au uC's i tried the same thing, to burn the Bootloader to the epty uC's but somehow it can't read the device signature, neither from a fresh arduino Nano or another avr(At least that is what avrdude said). I wired everything exectly like it was written in the ISP Sketch.

## Here is one of the error messages i received when I was trining to Burn the standard 16mhz Bootloader:

```
     Programmer Type : STK500
     Description     : Atmel STK500 Version 1.x firmware
     Hardware Version: 2
     Firmware Version: 1.18
     Topcard         : Unknown
     Vtarget         : 0.0 V
     Varef           : 0.0 V
     Oscillator      : Off
     SCK period      : 0.1 us

     Fehler beim Brennen des Bootloaders.
     avrdude: AVR device initialized and ready to accept instructions

     Reading | ################################################## | 100%          0.02s

     avrdude: Device signature = 0xff0000
     avrdude: Expected signature for ATmega328P is 1E 95 0F
     Double check chip, or use -F to override this check.

     avrdude done.  Thank you.

```

---

So what am I doing wrong? (Using -F is what I tried but it didn't work, except the first time I programmed the 8Mhz Int. Oscillator Bootloader)

What stand out to me is that there was nothing happening on the MISO line. Here is a screenshot from my Logic Aalyzer software: ibb.co/hWXrpp7

And here is an Image of my setup(the right Arduino is the programmer and the left one has the empty uC soldered onto it): https://ibb.co/zXQFmwR I am relative new to Arduino, so I hope some of you can help me with that.

# Answer
> 1 votes
It seems that you are using too high programming speed. SCK period al of 0.1 us renders 10 MHz, which is to fast if crystal is working at 8 MHz. Not sure where to change it in Arduino environment, but you should add this key to avrdude.exe run string:

`avrdude.exe -B 8`

This will set programming speed to 125 kHz. Also I suggest you to buy a cheap USBasp programmer from eBay or AliExpress. It is well documented and have plenty GUI programs, running on top of the avrdude. In newest Arduino IDE you can generate hex files in the sketch directory, and burn it with programmer.

---
Tags: atmega328, bootloader, avrdude, isp
---


# Question
Title: Can an Arduino act as a GATT Server (Bluetooth LE)
I know it's pretty standard to set up an Arduino system as a BLE client, and use something like an app running on a smartphone as the GATT server, which receives the data and does something with it.

In my scenario I have a BLE sensor that is not connected directly to the Arduino system, and I want the Arduino to be able to respond to the sensor output (a wearable accelerometer) and, for example, initiate various lighting sequences depending on the data being received.

I would prefer not to introduce a third component (ie: mobile device as GATT server) into the equation. I'd like for the Arduino to listen to the remote device's services and characteristics, analyze the incoming data and then make some decisions about what LEDs to illuminate based on that analysis.

Can an Arduino run as a GATT server?

# Answer
An ESP32 module (Arduino IDE compatible) can act as both a GATT Client and Server, and there are module examples for each of these, as well as github projects.
> 0 votes

# Answer
I got this link here that could be helpful - link at the bottom. It is a tutorial that shows you how to control your Arduino with a custom app on an Android. It uses the MIT app creator, an app that lets you create an app. You program it with there IDE in some Java I believe. You can add button to your app so that is sends a message to your Arduino then program the Arduino to do something when it receives that message. For the Arduino side, you could buy an HC-05 Bluetooth module. It is both an transmitter and receiver. It is quite cheap and very popular so there is many libraries out there. I think this is a good module you should get and I recommend to get them in pairs so you can connect them together with 2 Arduinos.

https://www.youtube.com/watch?v=E-1w7dL3Cps
> -1 votes

---
Tags: bluetooth
---


title: I2C - Confusion

text:
# Question
Title: I2C - Confusion
It's not often I ask a question. This one has me a little stumped though.
Scenario:
I have an 328PB (internal 8mhz), it speaks to a multiplexer on Wire1 (the PB's second IC2 - Minicore lib). The multiplexer speaks to many sensors. That is all working just fine.
I have a logic analyser hooked up to the key points so I can see what is going on.
I have a Nano (external 16mhz) hooked up to Wire (the PB's first I2C), it sends a master request.
The PB is master on Wire1 and slave on Wire.
For some reason the Nano's request on (address 8) is acknowledged by the PB but then the subsequent reads deliver a zero byte and an NACK.
I'm just asking for one byte to troubleshoot. Previous attempts at multiple bytes would deliver the expected bytes but all of them zero.
Strange thing I'm seeing on the logic analyser is that the PB to Multiplexer communication seems to be slower than the Nano to PB (much slower).
I've looked through the libraries and both Wire and Wire1 seem to calculate the speed down to 100khz. I'm using the standard Arduino Wire on the Nano. Given that the initial Address comms gets an ACK. I'm stumped why the subsequent read gets zero and a NACK.
Any help to restore my sanity is much appreciated. Chances are I'm having a dumb moment. My suspicions are that the clock differences are to blame (but logically they shouldn't be).

---

Edit: This is the analyser recording. The dodgy byte is highlighted in Blue.

The communication from the Atmega328pb to the multiplexer and then on to the temperature sensor is working fine. Not all of the multiplexer channels have sensors at the moment hence the NACKs but you can see success on channel 1 to the right of the screenshot. The Nano to Atmega328pb communication starts off good but I'm expecting to see 0X41 in the blue box not 0x00.

This is going to end up being something simple, I'm going to kick myself.

Nano code:

```
#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);             // start serial for output.
}

void loop() {
  Wire.requestFrom(8, 1);         // request 1 byte from slave device #8
  char c = Wire.read();           // receive a byte as character
  Serial.print("The character: ");
  Serial.println(c);              // print the character
  delay(1000);
}

```

Atmega328pb requestEvent code:

```
void requestEvent() {
  Wire.write("A");
}

```

Edit: There are other wires for programming etc, but they are disconnected during test.

Edit: I commented out all the usage of Wire1 in the PB code. And the result was that the Nano got it's byte. I wove the usage of Wire1 back into the code. Right up until it was actually active i.e. communicating with the multiplexer. At that point the Nano started getting a zero byte again.

It seems to be when they are both active. Which suggests it is something in the Wire/Wire1 library by Minicore.

I suspect there is something in the registers but scanning the datasheet for the PB is not yielding any insights. Except for this: 26.1 - Device can Operate as Transmitter **or** Receiver
There is no elaboration in the document that I can see.

I've tried staggering the communication so that neither is active at the same time. Still the same result.

Still hoping that someone here has the answer ;-)

# Answer
> 1 votes
I got it to work ... sort of. I had to move some lines from init to the loop. I found that by delaying the Wire1 communication (pb to multiplexer) I could get Wire (Nano to pb) to work. Then as soon as the Wire1 communication had *finished* Wire no longer worked. Interestingly Wire continued to work while Wire1 was also active. This has lead me to believe the end of the Wire1 communication is leaving something in a conflicted state (the events on Wire were not connected any longer). The blunt answer was to re-initialise on each loop. This seems to work but is not particularly elegant.

```
void loop()
{
    Wire1.begin();
    getTemperatures();
    Wire1.end();
    Wire.begin(8);                                               // Join i2c bus 0 with address #8
    Wire.onReceive(receiveEvent);                                // Register event.
    Wire.onRequest(requestEvent);                                // Register event.
}

```

I'm going to continue with this and see if it offers an appropriate degree of reliability. I'm still hunting for the root issue though.

# Answer
> 1 votes
I've been rebuilding using Atmel Studio. After a long time bringing my C++ skills up to scratch I've managed to get it to work very reliably. I like the greater level of control it brings. I suspect that I was trying to do something in Arduino IDE that cannot be done with the Wire library. I had to effectively rewrite the Atmel Start Slave driver to get it to behave as I expected it to. I have no other experience of using I2C. So I cannot say whether it is the Atmega328pb that is different or not.
I'm going to stick to Atmel Studio for this project, thanks for all the responses.

---
Tags: arduino-nano, i2c
---


# Question
Title: IDE / Plugin / Compiler / Language: Which combination is closest to best-practice embedded development in C or C++?
Currently I'm pretty far out to sea with a combination of Visual Studio Code, the Platform.io extension, while writing new code in C++ using avr-gcc.

I'm hoping for a combination that would offer the most crossover educational value, in the event that I potentially **experiment** (if only to prove the Arduino platform's **superiority** to any doubters) with non-Arduino-specific embedded development.

The default IDE seemed to present me with less information about the remarkably sound underpinnings and marvelous overall artistry with which they've woven the many different design techniques and languages together. I'm mainly curious about other (**inferior** to Arduino, mind you), more widely used combinations / tool chains in the world of embedded programming.

# Answer
> 1 votes
A great deal of what you learn with any comprehensive IDE will transfer to another one, if you need to. The IDEs that come to mind are Eclipse (listed first, only because it is my personal choice and has a broad range of application), Visual Studio, and others I have no experience with.

The Arduino IDE is as limited as you found it, primarily because it was written as (1) a learning tool for (2) AVR-based Arduinos, and goes to some lengths to offer an easier entry into embedded systems programming for non-programmer hobbyists. To that end, it achieves its goal very well. But as you have observed, you quickly run into its limitations, especially when your goal is to branch out onto other processors and other tool-sets.

Once someone is over the hump of basic programming and debugging, more advanced tools like a full-on IDE take most of those limitations out of your way, at the cost of less hand-holding, but by that time, you presumably need the freedom much more than the help!

I don't want to outright tell you "You need to use FiddleFoo 18.4 or you'll never get anywhere" - one (or a couple) of the industrial strength IDEs will appeal to your view of programming and your personal work-style. Try a few of them, paying attention to what toolsets and processors each one can target with OEM or third-party support, for the processors you think you might become interested in. It's quite likely T-H-E right IDE for you will stand out from the rest.

Update:

Eclipse *will* need a plug-in to target Arduino and other embedded system boards. The one I use - and the only one being maintained AFAIK - is Sloeber by Jan Baeyens, who occasionally posts here as jantje. It is pretty comprehensive, including the ability to write and import new board descriptors.

Memory limitations come with the hardware, and while compiler advances can help this out, it's pretty much governed by the numbers. An Arduino Uno still has only 2K of RAM and 32K of Flash minus whatever the bootloader uses (if you choose to use a bootloader). Heap is still problematic for all the usual reasons - fragmentation of free memory (positioned, as it is, between static area and the bottom of the stack), and reduction of available stack and/or data space. There are, of course, more embedded boards available, with larger memories, but that just helps you put off the inevitable. I view the use of heap in an embedded system as a reliability issue even more than as a memory limitation; it is all too easy for fragmentation and memory leaks to eventually take down your system, and a Blue Screen Of Death is a big no-no in embedded systems.

---
Tags: arduino-uno, arduino-ide
---


# Question
Title: Why should I connect GND to RST to send data through Rx using USB-TTL?
I've found that when I use Arduino Nano connected with USB everything is working great, and when I tryed to use it with USB to TTL connector I've understood that I can only read data. I tryed to connect **GND** to **RST** as it was on some picture in Internet, and it works! Now I can send data through my USB to TTL (and through another UART device). So I can't uderstand, why should I do it? Why can't I just send data through Rx Arduino pin? Why do I need an extra action? Is it related with Arduino microcontroller?

# Answer
> 0 votes
The key here is to remember the simple rules:

1. One device can send to many devices
2. One device can receive only from one device

In your situation you have three devices that are communicating:

* The USB to UART chip
* The on-board ATMega, and
* The off-board ATMega connected to the TX/RX pins.

All three of those are connected together through the TX and RX pins. This means that:

* The UART chip sends to the on-board ATMega, and
* The UART chip sends to the off-board ATMega

This fits with rule 1 above: one device can talk to many devices.

But:

* The UART chip receives from the on-board ATMega, and
* The UART chip receives from the off-board ATMega

This breaks rule 2 above. You can't have two devices sending to one receiver.

By connecting the RESET pin to GND you are effectively turning off the on-board ATMega. It's like you removed it from the board. It's not allowed to do anything - including communicating with the UART chip.

So that fixes rule 2 above, because now you only have one device sending to the UART chip, not two.

---
Tags: reset, rx-pin
---


title: Arduino uno + 5 IR obstacle sensor

text:
# Question
Title: Arduino uno + 5 IR obstacle sensor
I have IR sensor with current draw 100ma i have to connect 5 of them is i can connect all 5 with arduino directly or i have to use external power suplly for them

# Answer
An Arduino UNO has a max current of 20 mA per IO Pin and a max current of 200 mA of all Pins together. If you intent to drive the senders with the pins then this is impossible.

If you power the Arduino with USB, the VCC current is limited to 500 mA (thermo fuses). If you power it externally, it depends on the power supply. Using the voltage from the Vcc Pin is risky (IMHO), because the Arduino needs power too.

So with 100 mA per sensor I would definitively use an external power supply.
> 1 votes

---
Tags: sensors, power
---


# Question
Title: Is there a way for keypad to stop the buzzer while it is running?
I am new to arduino, currently I am looking for a way to make the keypad able to stop the buzzer making a siren alarm when password are keyed in wrong and able to move into password screen by pressing any button on the keypad. From all the videos i have seen, only 1 fits the way i want it to work.

https://www.hackster.io/thehack904/motion-sensing-alarm-with-keypad-password-53f05c

Below is the code I have completed with but i want to try adding a siren alarm function that is able to stop using keypad. Can anyone please teach me how to use a keypad to stop the buzzer and move into master key screen.

```
//Libraries
#include <LiquidCrystal.h>
#include <Keypad.h>

/*-------------------------------KEYPAD---------------------------------------*/
const byte numRows = 4; //number of rows on the keypad
const byte numCols = 4; //number of columns on the keypad
char keypressed;
char keymap[numRows][numCols] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
//Code that shows the the keypad connections to the arduino terminals
byte rowPins[numRows] = {2, 3, 4, 5};//Rows 0 to 3
byte colPins[numCols] = {6, 7, 8, 9};//Columns 0 to 3
//initializes an instance of the Keypad class
Keypad myKeypad = Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

/*-------------------------------CONSTANTS------------------------------------*/
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5); //LCD
const int buzzer = 10;        //Buzzer/small speaker
int solenoidPin = 11;         //Solenoid

/*-------------------------------VARIABLES------------------------------------*/
String password = "0"; //Variable to store the current password
String master_key = "999"; //Variable to store the master key
String tempPassword = ""; //Variable to store the input password
int doublecheck;    //Check twice the new passoword
boolean armed = false;  //Variable for system state (armed:true / unarmed:false)
boolean input_pass;   //Variable for input password (correct:true / wrong:false)
boolean storedPassword = true;
boolean changedPassword = false;
boolean checkPassword = false;
int i = 1; //variable to index an array
unsigned char WrongAttempts = 0; //global variable to keep the number of wrong attempts done at the code.

/*----------------------------------------------------------------------------*/
void setup() {
  lcd.begin(16, 2); //Setup the LCD's number of columns and rows
  pinMode(solenoidPin, OUTPUT);
  pinMode(buzzer, OUTPUT);
  Serial.begin(9600);
}

void loop() { //Main loop
  unlockTheDoor();
}
/********************************FUNCTIONS*************************************/
void unlockTheDoor() {
lockAgain: //goto label
  digitalWrite(solenoidPin, HIGH);       //Switch Solenoid OFF
  tempPassword = "";
  lcd.clear();
  i = 6;
  noTone(buzzer);
  while (!checkPassword) {
    lcd.setCursor(0, 0);
    lcd.print("Open the door:  ");
    lcd.setCursor(0, 1);
    lcd.print("PASS>");
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (keypressed != NO_KEY) {   //Accept only numbers and * from keypad
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
          keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
          keypressed == '8' || keypressed == '9' ) {
        tempPassword += keypressed;
        lcd.setCursor(i, 1);
        lcd.print("*");       //Put * on lcd
        i++;
        tone(buzzer, 800, 200); //Button tone
      }
      else if (keypressed == 'A') {
        changePassword();
        goto lockAgain;
      }
      else if (keypressed == 'D') {
        break;
      }
      else if (keypressed == '*') { //Check for password
        if (password == tempPassword) { //If it's correct...
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Correct Password");
          lcd.setCursor(0, 1);
          lcd.print("Door is unlocked");
          tone(buzzer, 100);   //Play a tone while door is unlocked
          delay(100);        // ...for 0.1 sec
          noTone(buzzer);     // Stop sound...
          digitalWrite(solenoidPin, LOW);      //Switch Solenoid ON
          delay(5000);
          WrongAttempts = 0;
          changePassword(); {
            setLocked (true); ///.......to lock again
            tone(buzzer, 1000); // Send 1KHz sound signal...
            delay(100);        // ...for 0.1 sec
            noTone(buzzer);     // Stop sound...
            delay(1000);
            lcd.clear();
            goto lockAgain;
          }
          if (keypressed == '#') {
            setLocked (true); ///.......to lock again
            tone(buzzer, 1000); // Send 1KHz sound signal...
            delay(100);        // ...for 0.1 sec
            noTone(buzzer);     // Stop sound...
            delay(1000);
            lcd.clear();
            goto lockAgain;
          }
        }
        else {           //if it's false, retry
          tempPassword = "";
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("*Wrong Password*");
          tone(buzzer, 500, 200);
          delay(300);
          tone(buzzer, 500, 200);
          delay(300);
          WrongAttempts++;  //ADDED
          Attempts();
        }
      }
    }
  }
}

//Change current password
void changePassword() {
retry: //label for goto
  tempPassword = "";
  lcd.clear();
  i = 1;
  while (!changedPassword) {      //Waiting for current password
    keypressed = myKeypad.getKey();   //Read pressed keys
    lcd.setCursor(0, 0);
    lcd.print("CURRENT PASSWORD");
    lcd.setCursor(0, 1);
    lcd.print(">");
    if (keypressed != NO_KEY) {
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
          keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
          keypressed == '8' || keypressed == '9' ) {
        tempPassword += keypressed;
        lcd.setCursor(i, 1);
        lcd.print("*");
        i++;
        tone(buzzer, 800, 200);
      }
      else if (keypressed == '#') {
        break;
      }
      else if (keypressed == 'D') {
        goto retry;
      }
      else if (keypressed == '*') {
        i = 1;
        if (password == tempPassword) {
          storedPassword = false;
          tone(buzzer, 500, 200);
          newPassword();          //Password is corrent, so call the newPassword function
          break;
        }
        else {              //Try again
          tempPassword = "";
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("*Wrong Password*");
          tone(buzzer, 500, 200);
          delay(300);
          tone(buzzer, 500, 200);
          delay(300);
          WrongAttempts++;  //ADDED
          Attempts();
          goto retry;
        }
      }
    }
  }
}

String firstpass;
//Setup new password
void newPassword() {
retry: //label for goto
  tempPassword = "";
  changedPassword = false;
  lcd.clear();
  i = 1;
  while (!storedPassword) {
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (doublecheck == 0) {
      lcd.setCursor(0, 0);
      lcd.print("SET NEW PASSWORD");
      lcd.setCursor(0, 1);
      lcd.print(">");
    }
    else {
      lcd.setCursor(0, 0);
      lcd.print("One more time...");
      lcd.setCursor(0, 1);
      lcd.print(">");
    }
    if (keypressed != NO_KEY) {
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
          keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
          keypressed == '8' || keypressed == '9' ) {
        tempPassword += keypressed;
        lcd.setCursor(i, 1);
        lcd.print("*");
        i++;
        tone(buzzer, 800, 200);
      }
      else if (keypressed == '#') {
        break;
      }
      else if (keypressed == 'D') {
        goto retry;
      }
      else if (keypressed == '*') {
        if (doublecheck == 0) {
          firstpass = tempPassword;
          doublecheck = 1;
          newPassword();
        }
        if (doublecheck == 1) {
          doublecheck = 0;
          if (firstpass == tempPassword) {
            i = 1;
            firstpass = "";
            password = tempPassword; // New password saved
            tempPassword = ""; //erase temp password
            lcd.setCursor(0, 0);
            lcd.print("PASSWORD CHANGED");
            lcd.setCursor(0, 1);
            lcd.print("----------------");
            storedPassword = true;
            tone(buzzer, 500, 400);
            delay(2000);
            lcd.clear();
            break;
          }
          else {
            firstpass = "";
            newPassword();
          }
        }
      }
    }
  }
}

void setLocked(int locked) {
  if (locked) {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("*** LOCKED ***");
  }
  else {
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("*** UNLOCKED ***");;
  }
}

void Attempts() {
  if (WrongAttempts >= 3) { //UPS....
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TO UNLOCK PLEASE");
    lcd.setCursor(0, 1);
    lcd.print("INPUT MASTER KEY");
    digitalWrite(buzzer, HIGH);
    delay (5000);
    master();
  }
}

void master() {
lockAgain: //goto label
retry: //label for goto
  tempPassword = "";
  lcd.clear();
  i = 6;
  noTone(buzzer);
  while (!checkPassword) {
    lcd.setCursor(0, 0);
    lcd.print("***MASTER KEY***");
    lcd.setCursor(0, 1);
    lcd.print(">");
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (keypressed != NO_KEY) {   //Accept only numbers and * from keypad
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
          keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
          keypressed == '8' || keypressed == '9' ) {
        tempPassword += keypressed;
        lcd.setCursor(i, 1);
        lcd.print("*");       //Put * on lcd
        i++;
        tone(buzzer, 800, 200); //Button tone
      }
      else if (keypressed == 'D') {
        goto retry;
      }
      else if (keypressed == '*') { //Check for password
        if (master_key == tempPassword) { //If it's correct...
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Correct Password");
          lcd.setCursor(0, 1);
          lcd.print("Door is unlocked");
          tone(buzzer, 100);   //Play a tone while door is unlocked
          delay(100);        // ...for 0.1 sec
          noTone(buzzer);     // Stop sound...
          digitalWrite(solenoidPin, LOW);      //Switch Solenoid ON
          delay(5000);
          WrongAttempts = 0;
          changePassword(); {
            setLocked (true); ///.......to lock again
            tone(buzzer, 1000); // Send 1KHz sound signal...
            delay(100);        // ...for 0.1 sec
            noTone(buzzer);     // Stop sound...
            delay(1000);
            lcd.clear();
            unlockTheDoor();
          }
          if (keypressed == '#') {
            setLocked (true); ///.......to lock again
            tone(buzzer, 1000); // Send 1KHz sound signal...
            delay(100);        // ...for 0.1 sec
            noTone(buzzer);     // Stop sound...
            delay(1000);
            lcd.clear();
            unlockTheDoor();
          }
        }
        else {           //if it's false, retry
          tempPassword = "";
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("*Wrong Password*");
          tone(buzzer, 500, 200);
          delay(300);
          tone(buzzer, 500, 200);
          delay(300);
          WrongAttempts++;  //ADDED
          Attempts();
        }
      }
    }
  }
}

```

# Answer
> 1 votes
Consider defining exactly what you want your Arduino application to do using a state machine approach. Drafting a state machine diagram allows a developer to visualize the inputs to the state machine, the number & types of states necessary and the outputs of the state machine. The following diagram from the above wikipedia.org link has two states:

A "Locked" and an "Unlocked" state. You see that a "Coin" is necessary to change from the "Locked" to the "Unlocked" state.

For the number-coded-lock in the question there are likely many more state to consider. For instance, there may be a state for each button number entered. The correct number will advance to the next state. The incorrect number will revert to the state where the state machine expects to see the 1st number in the code. If all the numbers in the code have been entered correctly, the last state will likely be the state that unlocks the device. A buzzer may have a state of its own. While in the buzzer state the buzzer will be making noise. An input to the state machine indicating that 1/2 second has elapsed could be used to exit from the buzzer state.

In this way any desired behavior can be created. In addition, by using a state diagram, the intentions of the final program are made clear. And any logical errors are exposed before code creation.

---
Tags: arduino-uno, buzzer, keypad
---


# Question
Title: Function pointer call results in InstrFetchProhibited (ESP32)
I have the following issue which I'm unable to resolve by myself. Perhaps one of you could point me to issues in my code which I don't see.

There is a class called *communicator* which handles an MQTT connection. I use `PubSubClient` as a MQTT client. The constructor of `communicator` looks like the following. Besides connection arguments, it also receives an array of structs `SubscriptionHandler`. These structs define which topics should be subscribed to and also point to a callback method. When a `communicator` receives a MQTT message, it compares the topic to the known ones and calls the appropriate callback.

```
Communicator(char * mqttBrokerIP, uint16_t mqttBrokerPort, char *mqttUsername, char * mqttPassword, char * mqttClientHostname, SubscriptionHandler subscriptionHandlers[], int lenHandlers);

```

**SubscriptionHandler**. is defined like this:

```
typedef void (*callback)();

struct SubscriptionHandler
{
    char *Topic;
    callback Callback;
};

```

I tried the following: In the main file, I defined two methods for demonstration purposes:

```
void enableHandler()
{
  Serial.println("enable handler");
}

void disableHandler()
{
  Serial.println("disable handler");
}

```

The `communicator` is created in the `setup()`-Method:

```
SubscriptionHandler handlers[] = {{&strEnable, enableHandler},
                                    {&strDisable, disableHandler}};

```

callback (in *communicator.h*) `typedef void (callback)();`

strings : `String strEnable = ("test/" + hostname + "/command/enable");` and the same for disable. Those are also defined in main.cpp –

As soon as the `communicator` receives a MQTT message, the ESP32 crashes with the following message:

```
Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x3ffc9306  PS      : 0x00060c30  A0      : 0x8017e97c  A1      : 0x3ffb1ed0
A2      : 0x3ffc9306  A3      : 0x3ffc9306  A4      : 0x3ffc9306  A5      : 0x3ffc1318
A6      : 0x3ffb1f44  A7      : 0x00000000  A8      : 0x800d4df0  A9      : 0x3ffb1eb0
A10     : 0x0000000d  A11     : 0x0000000b  A12     : 0x3ffc24a4  A13     : 0xa98b32f8
A14     : 0x3ffc1318  A15     : 0xff000000  SAR     : 0x00000004  EXCCAUSE: 0x00000014
EXCVADDR: 0x3ffc9304  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff

Backtrace: 0x3ffc9306:0x3ffb1ed0 0x4017e979:0x3ffb1f00 0x400e280e:0x3ffb1f20 0x400d4f3e:0x3ffb1f70 0x400d5cff:0x3ffb1f90 0x400e4c45:0x3ffb1fb0 0x400889dd:0x3ffb1fd0

```

Therefore, something is wrong with how I use the function pointer (or somewhere which I don't even think about). Could anyone give me a hint where I could start?

# Answer
> 2 votes
I found the issue. After moving `SubscriptionHandler handlers[] = ...` out of the `setup()-`method, the function calls work. Perhaps `handlers` gets overwritten after leaving the setupfunction scope. Could anyone validate my suspected reason?

---
Tags: esp32
---