# Question
Title: Can I call functions from a different sketch?
I am a beginner at programming with Arduino and I am unsure on how can I call functions (such as, getData()) for the touchscreen LCD to display that data. The purpose of my device would be to listen to data communications between sensors and a controller and thus I have one RedBoard with CAN-BUS shield with a dataComms.ino sketch, which initialises getting data functions from received data packets and parses them.

Do I need to create another sketch for the display? If so, how can I call functions from another sketch, so that display.ino would have access to received values? Or are there some better ways of displaying data?

# Answer
You can only use one sketch at a time, meaning one sketch can be stored inside an Arduino to be executed.

This means all your code (and functionality for all devices you want to access) needs to be within that single sketch.

So what you mostly need to do is:

* Add a library for every device that you want to use.
* Call functions from that library in your .ino file.
* If you want to add functions which are not part of a library, you add both the function code and the call (where you need it) in your .ino file.

Also if you are new, don't start with everything at the same time.

* First find an example how to control the display (that's probably easier than the CAN shield).
* Add the library for the display
* Change (or copy from an example) code for the display
* Run and debug it until it works.
* Create a new sketch for the CAN shield.
* Add the library for the CAN shield.
* Call functions from that library (or use an example if available).
* Once you are convinced you know how to use both devices (display + CAN), combine the sketches (create a new sketch, add both libraries, copy code and make it one sketch).
> 1 votes

---
Tags: sketch, display
---


# Question
Title: Use lowpower-libary and still use serial connection and other things
I managed to get the LowPower libary working on my Arduino Micro. This code works perfectly:

```
#include <LowPower.h>

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);                  // wait for a second
}

```

However. I also tried it with a serial connection, to put out some text periodically. But I think the lowpower-libary does - in order to save power - disable this function. So now I am worried that it also disables some other things I might have to use but won't work. Like OneWire or I2C. It also would be nice to work with a functioning standby-mode while developing where serial output is vital, altough it's not neccessary, because I can simulate it with a simple delay. So my question is: How can I use the lowpower-libary AND have a serial connection. And will this libary affect OneWire or I2C? If so: Is there a way on how to keep these "services" running? Or is there maybe another libary wich also saves power in a similar way, but where you have more abilities to customize what you want to have shut down?

# Answer
Yes, activating low power does disable the UART - but only *while* it's sleeping.

To use serial you just need to ensure that you only use it while it's not sleeping - and due to the interrupt and buffered nature of the Serial driver it's not as easy as just printing.

However, it's simple to achieve: just `flush` the serial before sleeping. This ensures that any pending serial data is sent out through the serial port before you go to sleep:

```
void loop() {
  Serial.println("Turning LED on");
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  Serial.flush();
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);                      // wait for a second
  Serial.println("Turning LED off");
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  Serial.flush();
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);                  // wait for a second
}

```

If that doesn't help you may need to turn serial off and on yourself either side of your powerdown:

```
void loop() {
  Serial.begin(115200);
  Serial.println("Turning LED on");
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  Serial.flush();
  Serial.end();
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);                      // wait for a second
  Serial.begin(115200);
  Serial.println("Turning LED off");
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  Serial.flush();
  Serial.end();
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);                  // wait for a second
}

```

---

Update:

I just noticed you're using the Micro. That makes a big difference. The Micro and the Leonardo's `Serial` object is actually a USB CDC/ACM serial emulation, not UART. You cannot sustain a USB connection while sleeping. So it will be killed.

To use communication while sleeping you will have to switch to a proper UART connection with a USB to TTL UART (e.g., FT232RL) adaptor to connect to the TX/RX pins and use `Serial1` instead.
> 4 votes

---
Tags: power, arduino-micro, sleep
---


title: DHT11 Sensor : Stand-by or Shut down?

text:
# Question
Title: DHT11 Sensor : Stand-by or Shut down?
I have an ATmega328P monitoring room temperature and humidity. It is enough for me to monitor every 8 seconds. In these 8 seconds, I am putting my Atmega to sleep.

Now , I want to know : Does shutting down the DHT11 for these 8 seconds affect the performance of the sensor in any way or is it advisable to keep it running (stand by) for these 8 seconds ?

\[Shutting down means connecting the Vcc of the sensor to GND by means of digitalWrite(Sensor\_pin,LOW);\]

Also , (The below question is applicable only if your answer to the above question is to keep it in Stand-by) :-

I want to modify the above project such that Temp & Humidity is measured as and when only an input button is pressed. In this case too, should I keep the DHT11 running?

Is a running DHT11 sensor more accurate than a instantly powered on DHT11 ?

\[And in case you are speculating , yeah,I want to save the 50 micro-amps Standby current of the sensor.(but of course without sacrificing accuracy of the sensor)\]

# Answer
> 4 votes
At times like this it is useful to refer to the datasheet. You can, in that document, find this paragraph:

> **4. Power and Pin**
>
> DHT11’s power supply is 3-5.5V DC. When power is supplied to the sensor, do not send any instruction to the sensor in within one second in order to pass the unstable status. One capacitor valued 100nF can be added between VDD and GND for power filtering.

So you can see that if you power down the sensor completely you have to wait at least 1 second before you can do anything with it.

With it just in the low power mode it defaults to between readings you can immediately start reading as soon as your ATMega wakes up.

So you have to ask yourself: Does running the ATMega at full power for 1 second consume more or less power than running the DHT11 in low power mode for 8 seconds?

As a rough guestimate - if the ATMega is using 30mA (ballpark figure) for 1 second (that's 30mAs - milliamp-seconds), and the DHT11 uses 50uA for 8 seconds, then you have 0.05\*8 = 0.4mAs.

That's 0.4mAs (sleeping) vs 30mAs (powered down). So I'd go for leaving it powered and avoid the one second delay at full power.

Another option that may save more power would be to:

1. Power off the DHT11
2. Sleep 8 seconds
3. Power on the DHT11
4. Sleep 1 second
5. Read DHT11
6. Go to 1

Of course, that means your loop then takes 9 seconds not 8. You could compensate by sleeping for multiple amounts to make 7 seconds:

1. Sleep 4 seconds
2. Sleep 2 seconds
3. Sleep 1 second
4. Power on the DHT11
5. Sleep 1 second
6. Read DHT11
7. Power off the DHT11
8. Go to 1

But of course that then makes your sleeping less efficient - so is it really worth it?

---
Tags: arduino-uno, sensors, power, atmega328, temperature-sensor
---


title: Why are Arduino timer registers not 0?

text:
# Question
Title: Why are Arduino timer registers not 0?
I'm trying to use the timer registers to do some timing on my Arduino Mega 2560.

The output of the following code confuses me:

```
void setup ()
{
    // Set up serial connection
    Serial.begin(9600);
    while (!Serial) {}

    // Print control registers of timer 1
    Serial.println(TCCR1A); // Outputs 1
    Serial.println(TCCR1B); // Outputs 3
}

void loop () {}

```

Why is `TCCR1A` equal to `1` and `TCCR1B` equal to `3`? The documentation of the chip says the initial values of the registers are zero. I could of course set them to zero, but I want to understand why it works like this. The values are the same for the other 16-bit timers (3, 4 and 5).

# Answer
The Arduino core does things at startup. One of those things is to configure the timers ready for PWM operation.

Here's the relevant bits from `init()` in `wiring.c`:

```
    // set timer 1 prescale factor to 64
    sbi(TCCR1B, CS11);
#if F_CPU >= 8000000L
    sbi(TCCR1B, CS10);
#endif

#if defined(TCCR1A) && defined(WGM10)
    sbi(TCCR1A, WGM10);
#endif

```
> 9 votes

---
Tags: timers, avr
---


# Question
Title: Detecting if a push button was pressed and released
I want to detect if a push button was pressed and released again. So I thought the right approach would be to first wait while the pin yields `LOW` and then wait while the pin yields `HIGH`:

```
void push(int pin) {
  // wait until button was pushed down...
  while (digitalRead(pin) == LOW);
  // ... and released again
  while (digitalRead(pin) == HIGH);
}

```

That function can be easily reused. The code works fine, but I am just wondering if that solution is considered clean and a good practice.

# Answer
No, I wouldn't consider that good practice - for one good reason: it's blocking.

Your system can't be doing anything else at all while you're waiting on the button. That may be fine for some situations, but far from ideal for 99% of others.

It is better to remember the state of the button and detect that change of state.

Personally, to make it properly portable, I would implement a class to contain all the state information. Something like:

```
class Button {
    private:
        bool _state;
        uint8_t _pin;

    public:
        Button(uint8_t pin) : _pin(pin) {}

        void begin() {
            pinMode(_pin, INPUT_PULLUP);
            _state = digitalRead(_pin);
        }

        bool isReleased() {
            bool v = digitalRead(_pin);
            if (v != _state) {
                _state = v;
                if (_state) {
                    return true;
                }
            }
            return false;
        }
};

```

Then you can do something like:

```
Button myButton(3);

void setup() {
    myButton.begin();
    Serial.begin(115200);
}

void loop() {
    if (myButton.isReleased()) {
        Serial.println(F("Released"));
    }
}

```

Every time `myButton.isReleased()` is called the current button state is compared against the state it was last time it was called. If it's changed then the button must either have been pressed or released. So you remember that change. If it's been released then you return a `true`, otherwise return a `false`.

You can now easily have it work with many buttons:

```
Button myButton(3);
Button myOtherButton(4);

void setup() {
    myButton.begin();
    myOtherButton.begin();
    Serial.begin(115200);
}

void loop() {
    if (myButton.isReleased()) {
        Serial.println(F("Released 1"));
    }
    if (myOtherButton.isReleased()) {
        Serial.println(F("Released 2"));
    }
}

```
> 4 votes

# Answer
I concur with Majenko, although your code would work, the code is blocking, meaning that your code stops at that point until the button is released again. The remaining code in your loop does not execute until the button is resolved.

A much better method is to check the state of the button in each passing of the loop. If the state changes (ie goes low) you can set a flag. Then when you read that the button is high again and the flag has been set then you execute the appropriate code. For example:

```
const int buttonPin = 2;     // the number of the pushbutton pin
boolean buttonWasLow = false;         // variable flag for when the pushbutton goes low

void setup() {
    pinMode(buttonPin, INPUT);    // initialize the pushbutton pin as an input:
}

void loop() {
    // read the state of the pushbutton and set a flag if it is low:
    if (digitalRead(buttonPin) == LOW)  {
        buttonWasLow = true;
    }

    // This if statement will only fire on the rising edge of the button input
    if (digitalRead(buttonPin) == HIGH && buttonWasLow)  {
        // reset the button low flag
        buttonWasLow = false;

        // Button event here
    }
}

```

My favorite way to detect a rising edge of an input is actually much simpler:

```
void loop() {
    button = digitalRead(buttonPin);

    // If the button is pressed
    if (button && !buttonLast)
    {
        // Button event here
    }

    // Update button flag
    buttonLast = button;
}

```

user8886193 brings up the very good point about button debounce.

> Bouncing is the tendency of any two metal contacts in an electronic device to generate multiple signals as the contacts close or open; debouncing is any kind of hardware device or software that ensures that only a single signal will be acted upon for a single opening or closing of a contact.

I prefer to debounce the pushbutton inputs through hardware by adding a 100nF (or larger) from the input pin to ground. Note that this requires a 10K (or larger) resistance in series with the button circuit in order for the capacitor to charge/discharge.

Alternatively, in software, the most common debounce for beginners is adding a delay such as `delay(100);`, which would look something like this:

```
void loop() {
    button = digitalRead(buttonPin);

    // If the button is pressed
    if (button && !buttonLast)
    {
        // Button event here
        delay(100);  // <---- Delay inserted after the button event
    }

    // Update button flag
    buttonLast = button;
}

```

This has the downside that it is blocking for 100ms while the delay executes. A better method is to debounce without a delay. One of the built in examples demonstrates button debounce. The main loop is shown below:

```
void loop() {
    // read the state of the switch into a local variable:
    int reading = digitalRead(buttonPin);

    // check to see if you just pressed the button
    // (i.e. the input went from LOW to HIGH), and you've waited long enough
    // since the last press to ignore any noise:

    // If the switch changed, due to noise or pressing:
    if (reading != lastButtonState) {
        // reset the debouncing timer
        lastDebounceTime = millis();
    }

    if ((millis() - lastDebounceTime) > debounceDelay) {
        // whatever the reading is at, it's been there for longer than the debounce
        // delay, so take it as the actual current state:

        // if the button state has changed:
        if (reading != buttonState) {
            buttonState = reading;

            // only toggle the LED if the new button state is HIGH
            if (buttonState == HIGH) {
                ledState = !ledState;
            }
        }
    }

    // set the LED:
    digitalWrite(ledPin, ledState);

    // save the reading. Next time through the loop, it'll be the lastButtonState:
    lastButtonState = reading;
}

```
> 4 votes

# Answer
> "I usually put a capacitor next to my push button"

A 1uF capacitor across the button is easy, cheap and means no need to fiddle with debouncing codes. See Nick Gammon's excellent switch tutorial that covers almost any conceivable situation when using switches with Arduinos and clones (high or low, GND or +5V, internal pull-up or pull-down, capacitor debounce or software debounce, etc.). In any case, Nick Gammon has many great explanatory examples on his site and where else he comments online.
> 4 votes

---
Tags: arduino-uno, button
---


# Question
Title: Need help in connecting 64x32 LED Matrix
I recently got a 64x32 LED Matrix. However, I'm not sure how to connect it to an arduino uno. I tried following the docs here: https://cdn-learn.adafruit.com/downloads/pdf/32x16-32x32-rgb-led-matrix.pdf, but I can't get my OLED matrix to display the example.

This is my current connection so far:  (I have the R0 at the top left variant. I tried connecting it to the ESP8266 before and it works well, just that I do not know how to translate the connections to the Arduino UNO) I have a feeling that my connection is wrong since I copied the PI to PO connections from here:

and I only changed the PI to ESP8266 connections to the adafruit docs connections.

The code I am running is the example testshapes\_32x64 from the RGB matrix panel library: https://github.com/adafruit/RGB-matrix-Panel/blob/master/examples/testshapes\_32x64/testshapes\_32x64.ino

EDIT: Since my connection for the CLK pin is connected to pin 8, I made changes in the code but it is still not working.

x-post from: https://www.reddit.com/r/arduino/comments/8qgm9x/need\_help\_in\_connecting\_a\_64x32\_oled\_matrix\_to\_an/ and https://forum.arduino.cc/index.php?topic=552832.0

# Answer
> 0 votes
If your matrix is the same as mine (32x64) I don't think you can drive it with a UNO. You should use a MEGA. Then follow the wiring supplied by SparkFun and make sure you connect CLK to Pin 11, NOT Pin 8.

---
Tags: rgb-led
---


# Question
Title: Can I connect Multiple Devices to One 5V and one GND pin of my Arduino Uno R3
I have made a Bluetooth Controlled Robot Car. Using L298N Motor Driver, HC-05 Bluetooth Module and Arduino R3 I was able to run it by giving one "VIN" and one "GND" to L298N, one "5V" and one "GND" to HC-05 and I gave 12V input to the Arduino Board. But now I want upgrade it to an upper level by adding IR transceiver as obstacle sensor and a buzzer (as a horn, such that it will sound whenever any obstacle is sensed OR I'll set a button in the GUI to play the horn) Please Help me. I am a very beginner and assume it as my first project. Any kind of help would be appreciated. Thanks in advance.

# Answer
Yes, you can connect multiple devices to GND and +5 V. You may find that you need to bring one wire from the PCB to an external connector or piece of stripboard so that you can make more reliable connections.

Watch that your total current does not exceed the rating for the voltage regulator or USB power supply.
> 3 votes

---
Tags: wireless, robotics, arduino-uno
---


# Question
Title: Where does arduino IDE store the latest board selection?
I'm building a tool to help me automate my uploading process. How do I know where Arduino stores the current preferences - which board, which com port, what serial speed?

If devs are familiar with using multiple boards in the same system ithey'd know it would be really handy to be able to change that

# Answer
It is stored in `preferences.txt` in your Arduino data folder.

You can find more about that file, including where to find it, here.

Some of the keys you may be interested in are:

* board=uno
* serial.port=COM3
* serial.debug\_rate=115200

However maybe for your workflow the Arduino IDE isn't the best tool for the job. You may consider `arduino-builder`, which is the back-end that the Arduino IDE uses to do the actual compiling, or maybe another IDE entirely, such as PlatformIO or UECIDE.
> 1 votes

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


# Question
Title: Send out a short signal every 10 seconds to an arduino
In order to reduce power consumption, I want to resume my Arduino from standby mode every 10 seconds. For this a hardware interrupt is necessary.

Is there such a device that can create a quick impulse to trigger that interrupt? It can be anything from 10ms to 2 seconds; doesn't matter. My first thought was to use a 555 timer, but this one can only be on for 10 seconds and off for the same amount of time.

The best solution for me would be an already assembled device that I just have to wire with my Arduino since my knowledge in electronics is very low. Or a detailed assembly plan, then I would be able to build it myself I guess?

**UPDATE:** I was now able to put the Arduino into standby-mode using the Low-Power library. At first it seemed like it didn't work, because I wanted to print out a text over the serial connection. Instead, I tried to let the internal LED blink every 8 seconds, and this works perfectly.

# Answer
A 555 doesn't have to generate a 50% duty cycle. Even if you do want to use a 50% duty cycle, the edge can be RC coupled into the interrupt to reduce the pulse width.

An Arduino can use a slow clock like a 32kHz watch crystal, then it's very low power indeed. This slow one can be used to wake-up your more power-hungry Arduino.

The lowest power and tidiest external solution would be to use a CD4060. These are designed to be very low power, very long period timing devices.

The correct way to do it is to use the internal Watchdog Timer to wake itself up from sleep. This uses an independent internal hardware 128kHz low power oscillator. The longest this can be programmed to wait is 8s. However, if you program it to 5s, then the Arduino can choose to do work, or go straight back to sleep again, on each interrupt.
> 12 votes

# Answer
The best solution for you is to use LowPower library which does not require any external parts. It supports up to 8 seconds sleep. If you need exactly 10 seconds you can write a loop with 5 cycles and call powerDown with 2 seconds sleep.

If you still want to use external interrupt, see this for some chip options.

Also, see this article for some good ideas on reducing power consumption, and this article on how to run Arduino for a year on coin cell.
> 10 votes

# Answer
I believe that the LTC2956 was made exactly for this purpose. Directly from the datasheet:

> The LTC2956 is a micropower, wide input voltage range, configurable wake-up timer with pushbutton control.
>
> It periodically wakes up and turns on a connected system to perform tasks like monitoring temperature or capturing images. After completing the task, the LTC2956 turns the system off to conserve power. The wake-up timer period can be adjusted from 250ms to 39 days using configuration resistors

You can find the datasheet here: LTC2956. It is probably considered expensive at 1.98$ in 1000+ quantity.
> 4 votes

# Answer
Along the lines of mr\_sunshine's answer, another chip you could use is commonly known as a 556 timer - it's two 555 timers in a single package. Run one timer on the normal 50% duty cycle (astable), and have it trigger the other timer in monostable mode to send a short pulse of voltage. Look for a schematic for a servo controller based on a 556 or two 555's, and change the values to get your 10s delay. Here's a link to one such page, found with a google search: Servo Exerciser
> 0 votes

---
Tags: power
---


title: How to convert USB to PS/2?

text:
# Question
Title: How to convert USB to PS/2?
Objective: To get my USB keyboard to interface with an Arduino Uno board.

Constraints: I can't afford a USB host shield for now for Arduino. Currently available is a keyboard with PS/2 connector. That example is available here. However, it is silly going for such a keyboard, or, buy a USB to PS/2 converter at the moment.

Challenge: USB has VCC, GND, RX/TX. (Rx/Tx also labelled D+/D- respectively). The parallel port connector has the following:

Where will the D- pin go?

# Answer
> 5 votes
Many USB keyboards (certainly older ones, though almost certainly not wireless ones) are also PS/2 keyboards. The wiring of the cable is all that differs, and the chip in the keyboard changes its behaviour depending on how it's wired.

A simple USB to PS/2 adaptor is merely a USB socket and PS/2 plug wired together in a certain way:

So that's:

* 5V to 5V
* D- to Data
* D+ to Clock
* GND to GND

It *may* work with your keyboard, or it may not. All you can do is try it and see.

---
Tags: usb, keyboard
---


# Question
Title: How can I stock data, and send them over by serial?
I want to make an array with data from the sensor. In data, I have displacement in x/y axis. I want to send them in the array, because in my python code I don't send them one by one, slow down really quickly program.

**Arduino code responsible for sensor**

```
class MouseRptParser : public MouseReportParser
{
protected:
 void OnMouseMove (MOUSEINFO *mi);
};

void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
{

    Serial.print(mi ->dX, DEC);
    Serial.print(",");
    Serial.println(mi ->dY, DEC);

};

```

I tried to do something on my own, but I get stuck with an error about data not in the scope. I try some variant placing it, but I don't succeed .

```
class MouseRptParser : public MouseReportParser {

 void OnMouseMove (MOUSEINFO *mi); };

void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
{ int i;   for (i=0;i<10;i+2)   {
        data[i]=(mi ->dX, DEC);
        data[i+1]=(mi ->dY, DEC);   }
  Serial.println(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8],data[9]);

    delay(20); };

```

EDIT: I have now program that's making an array of 10 cells, but values in it are constatnt 10.

```
#include <hidboot.h>
#include <usbhub.h>

// Satisfy the IDE, which needs to see the include statment in the ino too.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>
int data[10];

class MouseRptParser : public MouseReportParser
{
protected:
 void OnMouseMove (MOUSEINFO *mi);
};

void MouseRptParser::OnMouseMove(MOUSEINFO *mi)
{

    for (int i=0; i<10; i=i+2)
  {
    data[i]=(mi->dX, DEC);
    data[i+1]=(mi->dY, DEC);

  }
  for(int j=0; j<10; j=j+1)
  {
  Serial.print(data[j]);
  Serial.print(",");
}
Serial.println();
  delay(100);
};

USB     Usb;
USBHub     Hub(&Usb);
HIDBoot<USB_HID_PROTOCOL_MOUSE>    HidMouse(&Usb);

MouseRptParser Prs;

void setup()
{
    Serial.begin( 9600 );
#if !defined(__MIPSEL__)
    while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
    //Serial.println("Start");

    if (Usb.Init() == -1)
        Serial.println("OSC did not start.");

    HidMouse.SetReportParser(0, &Prs);
}

void loop()
{

  Usb.Task();

}

```

# Answer
> 1 votes
There is no such thing as "all at once" with serial. The whole point of serial is that it sends things one character at a time.

It is entirely up to you to decide what constitutes one "block" of data.

There is absolutely no difference (besides some slight processing overheads) between:

```
Serial.print("Hello");
Serial.print(" ");
Serial.println("World");

```

and:

```
Serial.println("Hello World");

```

Both of them result in Serial sending:

```
H
e
l
l
o
[space]
W
o
r
l
d
[cr]
[lf]

```

No matter how you "batch" stuff together (or attempt to) it makes no difference.

You need to have:

* Some way of identifying the *start* of a block of data,
* A mechanism to receive the entire block a byte at a time, and
* Some way of identifying the *end* of a block of data.

How you do that is entirely up to you.

---

Here's an example of how to arrange the storage:

```
class MouseRptParser : public MouseReportParser
{
    private:
        int dx[10];
        int dy[10];
        int dpos = 0;

    protected:
        void OnMouseMove (MOUSEINFO *mi) {
            dx[dpos] = mi->dX;
            dy[dpos] = mi->dY;
            dpos++;

            if (dpos == 10) {
                dpos = 0;
                for (int i = 0; i < 10; i++) {
                    Serial.print("X");
                    Serial.print(dx[i]);
                    Serial.print("Y");
                    Serial.print(dy[i]);
                }
                Serial.println();
            }
        }
};

```

What that gives you is a pair of 10-entry arrays, one for X and one for Y values. Each time a report arrives the current DX and DY values are stored. The pointer for where to store is incremented. Then, if that pointer equals 10, reset it to 0 and print all the values.

I chose a format that gives you:

```
X3Y-2X2Y-4X6Y8X-3Y7X6Y38X176Y76X-4Y8X8Y3X39Y-32X71Y4

```

That is, an "X" followed by a decimal value for a change in X, and a Y followed by a decimal value for a change in Y. The whole lot is then terminated by a standard CR/LF line ending pair.

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


title: Minimum separation of MOSFET

text:
# Question
Title: Minimum separation of MOSFET
I have three MOSFET in a row, each separated about 2.5mm apart with the backs facing each other. Is this a good idea?

N.B Each MOSFET will be sinking 20mA and 60 mA in total for all three MOSFET. I am using an IRF540. The schematic below is for ONE MOSFET.

# Answer
Power dissipation is only a couple of milli-watts. So heat is not an issue.

Just make sure the metal tabs can’t touch each other. Personally I might add some Kapton tape. Electrical tape would work in this case, but feel wrong to me.
> 1 votes

---
Tags: mosfet
---


# Question
Title: error: expected primary-expression before '(' token
I have a decent level of programming skill, or at least I thought so. I've been getting an error when compiling this Ardulno sketch. I don't really know what this error means or how to fix it. What's wrong with my code that's causing these errors. I was in the middle of making a big change to my code, so a lot of it is commented out because I haven't gotten to those parts.

code:

```
#include <LinkedList.h>

const uint8_t PinLeft = 2;
const uint8_t PinMiddle = 3;
const uint8_t PinRight = 4;
const uint8_t PinLED = 13;

enum MouseButtons {LEFT, MIDDLE, RIGHT} ;

bool leftPressed = false;
bool middlePressed = false;
bool rightPressed = false;

void sendMouseState() {
    if (leftPressed == true && middlePressed == false && rightPressed == false) {
        Mouse.set_buttons(1, 0, 0);
    } else if (leftPressed == true && middlePressed == true && rightPressed == false) {
        Mouse.set_buttons(1, 1, 0);
    } else if (leftPressed == true && middlePressed == true && rightPressed == true) {
        Mouse.set_buttons(1, 1, 1);
    } else if (leftPressed == true && middlePressed == false && rightPressed == true) {
        Mouse.set_buttons(1, 0, 1);
    } else if (leftPressed == false && middlePressed == true && rightPressed == false) {
        Mouse.set_buttons(0, 1, 0);
    } else if (leftPressed == false && middlePressed == false && rightPressed == true) {
        Mouse.set_buttons(0, 0, 1);
    } else if (leftPressed == false && middlePressed == true && rightPressed == true) {
        Mouse.set_buttons(0, 1, 1);
    } else if (leftPressed == false && middlePressed == false && rightPressed == false) {
        Mouse.set_buttons(0, 0, 0);
    }
}

void mouseButtonPress(MouseButtons theButton);
void mouseButtonPress(MouseButtons theButton) {
    if (theButton == MouseButtons::LEFT) {
        leftPressed = true;
    } else if(theButton == MouseButtons::MIDDLE) {
        middlePressed = true;
    } else if (theButton == MouseButtons::RIGHT) {
        rightPressed = true;
    }
}

void mouseButtonRelease(MouseButtons button);
void mouseButtonRelease(MouseButtons button) {
    if (button == LEFT) {
        leftPressed = false;
    } else if(button == MIDDLE) {
        middlePressed = false;
    } else if (button == RIGHT) {
        rightPressed = false;
    }
}

volatile unsigned int nextPressLeft = 0;
volatile unsigned int nextPressCenter = 0;
volatile unsigned int nextPressRight = 0;
const int timeBetween = 150; //milliseconds

enum ActionType {KB, MOU}; //keyboard or mouse

class Action {
    public:
        uint16_t keyCode;
        ActionType actionType;

        Action (uint16_t keyCode, ActionType actionType) {
            this->keyCode = keyCode;
            this->actionType = actionType;
        }

};

class ModeAction {

    public:
        LinkedList<Action> *keys = new LinkedList<Action>();

        void addAction(Action action) {
            keys->add(action);
        }

};

class ActionManager {

    private:
        uint8_t modeL = 1;
        uint8_t modeM = 1;
        uint8_t modeR = 1;

        LinkedList<ModeAction> *lActions = new LinkedList<ModeAction>();
        LinkedList<ModeAction> *mActions=new LinkedList<ModeAction>();
        LinkedList<ModeAction> *rActions=new LinkedList<ModeAction>();

        bool lActing = false, mActing = false, rActing = false;

    public:
        ActionManager() {
            //actions for left switch
            //mode 1
            lActions->add(ModeAction());
            lActions->get(lActions->size() - 1).addAction(Action(MouseButtons.LEFT, ActionType.MOU));
            //mode 2
            lActions->add(ModeAction());
            lActions->get(lActions->size() - 1).addAction(Action(KEY_F11, ActionType.KB));
            //mode 3
            lActions->add(ModeAction());
            lActions->get(lActions->size() - 1).addAction(Action(KEY_LEFT_CTRL, ActionType.KB));
            lActions->get(lActions->size() - 1).addAction(Action(KEY_LEFT_ALT, ActionType.KB));
            //mode 4
            lActions->add(ModeAction());
            lActions->get(lActions->size() - 1).addAction(Action(KEY_W, ActionType.KB));

            //actions for middle switch
            //mode 1
            mActions->add(ModeAction());
            mActions->get(lActions->size() - 1).addAction(Action(MouseButtons.MIDDLE, ActionType.MOU));

            //actions for right switch
            //mode 1
            rActions->add(ModeAction());
            rActions->get(lActions->size() - 1).addAction(Action(MouseButtons.RIGHT, ActionType.MOU));

        }

        void cycleModeL() {
            this->modeL++;
            if(this->modeL >= lActions->size()) {
                this->modeL = 1;
            }
        }

        void cycleModeM() {
            this->modeM++;
            if(this->modeM >= mActions->size()) {
                this->modeM = 1;
            }
        }

        void cycleModeR() {
            this->modeR++;
            if(this->modeR >= rActions->size()) {
                this->modeR = 1;
            }
        }

    private:

        //void doDownActions(ModeAction modeActions, uint8_t mode) {
            //for (int i = 0; i < modeActions.at(mode).keys.length(); i++) {
                //if (modeActions[mode][i].keys[i].actionType == ActionType.KB) {
                    //Keyboard.press(modeActions[mode].keys[i].keyCode)
                //} else if (modeActions[mode].keys[i].actionType == ActionType.MOU) {
                    //mouseButtonPress(modeActions[mode].keys[i].keyCode);
                //}
            //}
            //sendMouseState();
        //}
//
        //void doUpActions(ModeAction modeActions, uint8_t mode) {
            //for (int i = 0; i < modeActions[mode].keys.length(); i++) {
                //if (modeActions[mode][i].keys[i].actionType == ActionType.KB) {
                    //Keyboard.release(modeActions[mode].keys[i].keyCode)
                //} else if (modeActions[mode].keys[i].actionType == ActionType.MOU) {
                    //mouseButtonRelease(modeActions[mode].keys[i].keyCode);
                //}
            //}
            //sendMouseState();
        //}

    public:

        //void leftDown() {
            //if (lActing == false) {
                //lActing = true;
                //doDownActions(lActions, modeL);
            //}
        //}
//
        //void middleDown() {
            //if (mActing == false) {
                //mActing = true;
                //doDownActions(mActions, modeM);
            //}
        //}
//
        //void rightDown() {
            //if (rActing == false) {
                //rActing = true;
                //doDownActions(rActions, modeR);
            //}
        //}
//
        //void leftUp() {
            //if (lActing == true) {
                //lActing = false;
                //doUpActions(lActions, modeL);
            //}
        //}
//
        //void middleUp() {
            //if (mActing == true) {
                //mActing = false;
                //doUpActions(mActions, modeM);
            //}
        //}
//
        //void rightUp() {
            //if (rActing == true) {
                //rActing = false;
                //doUpActions(rActions, modeR);
            //}
        //}

};

ActionManager actionManager = ActionManager();

void setup() {

    Serial.begin(115200);

    pinMode(PinLED, OUTPUT);

    //pinMode(PinRight, INPUT_PULLUP); // sets the digital pin as output
    //attachInterrupt(PinRight, isrChangeR, CHANGE); // interrrupt is data ready
//
    //pinMode(PinMiddle, INPUT_PULLUP); // sets the digital pin as output
    //attachInterrupt(PinMiddle, isrChangeM, CHANGE); // interrrupt is data ready
//
    //pinMode(PinLeft, INPUT_PULLUP); // sets the digital pin as output
    //attachInterrupt(PinLeft, isrChangeL, CHANGE); // interrrupt is data ready

}

void loop() {

    //if (Serial.available()) {
////change mode
        //mode = Serial.parseInt();
//
////release all buttons
        //Keyboard.releaseAll();
        //Mouse.set_buttons(0, 0, 0);
//
////turn off LED
        //digitalWrite(PinLED, LOW);
//
////flush the serial input buffer
        //while (Serial.available()) {
            //Serial.read();
        //}
//
    //}
    //delay(1000);
    //Serial.println("Running");
}

//void isrChangeL() {
    //cli();
    //if (digitalRead(PinLeft) == LOW && nextPressLeft < millis()) {
////Serial.println("Pressed");
        //digitalWrite(PinLED, HIGH); //set the LED on
//
        //if (mode == 0) {
            //Mouse.set_buttons(1, 0, 0);
        //} else if (mode == 1) {
            //Keyboard.press(KEY_F11);
        //} else if (mode == 2) {
            //Keyboard.press(KEY_LEFT_CTRL);
            //Keyboard.press(KEY_LEFT_ALT);
        //} else if (mode == 3) {
            //Keyboard.press(KEY_W);
        //}
//
        //nextPressLeft = millis() + timeBetween;
//
    //} else {
//// Serial.println("Released");
        //digitalWrite(PinLED, LOW); // set the LED off
//
        //if (mode == 0) {
            //Mouse.set_buttons(0, 0, 0);
        //} else if (mode == 1) {
            //Keyboard.release(KEY_F11);
        //} else if (mode == 2) {
            //Keyboard.release(KEY_LEFT_CTRL);
            //Keyboard.release(KEY_LEFT_ALT);
        //} else if (mode == 3) {
            //Keyboard.release(KEY_W);
        //}
//
        //nextPressLeft = millis() + timeBetween * 0.6;
//
//
    //}
    //sei();
//}
//
//void isrChangeM() {
    //cli();
////if (digitalRead(PinMiddle) == LOW && nextPressCenter < millis())
////{
////Keyboard.press(KEY_SPACE);
////delay(250);
////Keyboard.release(KEY_SPACE);
////}
//
    //if (digitalRead(PinMiddle) == LOW && nextPressCenter < millis()) {
////Serial.println("Pressed");
        //digitalWrite(PinLED, HIGH); //set the LED on
////Mouse.set_buttons(0, 1, 0);
//
        //nextPressCenter = millis() + timeBetween;
//
    //} else {
//// Serial.println("Released");
        //digitalWrite(PinLED, LOW); // set the LED off
////Mouse.set_buttons(0, 0, 0);
//
        //nextPressCenter = millis() + timeBetween * 0.6;
//
//
    //}
//
    //sei();
//}
//
//void isrChangeR() {
    //cli();
    //if (digitalRead(PinRight) == LOW && nextPressRight < millis()) {
////Serial.println("Pressed");
        //digitalWrite(PinLED, HIGH); // set the LED on
        //Mouse.set_buttons(0, 0, 1);
////Keyboard.press(KEY_F11);
        //nextPressRight = millis() + timeBetween;
    //} else {
//// Serial.println("Released");
        //digitalWrite(PinLED, LOW); // set the LED off
        //Mouse.set_buttons(0, 0, 0);
////Keyboard.release(KEY_F11);
        //nextPressRight = millis() + timeBetween * 0.6;
    //}
    //sei();
//}

```

compiler log:

```
Compiling debug version of 'click_switch_5_cycling' for 'Teensy LC'
click_switch_5_cycling.ino: In constructor ActionManager::ActionManager()

click_switch_5_cycling.ino: 106:53: error: expected primary-expression before '(' token

click_switch_5_cycling.ino: 106:66: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 106:83: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 109:53: error: expected primary-expression before '(' token

click_switch_5_cycling.ino: 109:73: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 112:53: error: expected primary-expression before '(' token

click_switch_5_cycling.ino: 112:79: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 113:53: error: expected primary-expression before '(' token

click_switch_5_cycling.ino: 113:78: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 116:53: error: expected primary-expression before '(' token

click_switch_5_cycling.ino: 116:71: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 121:53: error: expected primary-expression before '(' token

click_switch_5_cycling.ino: 121:66: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 121:85: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 126:53: error: expected primary-expression before '(' token

click_switch_5_cycling.ino: 126:66: error: expected primary-expression before '.' token

click_switch_5_cycling.ino: 126:84: error: expected primary-expression before '.' token

click_switch_5_cycling.ino:1: In file included from
LinkedList.h: In instantiation of bool LinkedList<T>::add(T) [with T = Action]
click_switch_5_cycling.ino:83: required from here

LinkedList.h: 192:37: error: use of deleted function 'ListNode<Action>::ListNode()
ListNode<T> *tmp = new ListNode<T>()
LinkedList.h:19: note  ListNode<Action>  ListNode() is implicitly deleted because the default definition would be ill-formed
struct ListNode

LinkedList.h: 19:8: error: no matching function for call to 'Action::Action()
click_switch_5_cycling.ino:70: note  candidate  Action  Action(uint16_t, ActionType)
this->actionType = actionType
click_switch_5_cycling.ino:70: note    candidate expects 2 arguments, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(const Action&)
uint16_t keyCode
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(Action&&)
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided

click_switch_5_cycling.ino:1: In file included from
LinkedList.h: In instantiation of ListNode<T>* LinkedList<T>::getNode(int) [with T = ModeAction]
LinkedList.h:314: required from T LinkedList<T>  get(int) [with T = ModeAction]
click_switch_5_cycling.ino:106: required from here
LinkedList.h: 160:9: warning: converting 'false' to pointer type 'ListNode<ModeAction>*' [-Wconversion-null]
return false
LinkedList.h: In instantiation of bool LinkedList<T>::add(int, T) [with T = Action]
click_switch_5_cycling.ino:262: required from here

LinkedList.h: 177:37: error: use of deleted function 'ListNode<Action>::ListNode()
ListNode<T> *tmp = new ListNode<T>()
LinkedList.h: In instantiation of bool LinkedList<T>::unshift(T) [with T = Action]
click_switch_5_cycling.ino:262: required from here

LinkedList.h: 218:37: error: use of deleted function 'ListNode<Action>::ListNode()
ListNode<T> *tmp = new ListNode<T>()
LinkedList.h: In instantiation of T LinkedList<T>::remove(int) [with T = Action]
click_switch_5_cycling.ino:262: required from here

LinkedList.h: 290:12: error: no matching function for call to 'Action::Action()
return T()
click_switch_5_cycling.ino:70: note  candidate  Action  Action(uint16_t, ActionType)
this->actionType = actionType
click_switch_5_cycling.ino:70: note    candidate expects 2 arguments, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(const Action&)
uint16_t keyCode
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(Action&&)
Error compiling project sources
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided
Debug build failed for project 'click_switch_5_cycling'

click_switch_5_cycling.ino:1: In file included from
LinkedList.h: In instantiation of T LinkedList<T>::pop() [with T = Action]
click_switch_5_cycling.ino:262: required from here

LinkedList.h: 242:12: error: no matching function for call to 'Action::Action()
return T()
click_switch_5_cycling.ino:70: note  candidate  Action  Action(uint16_t, ActionType)
this->actionType = actionType
click_switch_5_cycling.ino:70: note    candidate expects 2 arguments, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(const Action&)
uint16_t keyCode
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(Action&&)
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided

click_switch_5_cycling.ino:1: In file included from
LinkedList.h: In instantiation of T LinkedList<T>::shift() [with T = Action]
click_switch_5_cycling.ino:262: required from here

LinkedList.h: 268:12: error: no matching function for call to 'Action::Action()
return T()
click_switch_5_cycling.ino:70: note  candidate  Action  Action(uint16_t, ActionType)
this->actionType = actionType
click_switch_5_cycling.ino:70: note    candidate expects 2 arguments, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(const Action&)
uint16_t keyCode
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(Action&&)
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided

click_switch_5_cycling.ino:1: In file included from
LinkedList.h: In instantiation of T LinkedList<T>::get(int) [with T = Action]
click_switch_5_cycling.ino:262: required from here

LinkedList.h: 316:14: error: no matching function for call to 'Action::Action()
T())
click_switch_5_cycling.ino:70: note  candidate  Action  Action(uint16_t, ActionType)
this->actionType = actionType
click_switch_5_cycling.ino:70: note    candidate expects 2 arguments, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(const Action&)
uint16_t keyCode
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided
click_switch_5_cycling.ino:65: note  candidate  constexpr Action  Action(Action&&)
click_switch_5_cycling.ino:65: note    candidate expects 1 argument, 0 provided

```

Thanks for any help you can give me about what these errors are and how to fix them.

# Answer
> 3 votes
You seem to have been programming in Java recently, because many of your errors have a Java ‘whiff’ to them. This, as you’ve tagged, is C++, not Java.

1. `sendMouseState`:

a. You wrote `leftPressed == true`. This is much more simply expressed by the expression `leftPressed`.

b. You wrote `middlePressed == false`. This is much more simply expressed using the “not” operator `!`, as in `!middlePressed`.

c. The code tests all eight possible combinations of `leftPressed`, `middlePressed` and `rightPressed`, calling `Mouse.set_buttons(#,#,#);`

However, `bool`s evaluate to numbers: `false` evaluates to `0`, while `true` evaluates to `1`. All eight tests, and therefore the entire function, can therefore be boiled down to the single line:

`Mouse.set_buttons(leftPressed, middlePressed, rightPressed);`
2. You declared to the compiler, in a few places, “There’s going to be a function called (e.g) `void mouseButtonPress(MouseButtons theButton);`

That’s fair enough - but the compiler only needs that if you’re going to *call* the function before you *define* it. Since you follow the declarations *immediately* by the definitions, the declarations are unnecessary: get rid of them.
3. Use of `enum`s:

Declaring an `enum` lets you use symbols instead of raw numbers: well done! However, that’s *all* you need to use: the `enum`’s symbol: `LEFT`, `MIDDLE` or `RIGHT` is all you need.

If you do feel the need to express the `enum`’s name, you need to use the `::` operator, not the `.` operator: `MouseButtons::LEFT`.
4. Use of `new`:

You do not need to call `new` to create members of classes. Well, OK, you might if they’re declared as pointers (which you have done), but that’s your problem: you should declare them as simple members, not pointer members.

For example, instead of:

```
LinkedList<Action> *keys = new LinkedList<Action>();

```

you simply need:

```
LinkedList<Action> keys;

```

Note that no `new` is needed now. Then, everywhere that you dereference the member with `keys->add(action);`, you use `keys.add(action);` instead.
5. Use of `this->`:

You use `this->` a lot. You practically never have to: however, the one time you did need to was in the code:

```
Action (uint16_t keyCode, ActionType actionType) {
    this->keyCode = keyCode;
    this->actionType = actionType;
}

```

Here, `this->` was needed to distinguish the class members from the passed-in parameters that have the same name. However, if you’d written the constructor correctly, using initialisation instead of assignment, you wouldn’t have needed `this->` here either:

```
Action (uint16_t keyCode, ActionType actionType) :
    keyCode(keyCode),
    actionType(actionType) {
}

```
6. `add()` followed by `get()`:

You use the following code:

```
lActions.add(ModeAction());
lActions.get(lActions->size() - 1).addAction(Action(LEFT,MOU));

```

That is, you add an empty `ModeAction`, then fetch it back with `get(...)` before manipulating it. Don’t.

Instead, create a temporary `ModeAction` object, get it ready, *then* `add()` it to the list:

```
ModeAction lMode1;
lMode1.addAction(Action(LEFT,MOU));
lActions.add(lMode1);

```

# Answer
> 1 votes
The compiler is giving you a clue that the problem is around line 106. You have there:

```
  LinkedList<ModeAction> *lActions = new LinkedList<ModeAction>();
  LinkedList<ModeAction> *mActions=new LinkedList<ModeAction>();
  LinkedList<ModeAction> *rActions=new LinkedList<ModeAction>();

```

You can't do procedural code (like `new`) in a data declaration. Also, I doubt that there is a function to be called so I would get rid of the brackets. Initializing member fields should be done in the constructor, not in the declaration.

# Answer
> 0 votes
you use wrong syntax to access an enum member. use `::` not `.`

`Action(MouseButtons::LEFT, ActionType::MOU)`

EDIT:

second error is that LinkedList requires constructor without parameters on the template type

add constructor without parameters to class Action

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


# Question
Title: Password.h and keypad.h change pass sketch for Arduino
I have a fixed password. If letter "D" is pressed on the keyboard and the correct password is entered, the fixed password will be then changed. This newly entered password is now the correct password, until the user decides again to change password. It is not working. **How to fix it?**

```
#include <Keypad.h>
#include <Password.h>

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns

const char keys[ROWS][COLS] = {
    {'1','2','3','A'},
    {'4','5','6','B'},
    {'7','8','9','C'},
    {'*','0','#','D'}
  };
const byte rowPins[ROWS] = {9,8,7,6};
const byte colPins[COLS] = {5,4,3,2};

Keypad    keypad { makeKeymap(keys), rowPins, colPins, ROWS, COLS };
Password passwd = Password("123A4");
char passwd2;

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

void loop() {

  char key = keypad.getKey();
   if (key != NO_KEY){
      delay(60);
      switch (key){
      case 'D': changepasswd(); break;
      case '*': checkpasswd(); break;
      case '#': passwd.reset(); break;
     default: passwd.append(key);
      }
   }
}

void checkpasswd() {

  Serial.print(passwd2);

   if (passwd.evaluate()){
      Serial.println(" OK.");
   } else {
      Serial.println(" Wrong password!");
   }
   passwd.reset();
}

void changepasswd() {
  char key = keypad.getKey();
      delay(60);
      Serial.print(key);
      passwd2 += key;
      passwd.set(passwd2);

   Serial.print("Password changed to ");
   Serial.println(passwd2);

}

```

# Answer
> 1 votes
The logic of your function is garbled:

1. **Function `checkpasswd()`**: Most of the function is ok, but you don't need to send `passwd2` through Serial, since it doesn't have anything to do with this function. You only use the variable for setting a new password. You can ditch this print statement.
2. **Function `changepasswd()`**: Here lies the problem. Most likely `getKey()` returns `NO_KEY` here, which is defined as the null character. So, when outputting it to Serial, you don't see anything there (The null character marks the end of a string in C/C++). You set the password to be the null character, which cannot every be inputted by the user. Also there lies another pitfall: The Arduino Playground Site for the `Password` library states for the `set()` function:
> Warning: The new password should be a global variable (not a local function variable) as this function copies a pointer to the new password into the library, not a copy of the password.

Since the `key` variable is only local, after the function the `Password` library has it's internal pointer pointing to a now freed memory space. At some other point in the program this space might be written again, effectively changing to password to something else.

And lastly the function does not contain any loop, so only 1 character will be inputted and the newly set password can only be 1 character long. The buffer variable `passwd2` is of type `char`, so also only 1 character. What you really need there is a `char []` (character array).

Here is a bit of code (not tested), that should implement this correctly:

```
char passwd2[6]=""; //global buffer for new password
                    // 6 bytes, because a C string has to end with the null character

void changepasswd(){
    for(byte i=0;i<5;i++){
        char key = NO_KEY;
        while(key == NO_KEY || key=='*' || key=='#' || key=='D') key = keypad.getKey();
        passwd2[i] = key;
        delay(60);
    }
    passwd2[5] = '\0'; //ensure correct string ending
    passwd.set(passwd2);
}

```

Note the following points:

* This implementation blocks the programs execution, until a full valid password has been typed. It will ignore all invalid characters, that you use for other purposes (`#`, `*` and `D`).
* The `passwd.set(passwd2)` is actually only necessary the first time, we change the password, to let the `Password` object have a pointer to our buffer. After that we technically can change the password directly in the buffer, without calling the `set()` function. I included it here for readability and making the code a bit more fail prove (against wrong futher coding).
* This is hardcoded to accept only 5-digit passwords. If you want passwords with arbitrary length, you can start programming from this basis.
* Debouncing buttons with a simple `delay()` may be not enough at some point. But as I understand the source code of the `Keypad` library, it also includes code for debouncing, by only checking every 10ms for a changed button and returning `NO_KEY` everytime else.

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


# Question
Title: NodeMCU v1.0 high power consumption in deepsleep
I am using a NodeMCU v.1.0 ESP-12 for a small project. It is powered by 3xAA batteries (4.5v) in Vin, but to reduce power consumption I need to put in in deepsleep every now and then.

Running this small sketch:

```
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(2000);

  // Wait for serial to initialize.
  while(!Serial) { }

  Serial.println("I'm awake.");

  Serial.println("Going into deep sleep for 20 seconds");
  ESP.deepSleep(20e6); // 20e6 is 20 seconds
}

void loop() {
}

```

I have measured a consumption of 8mA when it goes to deepsleep, and this is not acceptable for my purpose. In order to wake up from sleep I have connected pin GPIO16 (D0) to RST, and it works. I knew that NodeMCU should have only few µA of consumption in deepsleep. How can I fix this?

# Answer
Consider the TI TPL5110 timer chip with power control MOSFET. Set the timer period with a resistor then the TPL5110 powers on the NodeMCU periodically. Deep sleep is not used. RTC RAM will be lost so use SPIFFS for persistent data.

Adafruit has a breakout board. Take a look in Adafruit's forum for user comments because it has a few limitations.
> 1 votes

---
Tags: esp8266, wifi, nodemcu
---


title: I2C call during Wire.requestFrom

text:
# Question
Title: I2C call during Wire.requestFrom
Which I2C command happen during `Wire.requestFrom(address, quantity)`?

Is it correct that Wire put a Start condition, then 7-bit address appended with read bit? How would that be different from Wire.write(address)?

# Answer
There is no `Wire.write(address)` in the `Wire` library. The function `write()` takes data and puts it into the library internal write buffer. It does nothing on the I2C bus.

For master write operation (sending from master to slave) the following commands are necessary:

```
Wire.beginTransmission(address);
Wire.write(data);
Wire.endTransmission();

```

Only the last of these commands does something on the I2C bus. It generates a Start condition, sends the byte consisting of the address (that we set in the `beginTransmission()` statement) and the direction bit, which is always `0` here, because these commands are meant for master write operation. Then it sends the data and ends the transmission with a stop condition. You cannot control, which value the direction bit has. The parameter of `beginTransmission()` is only meant to be 7 bit long. If you provide a bigger address, the function will simply cut the highest bit and issuing a write operation anyway.

For master read operation the action on the I2C bus happens inside the `requestFrom()` function. It sends a Start condition, followed by the address and the direction bit set to `1` (again you cannot control the value of the direction bit here). Then it reads the bytes, that are coming from the slave until all requested bytes were received. Then you can read the bytes from the library internal buffer with the `Wire.read()` function. Again this function does nothing on the I2C bus. It only interacts with the libraries buffer.
> 2 votes

# Answer
When you send an address with write(), it is a register address on the device, not the device address on the bus.

The device address is set with beginTransmition() and requestFrom().

If the device requires to set the register before requestFrom(), the register address should be sent with write() wrapped in beginTransmition() and endTransmition().

Example:

```
Wire.beginTransmission(I2C_ADC121);
Wire.write(REG_ADDR_RESULT); // send register to read, the 'result' register
Wire.endTransmission();
Wire.requestFrom(I2C_ADC121, 2);
byte buff[2];
Wire.readBytes(buff, 2); // read value of the 'result' register

```
> 0 votes

---
Tags: i2c, wire-library
---


title: Arduino UNO dead with CNC shield

text:
# Question
Title: Arduino UNO dead with CNC shield
I have an Arduino UNO with a CNC shield. The Arduino is almost certainly a clone.

I installed GRBL with no issue and I have assembled a jig with CD-ROM motors. My first attempt to control this with UGS worked no problem.

I powered down to change the stepping with the jumpers and powered back up and was presented with a very hot smell after a few moments.

I removed the power quickly but now I can no longer program the UNO. It gets recognized in my devices but I can't send any code, even blink.

The jumpers were set like many examples I have seen on the web so I don't think this was the issue.

I am wondering if the way I powered it up was the issue? I am supplying the UNO with 12V 2A supply and I can't recall what order I plugged them in but I get the feeling it must have been supplying 12V to the Arduino.

I have now removed the shield and powering the unit solely from the USB and still can't communicate.

I have resigned to the fact this board is now toasted. Is it important which order you plug in the Arduino? USB first? Do you think it will be possible to recover this Arduino.

# Answer
This sounds as the ATmega328p processor of the UNO was fried. As the UNO has a second processor (ATmega16U2) which is simply a USB-to-serial converter you only see the presence of this in the list of USB devices but it cannot communicate with the board's main processor anymore.

The plug-in order is not that important with the UNO board only but depending on the components you have attached it may be important. especially if the circuit does not have protection against induction current, p.e. fly-back diodes.
> 1 votes

# Answer
Genuine Arduino's have an input limit of 20v and a recommended voltage of 7-12v. I naively assumed that the same would be for the clone but it has a max input voltage of 9v. Supplying 12v to the unit worked for a short time but the regulator must have melted and cooked the main processor.
> 1 votes

# Answer
The same exact thing happened to me. I was using A4988 on a CNC shield which was mounted onto my arduino uno by rexqualis. A couple days ago it was working (inconsistently) to move my NEMA 17 motors. Today, I adjusted the potentiometers on the A4988 to try to improve consistency when my arduino would no longer connect to the serial port. I took the shield off and realized the arduino was very hot. Now it gets hot anytime I plug it even with no inputs or outputs. It will still not connect to the serial port.

I was using 12V of power going into the CNC shield. This and 9v seemed to work a couple days ago. I am not sure of how to avoid this problem in the future, but I am thinking that I need to put the potentiometers where they were before.
> 1 votes

---
Tags: arduino-motor-shield
---


title: Connect arduino pro mini 3.3v to 5v

text:
# Question
Title: Connect arduino pro mini 3.3v to 5v
Is it safe to run an arduino pro mini 3.3v by 5v? I mean directly connect 5v to vcc not raw pin.

# Answer
> 2 votes
Yes you can.

The only difference between the 3.3 V and 5 V Pro Mini is the crystal and the voltage regulator.

# Answer
> 2 votes
Yes, an 8 MHz resonator-clocked Promini will happily work at 5V vs 3.3V.

If you want, add a diode from VCC to the RAW pin to protect the regulator, altho it's datasheet does not indicate such is warranted. Anecdotally, I used about 10 of these in my fencing club powered from 5V to the VCC line for quite a few years with no such protection and they ran fine for ~ 10 years, until we closed the club.

---
Tags: arduino-pro-mini
---


# Question
Title: Use an Arduino Mega in a incubator (high humidity)
I wonder whether it is possible to use an Arduino Mega in a cell incubator.

In the incubator there is a temperature of 37°C, 5% CO2 in the atmosphere and a high relative humidity of around 95% - 98%. I think the temperature (specs of ATmega2560, temperature range: -40 °C to 85 °C) and the CO2 is no problem.

But I am concerned the condensation due to the high humidity will cause damage.

One mitigation could be, that I first pre-warm the Arduino Mega so it doesn't condensate.

(There is a possibility that I don't put the Arduino in the incubator at all, but it would be easier if I could).

# Answer
"-40 °C to 85 °C" for the processor, yes, for the other parts, who knows?

The board doesn't get that hot unless you are powering from like a 12V source, and then it's just the regulator that gets hot.

You could a spray-on conformal coat, Mouser.com carries them. Insert any wires into the headers you will use and cover any headers you may want to use before you spray, if you get coating down into the female headers you may have poor contact later on.

The ziplock bag idea sounds like a good start as a start, put some silicon along the seal to fill the holes where the zipper won't close right next to the wires.
> 1 votes

---
Tags: arduino-mega
---


# Question
Title: I can't manage to upload multiple sketches
I'm doing a gardening project. It involves multiple sensors and even having the sketches for them, I don't know how to make them run together and get a reading on them at the same time. I'm really new with this. It's my first Arduino ever.

I seem to manage getting a read on one of the sensors, but whenever I try to upload a new sketch, it fails to load.

Here are a couple of the codes I want to run together. One is a temperature/humidity sensor and the other one a soil humidity sensor.

Thanks in advance!!!

```
#include "DHT.h"          // DHT & AM2302 library

// Data pin connected to AM2302
#define DHTPIN 2

#define DHTTYPE DHT22       // DHT 22  (AM2302)

DHT dht(DHTPIN, DHTTYPE);   // LED pins

//////////////////////////////////////////////////////
//
// SETUP
//
void setup() {
  // Setup serial monitor
  Serial.begin(9600);
  dht.begin();
}

void loop() {

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow     sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then     something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println(F("Failed to read from DHT"));
  }
  else {
Serial.print(F("Humedad: "));
Serial.print(h);
Serial.print(F(" %\t"));
Serial.print(F("Temperatura: "));
Serial.print(t);
Serial.println(F(" C"));
  }

  // Wait 3 seconds
  delay(3000);
}

```

**The other code:**

```
   //////////////////////////////////////////////
  //        ARDUINO SOIL MOISTURE DEMO        //
 //                                          //
//           http://www.educ8s.tv           //
/////////////////////////////////////////////

int sensorPin = A0;
int sensorValue = 0;
int percent = 0;

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

void loop() {

  sensorValue = analogRead(sensorPin);
  percent = convertToPercent(sensorValue);
  printValuesToSerial();
  delay(1000);
}

int convertToPercent(int value)
{
  int percentValue = 0;
  percentValue = map(value, 1023, 465, 0, 100);
  return percentValue;
}

void printValuesToSerial()
{
  Serial.print("\n\nAnalog Value: ");
  Serial.print(sensorValue);
  Serial.print("\nPercent: ");
  Serial.print(percent);
  Serial.print("%");
}

```

# Answer
> I can't manage to upload multiple sketches

The arduino can only run *one* sketch at a time. You can do multiple things in a single sketch, but you can only have one sketch.

> ... but whenever I try to upload a new sketch, it fails to load.

What exactly fails? You should be able to change sketches, the new sketch should replace the old sketch; If this isn't working you have another problem all together.

> Here are a couple of the codes I want to run together ...

You will have to write a new sketch that combines the behavior of the two sketches.

something like:

```
...
setup()
{
    // common setup code goes here
}
...
loop()
{
    int sensor_reading_1 = analogRead(sensor_pin);
    float sensor_reading_2_h = dht.readHumidity();
    float sensor_reading_2_t = dht.readTemperature();

    ... // do stuff with the readings
}

```
> 2 votes

---
Tags: sensors
---


title: Creating a Web Interface for ESP32

text:
# Question
Title: Creating a Web Interface for ESP32
I am working on a project that involves moving various servos and lights and I need a good UI to work with the device. I've previously used Blynk, which worked very well but I didn't like some of the limits it has. My current code works with Blynk and I'd like to change it to a web server so it can work on any device without an app or internet connection.

Right now my esp configures itself as an access point and I can navigate to its IP address to get to my "hello world file" but after that I'm stuck. What really stumps me is getting the input from the interface that I make in HTML, I could fairly easily make an arrangement of buttons, sliders, and fields, that fits my need but how do I get the value of these as a variable in my arduino code?

I've seen some examples of code that are very simple essentially a couple buttons redirect to different web pages on the server and it takes these commands to assign a variable, but that seems kind of poor form, is there a better way, or how do I make that work with a complex interface with many buttons and switches.

I've heard of Jquery and Ajax but not familiar on how to make this work with Arduino code.

# Answer
I would highly recommend splitting it into two parts: back end (C++) and front end (JS). You'll probably want to connect to a router, so your clients, like a phone and laptop need not be on that AP hotspot w/o internet.

You first build an API with arduino using GET params to control, example pin values `int level = server.arg("level").toInt(); analogWrite(2, level);`, or whatever you need to do. Put that in a function called handlePin, and subscribe it in setup(): `server.on("/pin", handlePin);`. Then just add CORS to the server response: `server.sendHeader("Access-Control-Allow-Origin","*");` and you can now hit it from any computer on the network. To test, just enter it's URL and some params into a browser URL bar; `http://192.168.2.123/pin?level=512` to dim halfway.

Once you have the URLs working, the interface part is built completely separately using whatever tools you want. All you need to do is have your UI hit the API using simple ajax calls. As a quick and dirty example: `Level:<input type=range id=val max=1024> <br> <button onclick="fetch('http://192.168.2.123/pin?level='+val.value)">update</button>`

That's hows the pros do it, you just swap C++ for PHP or C# or whatever, and use any UI framework you want. Once you have the source of your client app ready, you *can* upload it to the SPIFFS of the ESP, but I find it easier to host and update system-wide on a "real" server.

If you don't want to write the UI code yourself, you can use node-red to make a quick and dirty "control panel", just like HTML but with drag and drop functionality (more or less). You still use the same API on the ESP, and you can use more than one system at a time; all the ESPs care about is hitting the right URL.
> 1 votes

# Answer
> I could fairly easily make an arrangement of buttons, sliders, and fields, that fits my need but how do I get the value of these as a variable in my arduino code?

The same way a web server does! What you need to do is implement a web server on the ESP32. You will serve a page with the controls, and then that page must make a request back to the server which will then processes it and do whatever you program it to do.

There are two ways to do this:

* Use a get/post form; send all the data at once
* Something like ajax; each control sends data asynchronously
> 0 votes

---
Tags: web-server, esp32, web
---


# Question
Title: Why is my DHT22 sensor reading 1.00% humidity?
I have a seemingly simple problem but I haven't found a solution yet. I recently got a DHT22 temp/humidity sensor and I wired it according to the guide from Adafruit.

I downloaded and installed the library. I loaded the "DHTtester" example sketch. I also included the Adafruit Unified Sensor library to be safe, because the guide said I might need to. But when I upload the sketch and check the serial monitor the humidity value is always "1.00%". The temperature also seems to be off by about 4 degrees F.

I don't know what is going wrong here. I've removed the 10K resistor but nothing changed. Does anyone know why this might be happening? Any help would be appreciated. Thanks!

# Answer
This problem mainly happens when DHT11 sensor is mistaken with DHT22 or vice versa. Try testing it for DHT11, can you send the picture of sensor and circuit connection if possible.
> 1 votes

# Answer
I have 2 suggestions for you.

1. If you compare these 2 data sheets: This one says "adafruit learning systems" on it and this one is from the Adafruit website , you'll see there is a discrepancy regarding the pull-up resistor value to use. One document says 10k ohm, the other says 1k ohm. It's a bit of a long shot, but you could try adding another 10k ohm resistor in parallel with the one you already have on the data line. This gives you an equivalent resistance of 5k ohm which works when used on a DHT11 sensor (cheaper, less accurate version of the DHT22).
2. There are several versions of the DHTxx library out there, so my next suggestion is to try a different one. You may have to remove the library you currently have installed before trying a new one.
> 1 votes

# Answer
When I have rigged up these sensors to test, I breathe on them. Both the temperature and humidity should rise as breath is warm and humid.

From memory, I have seen the humidity rise from ~40% to ~70%, and temperature by at least 5 degrees.

If you see temperature rise but not humidity, then the humidity part may not be working (perhaps as smajli suggests).

There is also a checksum in the data, so I imagine that if there was a problem with communications, the result would be -1 or nothing at at all.
> 1 votes

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


# Question
Title: Tiny RTC module doesn't work properly when connected to an Arduino Uno together with 16x2 LCD
I am trying to make a digital clock using a tiny RTC, 16x2 LCD, and Arduino Uno. The RTC module works fine if 16x2 LCD is not connected to the Arduino. Both RTC and LCD are I2C modules and hence are using the same A4 and A5 pins of the Arduino. I have been informed that the I2C devices if connected in parallel should work. But, in this case, the clock doesn't show the time properly.

# Answer
An I2C scanner sketch can help to identify the actual addresses in use. I would use a sketch like on this page https://playground.arduino.cc/Main/I2cScanner or on this page http://gammon.com.au/forum/?id=10896&reply=6#reply6 . Or google 'arduino i2c scanner'.

Hook up the RTC by itself and run the scanner, then hook up the LCD by itself and run the scanner. The output will be on the serial monitor. If the devices have the same address, then that is your problem.

If one of the devices does not show up at all, then perhaps it is defective.
> 1 votes

---
Tags: arduino-uno, rtc
---


# Question
Title: YL-38 output to NodeMCU v1.0 analog input
Using a YL-38 and NodeMCU v1.0 I am trying to achieve what the first link is doing, take a soil moisture reading. I've done this on an arduino, but the conversion from an arduino nano to a nodemcu is proving difficult.

To my understanding, the nodemcu A0 pin operates from 0v-3.3v but the YL-38 analog output operates from 0-4.1v. So first off, is my understanding correct?

I struggle with hardware, so looking around I found these resources:

How to set up a simple level shifter: this setup seemed pretty much like what i wanted, but the 5v input was off

This thread was verbatim what I wanted but I am terrible with circuit math, so I couldn't solve or understand the provided formulas.

Attempt 0: Initially had sensor analog out connected to a0 on nodemcu. Saturated or dry the mcu read 1023. Thought this must be because the signal out is above the A0 mapping range.

Attempt 1: I figured I'd try out the level shifter. Wired it all up as indicated. Now my readings were 760 saturated and 765 dry.

```
runHygrometer(index);
delay(2000); //allow hygrometer to wake up
reading = (DEBUG) ? analogRead(HYGROMETER_READ_PIN) : 1023 - analogRead(HYGROMETER_READ_PIN);

```

As shown, my code does no scaling, It's a direct read (DEBUG is true here). So what gives? When using an arduino the range of readings was typically from 20 dry to 180 saturated (DEBUG false, so raw 1003 dry and 843 saturated)

# Answer
> 3 votes
> To my understanding, the NodeMCU A0 pin operates from 0v-3.3v

~~Incorrect. The ESP8266's ADC can only measure between 0V and 1V.~~

~~You need to reduce your output voltage down to that range. How you do that very much depends on the *output impedance* of the YL-38.~~

The LM393 that the YL-38 is based around looks to have a maximum output current of 16mA. That should be enough to happily drive a simple voltage divider. A 4.7kΩ and 1kΩ divider would give you 0 to 0.877v out from a 0-5V input.

simulate this circuit – Schematic created using CircuitLab

An alternative would be to attach an external ADC running at 5V to the NodeMCU. This would give you multiple channels of analogue input with a 0-5V range. I use the MCP3208 running over SPI (I actually bit-bang it on the ESP8266 rather than using SPI, since I haven't yet got SPI to work properly with it). Ideally, you want a proper logic level translator for the SCK and MOSI signals to boost them to 5V. It all gets a little complex, though.

---

It has come to light that the NodeMCU includes a voltage divider already. For some reason they chose to use massive resistors, which give far too high an impedance for any reasonable ADC input to accurately work with. I would suggest, if you can, removing those resistors from the board and replacing them with 4.7k and 1k resistors to form your own voltage divider. Otherwise you're going to have to use a pair of op-amps in inverting mode, one with a fractional gain, and one with unity gain (the second is to "undo" the inverting of the first one) to reduce the signal to 0-3.3V.

TBH I'd be inclined to use an external ADC anyway for this.

---
Tags: voltage-level, nodemcu
---


# Question
Title: Best practice to declare a 'static' text and save memory
I'm working on a project where I need to create a JSON to send back state of an object. I created the code to achieve it and all works fine, but I used this to declare the JSON fields:

```
static const String JSON_FIELD_A;

```

then in the .cpp file

```
const String MyClass::JSON_FIELD_A = "field_a";

```

In this way I can use that in several point inside my class (eg. to create and parse JSON) without needs to write the field name each time which may cause inconsistency after a refactoring.

I'm not sure about this way anyway... is there a more efficient way to achieve that? Using #define may be a solution?

# Answer
The "traditional" way is to use `PROGMEM` and use `const char *` strings.

I don't use the "traditional" way. Instead I use some "helper" classes and macros that WString.h provides.

This does mean, though, due to limitations in C++, that you have to create your string constants in two stages.

First is to define your variables:

```
const __FlashStringHelper *stringOne;
const __FlashStringHelper *stringTwo;

```

Then you need to assign the actual strings to those variables within a function. This could be in `setup()`, but I prefer to define an `initializeStrings()` function that `setup()` calls:

```
void initializeStrings() {
    stringOne = F("This is the first string")
    stringTwo = F("This is the second string");
}

void setup() {
    initializeStrings();
}

```

You can then pass these objects (they're not really objects, it's all just some magic casting done by the compiler) as parameters to other functions using `const __FlashStringHelper *` as the type. They can also be passed directly to any of the `.print()` and `.println()` functions provided by the `Print` class (which all `Stream` objects ultimately inherit).

If you want to use the standard C string library functions `_P` variants for manipulating the strings (concatenating them to other strings, for instance), you can simply cast them to `PGM_P`:

```
char temp[50];
strcpy_P(temp, (PGM_P)stringOne);
strcat_P(temp, (PGM_P)stringTwo);

```

Another alternative to all that is to use precompiler macros.

```
#define STRING_ONE F("This is the first string");
#define STRING_TWO F("This is the second string");

```

Again, you can cast those to `PGM_P` to use the `_P` variants of the standard C string library functions, and pass them directly to `print` functions, since they are replaced verbatim as `F("This is the first string")`, and `F()` does a reinterpret-cast to `const __FlashStringHelper *`.
> 3 votes

# Answer
`const String` does make nothing constant. You create an object, which can't be reassigned, but all methods work. Because it handles the characters inside and the const declaration doesn't change it. You can delete the content, change the content, append the content of the String object.

You should use `const char*` or `const char[]`. It is an c-string and the compiler checks if it is handled as a constant at gives at least a warning if not.

To save RAM the `const char[]` should be declared as PROGMEM. At runtime then this string isn't copied into RAM. You can use it with functions with \_P postfix or copy it temporally to RAM.

Example from my project:

global char array with PROGMEM

`const char data[] PROGMEM = "{\"suspension_time_seconds\":10800}";`

use in a function

```
client.print(F("Content-Length: "));
client.println(strlen_P(data));
char buff[64];
strcpy_P(buff, data);
client.print(buff);

```
> 1 votes

---
Tags: string, code-optimization, memory-usage, constants
---


# Question
Title: How to detect water presence with only 2 wires
I don't know if this question belong here or on electronics SE.

A manufacturer just sent me a personalize device which include an ESP-32 and a Water Sensor.

My problem is that I don't know how to retrieve the water sensor data (if there is water or not).
When I used my Arduino Nano and a Funduino Water Sensor, it was easy to retrieve the value because this sensor got 3 connectors (VCC, GND, Data), I just had to do a basic `analogRead(DATA_PIN)`.

But now, as you can see on the diagram bellow, the water sensor is just composed of 2 wires. I presume that it will detect water when these two wires are going to be connected by water.

**So, How to detect the presence of water in Arduino using only these 2 wires ?**

**What I tried :**

* Analog Read on the pin GPIO33
* Digital Read on the pin GPIO33
* Try to use TOUCH\_PAD with this pin using `touchAttachInterrupt(T8, callback, Threshold);` but callback was never called
* Contact the manufacturer (He said that it works perfectly, he used touch\_pad for testing but never used Arduino IDE, only ESP-IDF that I really don't know)

simulate this circuit – Schematic created using CircuitLab

**EDIT:**

This image represent the back of the device with the sensor, inner wire is directly connected to GND and outer wire is connected to GPIO\_33. This is all, there is not hidden connectors or something else.

# Answer
Since all you have is 2 bare wires, the water simply forms a resistor between them.

You can use it as part of a resistive divider, with a fixed resistor between your analog input and +3.3V. The resistance between the wires will change from infinite (dry) to something much lower (wet) and the reading you get from the ADC will depict that.

You will need to experiment with different resistances in order to get reasonable values, but start with 10kΩ, or 100kΩ. If you use a very high resistance (in the order of 1MΩ or more) you may even be able to use it like a simple switch and connect it to a digital input.

Be warned, though, that this method will cause a small amount of electrolysis, causing one electrode to be eroded away and the other to gain extra material. For this reason it can be good to connect the resistor to a GPIO pin instead of directly to +3.3V and switch the GPIO pin HIGH when you want to do a reading (to provide power) and LOW (or INPUT) when at other times (to remove power). This will greatly increase the lifetime of your water sensor.
> 5 votes

---
Tags: esp8266, sensors, esp32
---