text:
Debouncing a button with interrupt
I tried to follow the answer here:
https://arduino.stackexchange.com/a/18545/51302
Unfortunately I can only get the interrupt to go once (on serial monitor is the time of that first interrupt), then nothing.
I know this has already been answered but I don't understand the mistake and would appreciate help.
What I'm trying to do:
get a button to set an interrupt to trigger foo and thus write the steps on the monitor.
I've left remarks to try and explain what I try to do, so it would be easier to understand what I left out or used incorrectly.
Thanks.

#define IRF520 A2
#define BUTTON 3
static unsigned long last_press = 0;
static bool button_state = HIGH;             //pull up resistor
volatile bool interrupt_flag = 0;            //when the interrupt fires, button press or noise
bool is_pressed = false;                     //after checking that the button was really pressed
bool was_pressed = false;                    //last state of the button
unsigned long button_pause_duration = 20;        //pause required to accept press in ms
unsigned long interrupt_time=0;

void button_interrupt() {
  interrupt_flag = true;                      //can be a false alarm
  Serial.print("interrupt time: ");         //this is the onlt step that works
  Serial.print(millis());
  Serial.print("\n");
}

void setup() {
  Serial.begin(9600);
  pinMode(IRF520, OUTPUT); //A2 controls IRF520
  pinMode(BUTTON, INPUT_PULLUP);  //pin D2 and D3 are sutible for interrupts
  attachInterrupt(digitalPinToInterrupt(BUTTON), button_interrupt, FALLING);
}

void debounce_button() {
  if (digitalRead(BUTTON) != button_state) {
    button_state = digitalRead(BUTTON);         //if button changed state remember the new state
    interrupt_time=millis();
  }
  if (button_state == LOW) {
    last_press = millis();
    Serial.print("last_press was updated to: ");
    Serial.print(last_press);
    Serial.print("\n");
  } else {
    last_press = 0;
    interrupt_flag = false;
  }
  if ( last_press && (millis() - last_press) > button_pause_duration) {
    last_press = 0;     //set to 0 for the next check
    is_pressed = true;   //button was really pressed
    Serial.print("last_press was set to 0 and is_pressed to true - BUTTON WAS PRESSED at: ");
    Serial.print(millis());
    Serial.print("\n");
  }
}

unsigned int foo(bool is_pressed) {
  if (is_pressed) {
    Serial.print("foo is active, MOSFET does its thing");
    Serial.print("\n");
    }
  }
}

void loop() {
 if(interrupt_flag){
    Serial.print("the button is now being pressed: ");
    Serial.print(millis());
    Serial.print("\n");
 }
 debounce_button();
 foo(is_pressed);
}

do not use serial.print() inside the interrupt handler ... set the interrupt flag and save the value of millis() ... do the  serial.print() inside loop()

Edited the question, tried it but it doesn't solve the problem.

the && in the if statement looks wrong ... what are you trying to do?

I check that the timing is good and that last_press is not 0. because it is 0 for the cases I ignore and if it is not 0, along with the other condition, ist a real event.

In general, it's a bad idea to use interrupts for bouncing buttons. And interrupts are not able to do debug printouts.

So, I grabbed a Mega and several pushbutton switches (one of which turned out to be a push-on, push-off, much to my bemusement), and ginned up a small Arduino program to illustrate an interrupt-driven button debounce technique.  Please feel free to point out any and all errors ;-)
Here is a small program to debounce any momentary contact switch.  The Mega interrupt line (pin 2, interrupt 0) triggers on any low-to-high or high-to-low transition.  the interrupt service routine (ISR) simply sets a flag to TRUE and exits.  If multiple interrupts occur before the loop() function can service the flag, the second and subsequent ISR calls do nothing (well, they set the flag, but since it was already set...).  The loop() code looks for a set flag, and if it finds one, generates a 50uSec pulse on a selected pin, delays 100mSec, resets the flag, and exits.  As long as the switch's contact bounce activity ceases before the 100mSec delay expires, one and only one pulse per transition will be generated.  YMMV.
/*
Small program to demonstrate switch debounce technique using an interrupt
The ISR is called for low-to-high and high-to-low transitions, and may get
called multiple times per button press.  However, the code in loop() ensures
that each transition produces one and only one pulse per transition, assuming
the typical 10-20 mSec max bounce duration.

Note that if the line 'delayMicroseconds(50); //used to show multiple bounces'
is used instead of the line 'delay(100);//ignore bounces for 100mSec', then
multiple contact bounces will each generate their own 50uSec pulse.  This is
useful for O'scope diagnosis if you happen to have one.
*/

#include <elapsedMillis.h>
#include <PrintEx.h> //allows printf-style printout syntax

StreamEx mySerial = Serial; //added for printf-style printing

//pin assignments
const int LED_PIN = 13;
const int BUTTON_PIN = 2;
const int BUTTON_STATE_PIN = 3;

//variables
bool buttonState = 0;
bool blinkState = 0;

// ================================================================
// ===               INTERRUPT DETECTION ROUTINE                ===
// ================================================================

volatile bool Interrupt = false;     // indicates whether MPU interrupt pin has gone high
void BtnInterrupt()
{
    Interrupt = true;
}

// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================

void setup() {
    // configure pins
    pinMode(LED_PIN, OUTPUT);
    pinMode(BUTTON_PIN, INPUT_PULLUP);
    pinMode(BUTTON_STATE_PIN, OUTPUT); //scope monitor pin
    digitalWrite(BUTTON_STATE_PIN, LOW);

    buttonState = digitalRead(BUTTON_PIN);
    mySerial.printf("Initial button state is %s\n", buttonState == LOW ? "LOW" : "HIGH");
    attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), BtnInterrupt, CHANGE);
}

// ================================================================
// ===                    MAIN PROGRAM LOOP                     ===
// ================================================================

void loop()
{
    if (Interrupt)
    {
        digitalWrite(BUTTON_STATE_PIN, HIGH);
        delayMicroseconds(50);
        digitalWrite(BUTTON_STATE_PIN, LOW);
        //delayMicroseconds(50); //used to show multiple bounces
        delay(100);//ignore bounces for 100mSec
        Interrupt = false;
    }
}

Here are two O'scope screen grabs. One shows the pulse train generated by a single button transition with a 50uSec delay, and the other shows the same switch with the 100mSec delay.  In both photos, the horizontal time scale is 500uSec/cm

Amazing answer. This deserves more likes!

this works really fine, thanks!

I think the problem is that you only trigger the interrupt when the button is pressed (interrupt FALLING)
Therefore, there is no opportunity to call debounce when the button is released.
Therefore, there is no way to change the button state variable back to HIGH (I.e. when the button is released).
To verify the hypothesis or gain some other insights, I suggest trying to put a debug statement in your loop similar to the following
  If (millis () >= debugTime) {
       DebugTime = millis() + 1000:   // output every second...
       Serial.print("value of button state is: ");
        Serial.println(button_state);
      // and a few other variables.
  }

I will leave it to you to properly declare debugTime (unsigned long) and choose a few other key variables (maybe interrupt flag) to print in the debug message block.
And i think you already have done so,  but also delete the print statements in your ISR.

The problem is that you need to check whether the last interrupt was far enough in the past that the output can be considered stable.
The most obvious solution to me is to have the ISR record the time it was called, and the main loop can simply check if that time is sufficiently before the current time.  The comparison is very cheap, and doesn't require a delay.
The "same record interrupt time and then compare" can cover multiple buttons on MCUs like the ATTINY85 which uses a single shared ISR.  The disambiguation etc. resides outside the ISR.


text:
SR505 PIR sensor Time Delay Using Ticker Library NodeMCU
I am trying to make the value of PIR sensor value HIGH for certain time using code. SR505 have a default time delay of 8 seconds. But I want to increase it to 20 seconds.
I am thinking of increasing it using TICKER library. I have tried and tested a basic code and seems to be working fine. But I want to implement it with Ticker which will keep the value HIGH for 20 seconds as soon as the timer goes above 20 seconds and PIR is not detecting the motion then it will go set again the timer to 0.
Here is how my code looks like:
#include <Ticker.h>

#define SIGNAL_PIN D2

Ticker flipper;

void setup()
{
  Serial.begin(9600);
  pinMode(SIGNAL_PIN, INPUT);
  digitalWrite (SIGNAL_PIN, LOW);

}

void flip(){
  Serial.println("From callback");
  digitalWrite (SIGNAL_PIN, HIGH);
}

void loop() {
  if(digitalRead(SIGNAL_PIN)==HIGH) {
    Serial.println("Movement detected.");
    flipper.attach(1, flip);
  } else {
    Serial.println("Did not detect movement.");
    flipper.detach();
  }
  delay(1000);
}

Thank you!

Why do you feel the need to use the Ticker library? There is absolutely no need. All you need is a millis() timestamp.

Ok but I never used millis() before. How that work I will just check. If you have any example based on the same scenarios that will be amazing.

I'm writing one for you as we speak.

You really don't need the Ticker library. Just maintain a timestamp of the last time the PIR was seen to be HIGH:
void loop() {
    static uint32_t lastSeenHigh = millis();
    static bool pirState = false;

    // If it's active then record that fact along with the time
    if (digitalRead(SIGNAL_PIN) == HIGH) {
        lastSeenHigh = millis();
        pirState = true;
    } else {
        // otherwise, if it's been 12 seconds since last seen
        // active, record that it's inactive.
        // 20 seconds, minus the 8 second active time, times 1000 is
        // 12000 milliseconds to extend the time by
        if ((millis() - lastSeenHigh) > 12000) {
            pirState = false;
        }
    }

    if (pirState == true) {
        // Do whatever you want in here when the PIR is active
    }
}

With that (untested) code:

Any time the PIR is active the current time is recorded and the state is set true
When the PIR is LOW and at least 12 seconds have passed since the last activation, set the state to false.

Thank you so much, its amazing its working great! No library needed.

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Combining code for multiple sensors (Current and Voltage Sensors) in one program
I need to operate 2 different sensors (Current and Voltage) simultaneously. I have managed to run each one of them separately and I don't know how to manipulate the code so they could work together. My background in coding is basic and I'm not the one who wrote these codes.
Here are the sketches:
1. Current Sensor Code
void setup() {

  Serial.begin(9600);
}

void loop() {

  float average = 0;
  for(int i = 0; i < 1000; i++) {
    average = average + (.0264 * analogRead(A0) -13.385) / 1000;//this is
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to
    //(.19 * analogRead(A0) -25) for 20A mode and
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(3);
  }
  Serial.println(average);
}

2. Voltage Sensor Code
/*
DC Voltmeter Using a Voltage Divider
Based on Code Created By
T.K.Hareendran
*/

int analogInput = A1;
float vout = 0.0;
float vin = 0.0;
float R1 = 30000.0; //
float R2 = 7500.0; //
int value = 0;
void setup(){
   pinMode(analogInput, INPUT);
   Serial.begin(9600);
   Serial.print("DC VOLTMETER");
}
void loop(){
   // read the value at analog input
   value = analogRead(analogInput);
   vout = (value * 5.0) / 1024.0; // see text
   vin = vout / (R2/(R1+R2));

Serial.print("INPUT V= ");
Serial.println(vin,2);
delay(500);
}

Please format your code appropriately, your question is very hard to read.

what have you tried to combine the codes? ... you did not say anything about what you expect the output to be.

The bigger problem regarding combining the code is timing. You can't use delay() because the other code can't run.
You need to do let loop() run through as fast as possible and only do things when you need to i.e. when certain time elapses. And you do that with millis(), like in the Blink Without Delay example.
In your case, current reading code also needs to keep track of number of samples read and react when the sample count is reached.
const byte current_pin = A0;
const byte voltage_pin = A1;

const int max_current_sample_count = 1000;
const int current_sample_interval = 3;
const int voltage_sample_interval = 500;

// voltage divider parameters
const float R1 = 30000;
const float R2 = 7500;

// 5A current sensor parameters
const float current_sensor_scale = 0.0264;
const float current_sensor_offset = -13.385;

float current_sum = 0; // for accumulated measurements
int current_count = 0; // counter for measurements

unsigned long last_current_measure = 0; // for timing the current measurement
unsigned long last_voltage_measure = 0; // for timing the voltagemeasurement

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

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

    if (time - last_current_measure > current_sample_interval) { // if enough time elapsed to make another measurement
        last_current_measure = time; // save the time this action ran

        current_sum += current_sensor_scale * analogRead(current_pin) + current_sensor_offset;
        current_count++; // increase the counter
        if (current_count >= max_current_sample_count) { // when we reached number of samples
            // output the average and reset the sum and counter
            Serial.print("A = ");
            Serial.println(current_sum/current_count);
            current_sum = 0;
            current_count = 0;
        }
    }
    if (time - last_voltage_measure > voltage_sample_interval) { // if enough time elapsed to make another measurement
        last_voltage_measure = time; // save the time this action ran

        int value = analogRead(voltage_pin);
        float vout = (value * 5) / 1024.0;
        float vin = vout / (R2/(R1+R2));
        Serial.print("V = ");
        Serial.println(vin, 2);
    }
}

It is also a good practice that some values, that might need to be changed, are defined as constants. So you don't need to search for them inside the code which can become a problem, when you write more code. And it can prevent bugs, if you have those values in multiple places and forgot to change one.

WARNING The following advice does not generally produce compiling or working code, but is one way to start merging two separate sketches.
Without getting into the details of the code (we are not here to write code for free) I can give you the general guidelines:

put all the declarations (anything not contained in the setup or loop functions) at the top, first all from one sketch, then all from the other
copy the setup function from the first sketch and paste it after all the declarations
copy the content (anything inside the curly braces) of the setup function from the second sketch and put it inside the same function, but after all the first sketch code
rinse and repeat the last two steps for the loop functions

At this point the you might have variable name collisions and plenty of other issues, but looking at the type of code you are trying to mesh, it should work

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Looking for SPI documentation
I'm trying to use an Arduino as a slave and was searching for examples which I found many. But apart from the examples, I haven't found any documentation explaining many thing that show up in those examples.
For example, I'd like a document that would state what things like the following are:
-SPCR
-SPE
-SPDR
-ISR
-SPI_STC_vect
I'm asking this, because I don't and can't just copy an example and hope that it'll work, I really need to know what I'm doing.
Thank you,
João

you know, there is a SPI library?

Yes, I do know there's a library. But is there any document available that says what are the resources of that library?

reference of he SPI library https://www.arduino.cc/en/Reference/SPI

Atmega datasheet http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-42735-8-bit-AVR-Microcontroller-ATmega328-328P_Datasheet.pdf

Thank you very much, I'll look into the Atmega datasheet, didn't occur to me looking into it.

Take a look at Nick Gammon's SPI explanations also. Very good, with timing explained as well.
http://www.gammon.com.au/spi

His work is amazing, unfortunately he doesn't explain what those things are, apart from ISR and SPDR. And I had no idea from where the other things came. But there are already good answers that give me somewhere to look into.
Thank you very much!

I also explain SPI right here on this site: https://arduino.stackexchange.com/questions/16348/how-do-you-use-spi-on-an-arduino/  - As for the register names, they are explained in the datasheet.

Whilst I have a personal interest in the answer, it simply isn't practical to include or even summarize a lengthy post like an explanation of how SPI works. The OP is asking for documentation and this answer is giving a link to it. In my comment above I point out that there is more documentation available on this site which means it is less likely to go link-dead. Another answer might be to reference the datasheet, which again would have to be link-only, unless maybe you quoted a couple of pages.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Playing Audio from SD - Get VU, or audio waveform
I am using the library SimpleSDAudio to play a song from my SD card to an op-amp later in the circuit. I would like to take a sample from the audio pin (possibly with a Analog read) to power some visualizations (VU, etc.), although I am getting some unexpected readings off the audio pin.
I tried to bias the audio using this post, but got the same results.
I'm not sure if I am headed in the wrong direction here, any help would be amazing.
#include <SimpleSDAudio.h>
int ReadPin = A0;
int AudioValue = 0;

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

  Serial.print(F("\nInitializing SD card..."));

  if (!SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_MONO | SSDA_MODE_AUTOWORKER)) {
    Serial.println(SdPlay.getLastError());
    while(1);
    } else {
    Serial.println(F("Wiring is correct and a card is present."));
  }

  Serial.print(F("Looking for THRILLER.WAV... "));
  if(!SdPlay.setFile("THRILLER.WAV")) {
      Serial.println(F(" not found on card! Error code: "));
      Serial.println(SdPlay.getLastError());
      while(1);
  } else {
     Serial.println(F("found."));
  }

  Serial.print(F("Playing... "));
  SdPlay.play();

}

  void loop() {
    AudioValue = analogRead(ReadPin);
    Serial.println(AudioValue);
    delay(50);

}

My expected output of sampling the output from A0:

what does this mean? some unexpected readings

I would expect to see something similar to a wave form. Like I would see in Audacity. As the audio plays, I would see different values based upon the level of the output. Sorry if it's confusing.

it is not confusing ... it is just pointless to say that something is unexpected, without an explanation, because nobody else knows what you are expecting

@jsotola I have added an "expected" image. Thanks.

You are sampling your audio signal with only 20Hz. That is very low frequency for an audio signal, that humans can hear. Generally you need to sample your signal with double of the highest containing frequency at minimum, or you will only get nonsense (you can google Nyquist Rate for more information). Also a Nano does not have a real DAC, so the audio is generated via a PWM signal, which turn the line on and off very fast, so you only see the waveform only, if you apply a low pass filter (like a speaker will do, because it cannot move that fast).
But directly sampling the audio signal is overly complex, only for making a VU meter visualization. These visualizations are way slower, than the actual audio signal. So you need to take the mean value over a specific time interval. Best you can reach this by building a low pass filter using a resistor and a capacitor. You can sample the output of that filter, which will only have lower frequencies. The sampling frequency then should be double of the cut of frequency of the filter at minimum.
Of course it is also possible to do all this in software, but for this you would have to change the library and I guess you don't want to do this.

The delay was a leftover from me troubleshooting the code. When I leave the delay out, I get similar results. I have code to take the sample, and produce a VU, I didn't include as I didn't think I was getting something that I could use from the raw audio pin.

Still the raw audio pin will only have a PWM signal. You should try the low pass filter and sample that filtered signal.

If you didn't think, that you would get something useful from the audio pin, why did you sample it?

Sorry I was replying from mobile and was trying to be brief. I have edited my question to include a graph more like I was expecting. If I received a waveform from the audio pin like pictured above, I would have then ran the code through my "VU" function. This "expected" graph was produced with a condenser microphone connected with the same code, sampling at 20Hz. This condenser circuit has a op-amp that drives the output. Perhaps the output of the PWM audio signal isn't enough to drive the ADC and produce the waveform I thought I would see? Thanks @chrisl for your help!

You didn't show a VU function, so I cannot know, if this function would help. So you get a more expected output, if you take the sound with a microphone and sample that? As I tried to explain, there is already a (mechanical) low pass filter incorporated, since the speakers membrane cannot move fast enough to follow the PWM signal. Instead it will take the mean. That is the whole point in doing sound via PWM. If you don't want to use a mecrophone to sample the real sound, but want to use the direct electrical signal, you need an electrical low pass filter, to filter out the PWM frequency

And surely, you mecrophone samples are closer to the real world, but also not a good representation of the real soundwave

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Convert String to IPAddress
How can i convert a String to IPAddress on arduino / esp ?
etc. "192.168.1.2"  -> IPAddress(192, 168, 1, 2)
Tried this
void setup() {

  Serial.begin(115200);

  IPAddress apip;

  const char *apipch;
  apipch = "192.168.4.1";

Serial.println(apip.fromString(apipch));

}

void loop() {
  // put your main code here, to run repeatedly:
}

But i just get an output "1"

There are two possibilities in the link, which one did you use? If it didnt work, you did something wrong, but I can't guess what you did do. Post your code, perferably the shortest possible bit - it does not have to be functional, just the the bit where you get your string (is it a String or a char[] ?) how you implemneted the convert code, and where you call the ip() function.

please do not say didn't work ... instead say this is what happened .... .... "didn't work" is almost meanigless

ip.fromString(s.c_str());

@Msquare  have added an example tried both codes but they gave me a result of 1

@jsotola your right sorry, i added code and my result

@Juraj this just gave me a result of 1

because you print the return value of fromString and not the IP address. Serial.println(apip);

The IPAddress class has a member function bool fromString(const char *address).
const char *apipch = "192.168.4.1";
IPAddress apip;

if (apip.fromString(apipch)) { // try to parse into the IPAddress
    Serial.println(apip); // print the parsed IPAddress
} else {
    Serial.println("UnParsable IP");
}

You could do this:
String myip="192.168.1.2"
IPAddress local_IP;
bool x= local_IP.fromString(myip);

IPAddress str2IP(String str) {

    IPAddress ret( getIpBlock(0,str),getIpBlock(1,str),getIpBlock(2,str),getIpBlock(3,str) );
    return ret;

}

int getIpBlock(int index, String str) {
    char separator = '.';
    int found = 0;
    int strIndex[] = {0, -1};
    int maxIndex = str.length()-1;

    for(int i=0; i<=maxIndex && found<=index; i++){
      if(str.charAt(i)==separator || i==maxIndex){
          found++;
          strIndex[0] = strIndex[1]+1;
          strIndex[1] = (i == maxIndex) ? i+1 : i;
      }
    }

    return found>index ? str.substring(strIndex[0], strIndex[1]).toInt() : 0;
}

Please check the function into IPAddress.cpp file of line 70 :
bool IPAddress::fromString(const char *address) {
// TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats
....
}

I think you need to drop the parentheses from the IPAdress ip() in your code, The code should be like below :
Void yourMethod (const char *addr, String ipStr){

IPAdreess ip;
bool i;

i = ip.fromString(ipStr);
    if (i) {
        for (int a = 0; a < 4; a++) {
            addr[a] = ip[a];
          ....
        }
    }
}

Hope this helps.


text:
Can't install to arduino mega 2560 using arduino-cli, but can using IDE
I have a MKS GEN L v1.0 3dprinter board that works fine uploading using the IDE. But I need to install to it using the arduino-cli.
For some reason, the command arduino-cli board list says that the board has an unknown FQBN. Which is fine, I guess. I guess I don't know how to compile & upload without the FQBN.
The options I need selected (which work in the IDE) are:

Board: Arduino/Genuino Mega or Mega 2560
Processor: ATmega2560
Programmer: AVRISP mkII

I don't understand why these options aren't clearly available in the arduino-cli.
I ran these commands: arduino-cli core install arduino:avr and arduino-cli core install arduino:megaavr
I ran  arduino-cli board list. It says /dev/ttyUSB0, serial, Serial Port (USB), "Unknown" for FQBN....
I run arduino-cli compile Marlin. It says "unknown FQBN".
So how do I install using the same parameters in the IDE?

did you install the AVR boards package in CLI? IDE has the AVR boards package bundled in the installation folder, but the CLI doesn't use it from there

I did run : arduino-cli core install arduino:avr and arduino-cli core install arduino:megaavr... Is there something else I should do?

and what CLI command do you run at what is the output exactly? (add it to the question)

Ok I added it...

I would guess, that the arduino-cli doesn't recognize your boards FQBN, since it is not a genuine Arduino board. My Arduino Nano clones (with the CH340 USB-Serial-chip) aren't recognized as Arduino Nanos either. For me that's the same with the Arduino IDE.
Though, since you already know what board you have, you can find the FQBN yourself by looking through the list in the output of
arduino-cli board listall

or if you want to narrow the list down a bit:
arduino-cli board listall avr

There you will find the line with the Megas FQBN:
Arduino Mega or Mega 2560        arduino:avr:mega

Then you need to know, which Serial interface/COM port your Arduino has. This is done analog to the Arduino IDE: Check the list of connected boards via
arduino-cli board list

If you cannot identify it directly from the list, you might want to disconnect and connect it again, to see, what entry in this list reappears again.
Then compile and upload can be done like this (be sure to input your own COM port/Serial interface, if it differs from this):
arduino-cli compile --fqbn arduino:avr:mega
arduino-cli upload --fqbn arduino:avr:mega --port /dev/ttyUSB0

while being in the sketch folder.

Thank you... I have been searching for an answer to this for years... It is not clear the "FQBN" would be the same as that sub menu in the IDE


text:
On compiling I get #endif without #if error. Here is the code. Please help!
#include <Arduino.h>
#endif
#include <ESP8266WiFi.h>
#define watersensor D2
const char* ssid = "pooja";
const char* password = "ranip2780@";
WiFiServer server(301);
IPAddress ip(192, 168, 43, 67);
IPAddress gateway(192, 168, 43, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns(192, 168, 43, 1);
void setup() {
  Serial.begin(115200);
  delay(10);

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.config(ip, dns, gateway, subnet);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  server.begin();
  Serial.println("Server started");

  Serial.print("Use this URL to connect: ");
  Serial.print("http://");
  Serial.print(WiFi.localIP());
  Serial.println("/");
}

void loop()
{
  // Check if a client has connected
  < WiFiClient client = server.available();
  if (!client) {
    return;
  }

  // Wait until the client sends some data
  Serial.println("new client");
  while (!client.available()) {
    //    delay(1);
    client.setNoDelay(1);
  }

  String request = client.readStringUntil('\r');
  Serial.println(request);
  client.flush();

  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html");
  client.println("");
  client.println("");
  client.println("");
  client.println("<meta http-equiv='refresh' content='20'>");
  client.println("<title>WATER OVERFLOW ALARM WITH ONLINE UPDATES</title>");
  client.println("");
  client.println("");
  client.println("

");
  client.println("
");
  client.println("
");
  client.println("WATER OVERFLOW ALARM WITH ONLINE UPDATES
");
  client.println("USING NODEMCU 1.0 BOARD");
  client.println("
	");
  client.println("
");

  if (digitalRead(watersensor) == LOW)
  {
    client.println("<button style='background-color:red;width:200px;height:100px'>FULL LEVEL ALERT</button>
");
  }
  else
  {
    client.println("<button style='background-color:gray;width:200px;height:100px'NOT FULL</button>
");
  }

  client.println("
	");
  client.println("
");
  client.println("

");
  client.println("");
  client.println("
");
  client.println("

");
  client.println("LEGENDS:  <button style='background-color:gray;width:100px;height:50px'><font color='white'NOT FULL</button>");
  client.println("WATER LEVEL IS BELOW SENSOR.
");
  client.println("
<button style='background-color:red;width:100px;height:50px'>FULL LEVEL ALERT</button> WATER LEVEL IS ALREADY FULL.");
  client.println("

");
  client.println("");
  client.println("");
  delay(1);
  Serial.println("Client disconnected");
  Serial.println("");
  delay(500);
}

remove the #endif

You probably could have found this out yourself by just reading what the error message says. Maybe this tutorial will help you get started with coding for the Arduino.

The Arduino IDE gives you a massive clue
Arduino: 1.8.12 (Windows 10), Board: "Arduino Uno"

sketchX:2:2: error: #endif without #if

 #endif

  ^~~~~

sketchX:3:10: fatal error: ESP8266WiFi.h: No such file or directory

 #include <ESP8266WiFi.h>

          ^~~~~~~~~~~~~~~

compilation terminated.

exit status 1
#endif without #if

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

That's pointing at lines #2 & #3 in the sketch as having the error. So we fix those and try again
//#endif

I'll also install the ESP8266 stuff since that's missing on my new laptop.
Arduino: 1.8.12 (Windows 10), Board: "Generic ESP8266 Module, 80 MHz, Flash, Legacy (new
can return nullptr), All SSL ciphers (most compatible), dtr (aka nodemcu), 26 MHz, 40MHz,
DOUT (compatible), 1MB (FS:64KB OTA:~470KB), 2, nonos-sdk 2.2.1+100 (190703), v2 Lower
Memory, Disabled, None, Only Sketch, 115200"

C:\Users\winuser\Arduino\sketchX\sketchX.ino: In function 'void loop()':

sketchX:42:3: error: expected primary-expression before '<' token

   < WiFiClient client = server.available();

   ^

sketchX:42:16: error: expected primary-expression before 'client'

   < WiFiClient client = server.available();

                ^

sketchX:42:16: error: expected ';' before 'client'

sketchX:43:8: error: 'client' was not declared in this scope

   if (!client) {

        ^

sketchX:49:11: error: 'client' was not declared in this scope

   while (!client.available()) {

           ^

sketchX:54:20: error: 'client' was not declared in this scope

   String request = client.readStringUntil('\r');

                    ^

sketchX:4:21: error: 'D2' was not declared in this scope

 #define watersensor D2

                     ^

C:\Users\winuser\Arduino\sketchX\sketchX.ino:79:19: note: in expansion of
macro 'watersensor'

   if (digitalRead(watersensor) == LOW)

                   ^

exit status 1
expected primary-expression before '<' token

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

So all in all it's simple to use the messages that the IDE gives you to find your error and correct them, working from top to bottom in your sketch. It's not something that needs to be posted on StackExchange until you've corrected the basics.


text:
Arduino not rebooting with watchdog enabled
I have a custom board that is switching an inductive load through a 10A@230V ac relay.
Due to a poor design, voltage spikes are causing the board to reboot from time to time (brown-out, watchdog and "unknown reason")
The problem here is that from time to time, the microcontroller freezes and no longer executes code (or at least, it seems so), even if the watchdog should be running.
I programmed the WDTON and BROWN-OUT fuses, so the watchdog should be always on.
Once the microcontroller is frozen, an external reset makes it work again.
My questions:
Is there any SOFTWARE fix to guarantee that the device never freezes. Am I using the watchdog incorrectly?
I read in the Atmega 328P datasheet about the 4 cycle restriction between the WDE writing and the prescaler bits writing (page 44), but It´s not clear to me if this restriction applies when WDON fuse is programmed.
Also, I couldn´t find what the "wdt_enable (WDTO_2S);" instruction is doing under the hood.
Is it possible that the watchdog oscillator stops due to a voltage spike?
This is my code (the part to illustrate the watchdog problem)
Hardware: Custom board
microcontroller: ATmega 328P
Brown-out fuse: programmed
WDTON fuse: programmed

#include <avr/wdt.h>

#define R0          3 // Relay output 16A @ 230Vac (10A @ 230Vac)
#define R1          4 // Relay output 10A @ 230Vac (10A @ 230Vac)
#define R2          5 // Relay output 10A @ 230Vac (10A @ 230Vac)

byte outputs;

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

void test() {

#define TEST_SWITCHING_INTERVAL  500

  static unsigned long previousMillisTest;
  static int count;

  unsigned long actualTemp = millis();
  if ((actualTemp - previousMillisTest) >= TEST_SWITCHING_INTERVAL) {
    bitWrite (outputs, 0, !bitRead (outputs, 0)); Serial.print ("R0 = ");    Serial.print (bitRead (outputs, 0));
    bitWrite (outputs, 1, !bitRead (outputs, 1)); Serial.print ("   R1 = "); Serial.print (bitRead (outputs, 1));
    bitWrite (outputs, 2, !bitRead (outputs, 2)); Serial.print ("   R2 = "); Serial.print (bitRead (outputs, 2));
    Serial.print ("   count: "); Serial.print (count++);
    Serial.print ("  millis: "); Serial.println (previousMillisTest);
    previousMillisTest = actualTemp;
  }
  digitalWrite (R0, bitRead (outputs, 0));
  digitalWrite (R1, bitRead (outputs, 1));
  digitalWrite (R2, bitRead (outputs, 2));
}

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

void setup() {

  uint8_t MCUSR_save;

  MCUSR_save = MCUSR;
  MCUSR = 0;
  wdt_enable (WDTO_2S);

  Serial.begin (9600);

  if      (MCUSR_save & 0x01)  Serial.println ("*********Restarting . Power-on Reset*********");
  else if (MCUSR_save & 0x02)  Serial.println ("*********Restarting . External Reset*********");
  else if (MCUSR_save & 0x04)  Serial.println ("*********Restarting . Brown-out Reset*********");
  else if (MCUSR_save & 0x08)  Serial.println ("*********Restarting . Watchdog Reset*********");
  else if (MCUSR_save & 0x10)  Serial.println ("*********Restarting . JTAG Reset*********");
  else                         Serial.println ("*********Restarting . Unknown reason*********");
  Serial.print ("MCUSR = 0x"); Serial.println (MCUSR_save, HEX);

  initPins();
  initDevice();

  if (DEBUG) showConfig();

  // prevents flooding the RS485 bus if the device is continuously restarting
  delay (100);

  sendFrame (RESTARTED, 0); // sends the "restarted" event through the RS485 port

}

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

void loop() {
  wdt_reset();
  test();
}

You can choose to either reset the processor or execute an interrupt routine. Example code:
#include <avr/wdt.h>

// watchdog intervals
// sleep bit patterns for WDTCSR
enum
{
  WDT_16_MS  =  0b000000,
  WDT_32_MS  =  0b000001,
  WDT_64_MS  =  0b000010,
  WDT_128_MS =  0b000011,
  WDT_256_MS =  0b000100,
  WDT_512_MS =  0b000101,
  WDT_1_SEC  =  0b000110,
  WDT_2_SEC  =  0b000111,
  WDT_4_SEC  =  0b100000,
  WDT_8_SEC  =  0b100001,
 };  // end of WDT intervals enum

void setup()
  {
  wdt_disable ();
  Serial.begin(115200);
  Serial.println ();
  Serial.println("After reset");
  watchdogSetup(WDT_4_SEC);
  }

volatile bool watchdogFired = false;

ISR(WDT_vect) // Watchdog timer interrupt.
  {
  watchdogFired = true;
  }

void watchdogSetup(byte interval)
  {
  cli(); // disable all interrupts

  // Enter Watchdog Configuration mode:
  WDTCSR = bit (WDCE) | bit (WDE);
  // Set Watchdog settings:
  //  WDTCSR = bit (WDIE) | interval;   // set WDIE, and requested delay - for an INTERRUPT
  WDTCSR = bit (WDE) | interval;    // set WDIE, and requested delay - for a RESET
  wdt_reset(); // reset the WDT timer
  sei();  // enable interrupts again
  }

void loop()
  {

  if (watchdogFired)
    {
    watchdogFired = false;
    Serial.println ("Watchdog fired.");
    }

  // wdt_reset();  // if you want to reset the watchdog

  } // end of loop

This example resets the processor, however if you uncomment the line WDTCSR = bit (WDIE) | interval; and comment the one below WDTCSR = bit (WDE) | interval; then it interrupts instead. You can see that in the example output.
If you want an interrupt then you have to supply an interrupt routine (ISR).

Responding to comments:

But there´s little documentation about how to adequately recover from a reset when the fuse is programmed.

The processor resets, which is what you want, right? You don't need to "recover" from a reset. It's like saying how do you recover from powering it on.

Do I still need to re-enable the watchdog, even if it should be enabled by the fuse?.

I doubt it. In my code the watchdog keeps firing, even after you get the message the first time (the interrupt one).
However you might want to change the interval to the one you want. And you might want to reset the watchdog (wdt_reset ()) if things are going OK.

Also, with the WDTON fuse enabled, the ISR mode is not valid (only the reset mode).

Well, there is not necessarily an ISR for the ISR mode (yet, if ever). The datasheet specifically says that you get the reset mode and not the ISR mode.
It is unclear from the datasheet what the time interval is, with the WDTON fuse programmed.

Thank you for your answer. I try to ensure that the watchdog is ALWAYS running to prevent freezing. In your example, the watchdog is disabled in the setup function. This is the reason why I chose to program the WDTON fuse. But there´s little documentation about how to adequately recover from a reset when the fuse is programmed. Do I still need to re-enable the watchdog, even if it should be enabled by the fuse?. Also, with the WDTON fuse enabled, the ISR mode is not valid (only the reset mode).

See my amended answer which answers your questions.

"The processor resets, which is what you want, right?" -> The point is that the processor DOES NOT reset sometimes. It gets freezed even with the WDTON programmed. 99,9 % of the time it works fine, but still I have some freezing cases. My previous version was very much alike as your code but my guess was:  voltage spike -> uC resets -> setup function executes -> disable watchdog -> program counter jumps elsewhere in the code because of EMI -> program freezed because watchdog is disabled. I know maybe this is too much guessing, but I changed to WDTON and it improved

Now I am thinking that maybe one voltage spike stops the watchdog oscillator and also the uC oscillator. Do you know if this would be possible?. The fact is that only with a external restart the uC comes to live again

A voltage spike might conceivably set the thing into high-voltage programming mode. If you can reach the thing enough to press Reset, can't you wire in a spike protection? Like, a zener diode which redirects high voltages to earth.

I already tried placing a zener diode between Vcc (at the ISP connector) and GND. No luck with that. The spikes are already there (I see them with the scope) and also the reboots. I also tried with snubbers, emi filters, optocoupled relays, etc. The only thing that really worked was an SSR. But still, I would like to avoid installing them. But it seems my only option, as It looks impossible to solve this with only a software change. Thank you for your help, anyhow.


text:
Why can't my four batteries (6V) can't power this circuit while usb 5v from arduino can?
I have this circuit

And I want it to power all the led rgb (100 in total), I want to make a independent portable circuit, so I don't have to use the usb power. The thing is when I use this circuit it only power to 44 led.
WHile when I use the usb 5V it can full lights all led .

This is my code
#include <Adafruit_NeoPixel.h>

#define NUM_LEDS 100
#define LED_PIN 2
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_RGB+NEO_KHZ800);
void setup()
{

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

}

void loop()
{

  for (int i = 0; i < NUM_LEDS; i = i+1)
  {
    strip.setPixelColor(i, strip.Color(255, 240, 255));

    strip.show();
    delay(1000);
  }

}

What may I be missing?

USB port capable of providing 5V with up to 1A current. Your 4 AA-battery obviously not capable to deliver the current it required for 100 LED. 2) Programmable LED is not just LED, it has chip inside and it supposed to operate at 5V, you drive it with 6V, even it not "work", but it could damage the chip in the long run. I' suggest you read Adafruit Neopixel Uber Guide which explain the power requirements and choice of power source.

As shown, your four batteries are delivering 1.6v to the MCU, not 6v

The current available from a computer's USB port is 500 mA; some ports can supply more if the device negotiates for it.
You show AA cells in your diagram. Even assuming they're Alkaline cells, batteries differ in their capacity vs. discharge rates, and presumably in their internal resistances. Most any power-supply's voltage will sag as you draw more current from it. The likely answer is that as you add LED's the battery voltage falls below either what is needed to light the LEDs; or 2) the dropout voltage of Arduino's voltage regulator, which shuts down the Arduino (assuming you're connected to 'V_in', not '5v', which neither diagram shows).  Less-than-fresh batteries will exhibit this voltage drop sooner and to a greater degree.
This study of AA battery capacity vs. current draw might help understand the apparent loss of capacity at greater currents. But even without that phenomenon, the battery voltage will fall as (I * R_battery); capacity loss just makes it worse.

Hello JRobert thanks for your observation. Besides the explanation, is there anything I can do to solve this?

add more batteries in parallel (not series) or start with a higher voltage and use a properly rated and efficent dc-dc converter to lower it

It would probably be worth asking another question about how to estimate power draw from the lights and how to design a proper battery pack to power it...

A quick and dirty solution would be to make another (or 2 more, if needed) 4-cells-in-series battery packs, and connect its/their +V and Gnd to the +V and Gnd (respectively) of the present pack. All of your batteries should be fresh. Run a test to see how many LEDs it will sustain, and whether it will sustain them for as long as you need it to. The better solution is @user10489's second suggestion - to calculate your current needs and an energy budget, and design a power-pack to meet it.

Exactly as JRobert says...  note that if the batteries are not "fresh" they will mutually charge each other, which could be bad for non-rechargable batteries.  (In other words, they don't have to be fresh or balanced if they are rechargeable.)


text:
Random "Compilation error: Error: 13 INTERNAL: exit status 1". No clue how to resolve or even what causes this error
I am a beginner with Arduino. I have a program that is intentionally simple.
The code refuses to compile, spitting out the error Compilation error: Error: 13 INTERNAL: exit status 1. I have gotten this type of error multiple times, and I have no idea what causes it, nor how to fix it.
My code is below, by the way.
void setup() {
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);

  analogWrite(10, 10);
}

void loop() {
  digitalWrite(9, HIGH);
  digitalWrite(11, LOW);
  delay(250)
  digitalWrite(9, LOW);
  digitalWrite(11, HIGH);
}

comment out all lines ... then uncomment one at a time ... compile each time

might it be your board config? ide does some annoying stuff sometimes regarding where it caches crud, making getting a truly clean install more annoying than it should be.

If you read all the error message you'll see it complaining about a missing semicolon...

The problem with that error message is that you are only reading the very last line. That line says "Oops, it didn't compile". The actual error message occurs before that. You need to read the entire message to know what is going on.
With your code, for example, you get the following output:
blah.ino: In function 'void loop()':
blah.ino:13:3: error: expected ';' before 'digitalWrite'
   digitalWrite(9, LOW);

That is your actual error. It's telling you that there's a semi-colon missing before the digitalWrite on line 13.  There's nothing before the digitalWrite on line 13, but, if you look closely, you can see that line 12 has the semi-colon missing from the end of it.:
  delay(250)    <---- missing ;
  digitalWrite(9, LOW);

Thus it proves that it is always important to both read and (if you don't understand it) post the entire error message not just the last line.

Thanks, that works.


text:
i need help on how to use busy pin in df player to arduino
i need help on how to use busy pin in df player to arduino.... while playing one sound or df player is busy, i don't want to trigger df player by ultrasound sensors to play another song. here is my code without busy pin use in df player
#include "Arduino.h"
#include "SoftwareSerial.h"

#include "DFRobotDFPlayerMini.h"

const byte SENSOR_COUNT = 5;
byte triggerPins[SENSOR_COUNT] = {2,4,6,8,10};
byte echoPins[SENSOR_COUNT]    = {3,5,7,9,11};

SoftwareSerial mySoftwareSerial(12, 13); // RX, TX

DFRobotDFPlayerMini myDFPlayer;

void printDetail(uint8_t type, int value);

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

  for( byte i=0; i<SENSOR_COUNT; i++ )
  {
    pinMode(triggerPins[i], OUTPUT);
    pinMode(echoPins[i], INPUT);
  }

  Serial.println();
  Serial.println(F("DFRobot DFPlayer Mini Demo"));
  Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));

  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    Serial.println(F("Unable to begin:"));
    Serial.println(F("1.Please recheck the connection!"));
    Serial.println(F("2.Please insert the SD card!"));
    while(true);
  }
  Serial.println(F("DFPlayer Mini online."));

  myDFPlayer.volume(10);  //Set volume value. From 0 to 30

}

int currentSound = -1;
void loop()
{

  for( byte i=0; i<SENSOR_COUNT; i++ ) // loop through all distance sensors
  {
    if( detectPresence(i) ) // check if there is an object near it
    {
      if(currentSound!=i) // check that it's a different sensor than the one that was last triggered
      {
        Serial.print("play song number ");
        Serial.println(i);
        myDFPlayer.play(i+1); // play song nr `i+1`
      }
      currentSound = i;
    }
  }

  if (myDFPlayer.available()) {
    printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
  }

}

// detectPresence will return TRUE if there is an object close to it.
bool detectPresence(byte sensorNr)
{
  if( sensorNr>=SENSOR_COUNT )
    return false;
  long duration, distance;
  //digitalWrite(triggerPins[sensorNr], LOW);  // Added this line
  //delayMicroseconds(10); // Added this line
  digitalWrite(triggerPins[sensorNr], HIGH);
  delayMicroseconds(15); // Added this line
  digitalWrite(triggerPins[sensorNr], LOW);
  duration = pulseIn(echoPins[sensorNr], HIGH);
  distance = duration/58;

  return distance<30;// choose your own value here, from which distance it should trigger a sound
}

void printDetail(uint8_t type, int value){

  switch (type) {
    case TimeOut:
      Serial.println(F("Time Out!"));
      break;
    case WrongStack:
      Serial.println(F("Stack Wrong!"));
      break;
    case DFPlayerCardInserted:
      Serial.println(F("Card Inserted!"));
      break;
    case DFPlayerCardRemoved:
      Serial.println(F("Card Removed!"));
      break;
    case DFPlayerCardOnline:
      Serial.println(F("Card Online!"));
      break;
    case DFPlayerPlayFinished:
      Serial.print(F("Number:"));
      Serial.print(value);
      Serial.println(F(" Play Finished!"));
      break;
    case DFPlayerError:
      Serial.print(F("DFPlayerError:"));
      switch (value) {
        case Busy:
          Serial.println(F("Card not found"));
          break;
        case Sleeping:
          Serial.println(F("Sleeping"));
          break;
        case SerialWrongStack:
          Serial.println(F("Get Wrong Stack"));
          break;
        case CheckSumNotMatch:
          Serial.println(F("Check Sum Not Match"));
          break;
        case FileIndexOut:
          Serial.println(F("File Index Out of Bound"));
          break;
        case FileMismatch:
          Serial.println(F("Cannot Find File"));
          break;
        case Advertise:
          Serial.println(F("In Advertise"));
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
}

what help do you need? ... what is your specific question?

The busy pin is just a pin, that gets driven LOW, when a song is playing, and HIGH when nothing is playing. So connect it to a free digital IO pin on your Arduino and set that pin to input with:
pinMode(busy_pin, INPUT);

(Note: You yourself need to define busy_pin, since I don't know where you will connect it). Then just read this pin in the if statement together with detectPresence(i):
if(!digitalRead(busy_pin) && detectPresence(i))

The ! is to make the expression true, when digitalRead(busy_pin) returns 0 (LOW). This way the code will not even check for presence, when there is currently a song playing.


text:
How can I force an I2C module (for 1602 and 2004) to work with a 1601 LCD at my Arduino Micro
I'm new to Arduino and want to build a Button Box. When I buyed the parts I didn't watched out for the specifications of the I2C module. When I tried to print sth on the LCD nothing happened (in retro perspective it's logical). I wouldn't like to have to buy a new LCD.
How can I make the LCD work with the I2c module?
LCD - http://cdn-reichelt.de/documents/datenblatt/A500/DEM16101SYH.pdf
I2C-module - http://mantech.co.za/datasheets/products/lcd2004-i2c.pdf
it's wired correctly (VCC to 5V, GND to GND, SDA to SDA and SCL to SCL)
The Code I used is the "Hello World" Example thats included in the LiquidCrystal_I2C library, but with a few changes:
//YWROBOT
//Compatible with the Arduino IDE 1.0
//Library version:1.1
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,1);  //instead of LiquidCrystal_I2C lcd(0x27,20,4);

void setup()
{
  lcd.init();                      // initialize the lcd
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  lcd.setCursor(3,0);
  lcd.print("Hello, world!");
  lcd.setCursor(2,0); //isntead of lcd.setCursor(2,1);
  lcd.print("Ywrobot Arduino!");
   lcd.setCursor(0,0); //instead of lcd.setCursor(0,2);
  lcd.print("Arduino LCM IIC 2004");
   lcd.setCursor(2,0); //instead of lcd.setCursor(2,3);
  lcd.print("Power By Ec-yuan!");
}

void loop()
{
}

Hi @Chritzeltopf, welcome to Stack Overflow. If you edit your question to include the code you tried, what kind of LCD you’re connecting and how you wired it up, someone may be able to help you. Otherwise we know even less about what you’re doing than you do.

Sorry :(, I thought the given informations would be enough for the question. Added the infos :)

Yep, it's one line. That's the problem

what connections did you make? ... the I2C module provides the 8 data bits to the LCD module ... the E, R/S and RE signals to the LCD must be generated by the arduino

@VE7JRO it happens nothing

@jsotola what exactly do you want to know? I don't really get it?

How about this library just to test if you can get it to work with a simple sketch? https://github.com/AlexMartin17/Arduino-LCD-Library-16x1

Welcome! You mentioned how you you connected it but a schematic is always better. Where did you put your pull up resistors and did the I2C scan return the correct port?

@Gil do I need Pullup resistors on the SDA and SCL pins to use the I2C module? The I2C scan sketch that I used didn't worked (no address was printed in the Serial) so I guess the I2C module didn't communicated with the LCD?

I think we just found your problem. This happens a lot, I see it several times a week. Keep up the good work.

Welcome Chritzelopf! Yes pull up resistors are required by the I2C definition. Your link on the driver shows they are not included and no schematic to  indicate otherwise. The I2C bus is driven by open collector/drain semiconductor devices. This configuration will pull the line low but not source any current into it other then possibly some leakage. When the outputs of the I2C device are off the bus is pulled high or placed in the recessive state by the pull up resistors. When one or more of the devices turn on the bus is now in the dominate state or low. This configuration allows anything to turn on or off without damaging other devices on the bus. I like the pull up(s) to be in the 4.7K for 5V and about 3.3K in the 3V3v.
Some modules come with pull ups that are permanently connected, others are selectable with jumpers etc. This is NOT the A0 - A? jumpers which are address select lines. I always check the modules to determine if there are pull ups enabled and adjust my other resistances to get an appropriate value, sometimes even removing them.

So should I try it again with "pinMode(2, INPUT_PULLUP)"; pinMode(3, INPUT_PULLUP) ;

The library I use does not allow that as it programs them the way it wants. It does not report it just does. The safest, most likely to work is to use the recommended external resistors. Once you get it working then try your pull up idea. Remember they are somewhere in the 30 to 50K range.


text:
Use ESP8266 as WiFi client connected to Arduino Pro Mini
So i'm trying to use the PubSubClient Library on my arduino mini pro, but I'm connecting to the internet via wifi using an ESP8266.
Using a mini means I have to use software serial to connect to the ESP, but I've ran into a problem. I can't find anywhere such as ESPWiFiClient to use with the examples from the PubSubClient library where they use EthernetClient.
Is there any available libraries that can emulate EthernetClient with an ESP module over software serial?

Is there a specific reason for using the pubsubclient library? There are other mqtt libraries out there which do work with the esp8266... I do however completely agree with the answer below that ditching your Arduino and uploading the Arduino code to your ESP8266 is a much better approach.

Ditch the Pro Mini.  Upload your Arduino code to the ESP directly. There's a GitHub repo with the details. ESP for Arduino IDE has a ton of libraries. I'm sure you'll find it there.
But if you're bent on using the Pro Mini,  you'll have to use AT commands over serial to control it or flash a custom firmware into the ESP using Lua or something. And Pro Mini can use its hardware serial just like a Uno does.


text:
Car Control via OBD-II port
I was wondering if it is possible to send commands through the OBD-II on my car via an Arduino Uno Rev 3 with a CAN-BUS Shield from SEEDStudio. I am just going for basic functions i.e. lock control, window control, lights nothing really outside of those basic functions. My shield is currently in the mail and I was hoping anyone could shed light as to if this is even possible. My car model is a 2004 Mini Cooper S. Thanks.

The question, as-is, is off topic. Yes it is possible to use an Arduino to communicate on a CAN bus via some kind of shield. However, the root of your question is whether or not it can be done for your specific car, which is a question better served by some form of car enthusiast site, perhaps one dedicated to Mini Coopers.

Did you try google? https://www.google.com/search?client=ubuntu&channel=fs&q=Arduino+CAN+Car+Control+via+OBD-II. Looks like a "yes".

Technically, yes: If you hook up this shield to the car buses through OBD-II, and know which messages to send (e.g., ones that the car will accept and work with), then it will work.
The problem is: There are some "official" messages, basically emission related stuff, that are mandatory on every cars. There are lists of these out there.
Unfortunately, most messages are OEM dependent (including those that may control the basic features you mentioned), and they don't want you to mess around this.
Said differently: The semantic of CAN frames/messages varies from one car to another.
Being able to send receive CAN frames (which this shield is) is like being able to emit sounds & hear them: Mandatory, if you want to discuss with someone, but useless/not enough if you do not speak the same language.


text:
CHSV arguments with FastLED
I'm trying to use CHSV with FastLED library and as I understand hue, value and saturation in the CHSV type are of type uint8_t, or 1 byte.
My problem is with using variables:

CHSV led = (hue, sat, val);

with:
uint8_t hue;
uint8_t sat;
uint8_t val;

Is there a difference between uint8_t and byte data types? what is it and how does one use it with the context of arduino and FastLED library?
Am I getting the syntax wrong?
I get an error - convertion from 'uint8_t' to non scalar type 'CHSV' requasted.
I thought the library does that on its own, do I need to add more code? If yes, what code?

Thank you

Is there a difference between uint8_t and byte data types?

There is no difference in the datatype. byte is defined in Arduino.h:
typedef uint8_t byte;

So, uint8_t and byte are exactly the same. The uintX_t types and their siblings are specifically meant for having the same size on every platform (in difference to for example double which is only 16 bits on Arduino Uno, but can be 32 bits on bigger chips). But byte will also be 8 bits on every platform, so there is really no difference.

Am I getting the syntax wrong? I get an error - convertion from 'uint8_t' to non scalar type 'CHSV' requasted. I thought the library does that on its own, do I need to add more code? If yes, what code?

You get the error, because you use the wrong syntax here. A CHSV color is not just 3 byte values, it is a class with member variables and methods. So you cannot simply assign 3 byte values directly to the object. You need to actually create the object, using the values as parameters for the constructor:
CHSV led = CHSV( hue, sat, val);

This creates a CHSV object, executes it's constructor, which uses the values from the parameters to set the internal values. That is the context, how this is used in the FastLED library. You can also find such lines in the examples of the library (I found such use in line 15 of the example ColorPalette, but there might be more). Also this is the same principle, as with the other color classes, like CRGB.


text:
Arduino IDE: How to get PROGMEM const length?
I have defined a byte array as a constant in the Atmel's flash memory:
const uint8_t eye [] PROGMEM = {
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
};

How can I (repeatedly) read the length of this constant in the program? All the available functions in avr/pgmspace.h do not deliver the proper length, no matter how I use them. I tried strlen(eye), strlen_P(eye), strLen_PF(eye) and also sizeof(eye). I'm new to C, so I'm not sure about the whole pointer stuff.

you already know the length ... it is 16 bytes

@jsotola Indeed, but I want to read the array length in a function that gets an array as parameter.

sizeof(), when provided with a pointer to a const (or a pointer to anything else for that matter), which is what you have when you pass it to a function, gives you the size of that pointer. On an 8-bit Arduino that will always be 2.  strlen() only works on strings - null-terminated arrays, which that isn't.

Size 2 is exactly what I got in the function. Isn't there a way to get the size of an array when you just have the pointer address to the array?

No. You can only determine such things at compile time (sizeof is an operator, not a function). Setting a const or creating a #define macro containing the size calculated at compile time (as in C_Elegans' answer) is the way to do it.

Probably the best way would be to define below it
const int eye_len = sizeof(eye)/sizeof(eye[0]);

If the linker does link time optimization, or if you only use it within the same file (and declare it static), it shouldn’t cost any memory, otherwise it will take up two bytes of ram.

That works, although I don't know how. Guess I have to read more about C.

Sizeof(array) gives the size of the entire array in bytes, and sizeof(array[0]) gives the size in bytes of one element in the array. Divide the first by the second and you get the number of items in your array. In this case you could do without the second sizeof, but it makes it still work even if you change the data type in the array.

@BeB00 could be that he used sizeof(eye) in another file, and it gave him the size of a pointer

That totally sounds logic. I confused a lot of things by using length functions for strings on a byte array (which counted on because of missing null termination) and receiving the pointer length instead of the array length. That's what you get when making yourself too comfortable in high-level languages... :)

Update: I found another solution for my small arrays and put the size in the first byte of the array, in the example I'd read eye[0] and iterate over the rest. This way the arrays keep their size info with them and I don't have to rely on external variables holding the value :)

Update 2: I combined that with the most simple compression algorithm that holds the number in byte n (being 1...x) and the value in byte n+1, so I get
const uint8_t eye [] PROGMEM = {
0x03,0x10,0xff
};


text:
Why is my keypad requiring a double-click only on the first row to register?
I have a keypad that is connected to my Arduino and each time a key is pressed, the number should be outputted to an LCD screen. The issue is that after the screen is cleared, and a new ID is being entered, any number on the first row will not trigger a keypress event but only on its first click. If you press it twice, it works completely fine. I am using the Keypad library and here is my code. Thanks for any help!

#include <ESP8266WiFi.h>
#include <Keypad.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

#define I2C_ADDR    0x3F // <<----- Add your address here.  Find it from I2C Scanner
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7

const char* ssid     = "**";
const char* password = "**";

const char* host = "**";
const char* getSystem = "**";
const char* apiKey = "**";
const char* systemIdentifier = "**";

const byte n_rows = 4;
const byte n_cols = 3;

char keys[n_rows][n_cols] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

byte rowPins[n_rows] = {D2, D3, D4, D5};
byte colPins[n_cols] = {D6, D7, D8};

int n = 1;
String idNumber;

boolean checkingIn = false;

LiquidCrystal_I2C  lcd(I2C_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);
Keypad myKeypad = Keypad( makeKeymap(keys), rowPins, colPins, n_rows, n_cols);

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

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  lcd.begin (16, 2);

  // Switch on the backlight
  lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
  lcd.setBacklight(HIGH);
  lcd.home ();

  lcd.print("Connecting");

  while (WiFi.status() != WL_CONNECTED) {
    lcd.print(".");
    delay(500);
  }

  setLCD("Please Enter ID#", 0);
  setLCD("                ", 1);

  delay(500);
}

void loop() {
  if (!checkingIn) {
    char myKey = myKeypad.getKey();
    Serial.print(myKey);
    if (myKey != NULL && (String)myKey != "*" && (String)myKey != "#") {
      Serial.print("Key pressed: ");
      Serial.println(myKey);
      idNumber += (String)myKey;
      setLCD(idNumber, 1);
    } else if ((String)myKey == "*" && idNumber.length() > 0) {
      idNumber = idNumber.substring(0, idNumber.length() - 1);
      setLCD("                ", 1);
      setLCD(idNumber, 1);
    } else if ((String)myKey == "#") {
      setLCD("                ", 0);
      setLCD("                ", 1);
      setLCD(" Checking in... ", 0);
      checkIn();
    }
  }
}

void setLCD(String text, int line) {
  lcd.setBacklight(HIGH);
  lcd.setCursor(0, line);
  lcd.print(text);
}

void checkIn() {
  checkingIn = true;
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    setLCD("                ", 1);
    setLCD("    Failed!     ", 0);
    return;
  }

  // We now create a URI for the request
  String url = "/assets/api.php?SYSTEM=";
  url += getSystem;
  url += "&API_KEY=";
  url += apiKey;
  url += "&SYSTEM_IDENTIFIER=";
  url += systemIdentifier;
  url += "&ID=";
  url += idNumber;

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 1000) {
      setLCD("                ", 1);
      setLCD("    Failed!     ", 0);
      client.stop();
      return;
    }
  }

  // Read all the lines of the reply from server and print them to //Serial
  while (client.available()) {
    String line = client.readStringUntil('\r');
    if (line.indexOf("[response|failed]") > -1) {
      setLCD("Invalid Login...", 0);
      setLCD("                ", 1);
    } else if (line.indexOf("*") > -1) {
      setLCD("Welcome:        ", 0);
      setLCD("                ", 1);
      setLCD(line, 1);
    }
    //Serial.println(line);
  }
  idNumber = "";
  delay(750);
  checkingIn = false;
  setLCD("Please Enter ID#", 0);
  setLCD("                ", 1);
}

Why are you using D4, D5 and D6 for both the lcd and the keypad? That won't work, surely?

Which Arduino is it?

@NickGammon It's IC2, completely different protocol so yes, that works. Also, Wemos D1 WiFi

So just to be clear, D4 and D4_pin are completely different pins? That's kind-of confusing isn't it?

Yes, and because this is not production code, it's not that big of a deal at one point it will be changed but right now it is the way that it is and I understand it. Don't worry about that part. If you don't have any clues to what the issue is, I don't think it is necessary for you to continue commenting.

I think a minimal, complete, verifiable example would be useful here. It'll be easier for people to understand so you'll attract more help, and very likely you'll figure it out yourself in the process of creating it.

@NickGammon - If the LCD is using I2C then I didn't think it used the other pins designations?

You have three major things here: LCD, keypad, WiFi. Possibly they are interacting with each other (for example, sharing the same pin by accident). If that was the case displaying something on the LCD might change how the keypad is configured. If you think the problem is simply the keypad, make up a small example that tests that theory out. Then add in the LCD stuff. Finally add in the WiFi stuff.

if (myKey != NULL && (String)myKey != "*" && (String)myKey != "#") - this is using the String class quite unnecessarily here. That does dynamic memory allocation and you may eventually get heap fragmentation. Why not: if (myKey != 0 && myKey != '*' && myKey != '#') ?


text:
POST request on Arduino MKR1400 GSM not working
Im trying to send a POST request from the Arduino MKR1400 GSM board to a server with a database.
I've tested the server using Postman (https://www.getpostman.com/) and it handles the POST request correctly, the json data gets uploaded to database fine.
The problem is that the same POST request from the Arduino MKR GSM 1400 does nothing. I've tried using client.print and I get the same result.
I'm not sure what I'm doing wrong or how to debug this issue, any ideas?
Arduino code:
#include <MKRGSM.h>
#include "Credentials.h"

// Definiciones para el GPRS
const char PINNUMBER[]     = SECRET_PINNUMBER;
const char GPRS_APN[]      = SECRET_GPRS_APN;
const char GPRS_LOGIN[]    = SECRET_GPRS_LOGIN;
const char GPRS_PASSWORD[] = SECRET_GPRS_PASSWORD;

GSMClient client;
GPRS gprs;
GSM gsmAccess;
GSMScanner scanner;

char ip[4] = {xxx,xxx,xxx,xxx};
char ipstring[14];
char path[] = "/atcapp.php";
int port = 80; // port 80 is the default for HTTP

char respName[30] = "Arduino MKR GSM 1400";
char toolName[30] = "Herramienta martillo";
char location[30] = "Mave Aeronautica S.L.";
char tlState[4] = "OUT";
unsigned long int user_id = 4294967295;
unsigned long int tool_id = 1234567899;
unsigned long int tmeStmp = 1532684104;
char notes[100] = "";

char postData[200];
char packetData[500];

void setup() {

  Serial.begin(9600);
  while(!Serial);
  sprintf(ipstring,"%d.%d.%d.%d",ip[0],ip[1],ip[2],ip[3]);
  post(respName,user_id,location,toolName,tool_id,tlState,tmeStmp,notes);

}

char post(char* resp,unsigned long int userid,char* location, char* toolName,unsigned long int toolid,char* toolState,unsigned long int timeStamp,char* notes)
{
  Serial.println("Connecting to GPRS Network...");
  boolean connected = false;

  while (!connected) {
    if ((gsmAccess.begin(PINNUMBER) == GSM_READY) &&
        (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
      connected = true;
    } else {
      Serial.println("GPRS connection failed");
      delay(1000);
      return -1;
    }
  }

  if (client.connect(ip, port)) {
    sprintf(packetData,"POST %s HTTP/1.1\nHost: %s\nUser-Agent: Arduino/1.0\nConnection: close\nContent-Length: %d\nContent-Type: application/json\nCache-Control: no-cache\n\n{\n\"responsable\":\"%s\",\n\"user_id\":%lu,\n\"loc\":\"%s\",\n\"tool\":\"%s\",\n\"tool_id\":%lu,\n\"tool_state\":\"%s\",\n\"timestamp\":%lu,\n\"note\":\"%s\"\n}\n",path,ipstring,sizeof(postData),resp,userid,location,toolName,toolid,toolState,timeStamp,notes);
    client.beginWrite();
    for(int i=0;i<sizeof(packetData);i++){
        Serial.write(packetData[i]);
        client.write(packetData[i]);
    }
    client.endWrite();

    while(client.connected()){
      Serial.println("Client still connected.");
      while(client.available()){
        Serial.println("Client still available.");
        char c = client.read();
        Serial.print(c);
      }
    }

    Serial.println("disconnecting.");
    client.stop();

    Serial.println();
    Serial.println("Done.");
    return 1;
  }else{
    Serial.println("Cannot connect to server.");
    return 0;
  }

}

void loop() {}

Serial port output:

It's my first time ever asking a question here, any contructive criticism is more than valuable to me. Thank you in advance,

The problem most likely stems from your Content-Length header.  You are using sizeof(postData) as the length of your content - however postData is a 200 byte array which is not used for anything. sizeof() will always return 200 for that regardless of what the rest of your program is doing.
Content-Length must be equal to the number of bytes after the second of the two \n separating the header from the body.  The best way to calculate that is up add up the length of all the strings that get inserted into the body formatting (using strlen() not sizeof()), and then add to that a constant value which is equal to the number of static characters (including \n) in the body (I make that 108 possibly?).
int dataLen = 108;
dataLen += strlen(resp);
dataLen += strlen(userid);
dataLen += strlen(location);
dataLen += strlen(toolName);
dataLen += strlen(toolid);
dataLen += strlen(toolState);
dataLen += strlen(timeStamp);
dataLen += strlen(notes);

Alternatively you pre-format the body into a separate string and use strlen() on that to get the length before starting to send data.  Of course, you don't need to store all the header in the string, since you can just send that line-by-line...
sprintf(packetData,"{\n\"responsable\":\"%s\",\n\"user_id\":%lu,\n\"loc\":\"%s\",\n\"tool\":\"%s\",\n\"tool_id\":%lu,\n\"tool_state\":\"%s\",\n\"timestamp\":%lu,\n\"note\":\"%s\"\n}\n",resp,userid,location,toolName,toolid,toolState,timeStamp,notes);
client.beginWrite();
client.print(F("POST "));
client.print(path);
client.println(F(" HTTP/1.1"));

client.print(F("Host: "));
client.println(ipstring);

client.println(F("User-Agent: Arduino/1.0"));
client.println(F("Connection: close"));
client.print(F("Content-Length: "));
client.println(strlen(packetData));
client.println(F("Content-Type: application/json"));
client.println(F("Cache-Control: no-cache"));
client.println();

client.print(packetData);

client.endWrite();

Note the use of F() around your static text to save copious amounts of RAM on AVR-based boards. Not really necessary on an ARM-based board, but a good thing to get into the habit of to keep things portable.
If you want to debug what is being sent I would suggest making a "debug" wrapper class that comprises both client and Serial:
class TwinPrint : public Print {
    private:
        Print *_ch1;
        Print *_ch2;

    public:
        TwinPrint(Print &ch1, Print &ch2) : _ch1(&ch1), _ch2(&ch2) {}
        size_t write(uint8_t c) {
            _ch1->write(c);
            _ch2->write(c);
            return 1;
        }
};

You can then construct a new object:
TwinPrint debug(client, Serial);

and do your writing to that and it will come out on both client and Serial at once:
debug.print(F("POST "));
debug.print(path);
debug.println(F(" HTTP/1.1"));

debug.print(F("Host: "));
debug.println(ipstring);

debug.println(F("User-Agent: Arduino/1.0"));
debug.println(F("Connection: close"));
debug.print(F("Content-Length: "));
debug.println(strlen(packetData));
debug.println(F("Content-Type: application/json"));
debug.println(F("Cache-Control: no-cache"));
debug.println();

debug.print(packetData);

I used strlen() and it worked! The debug class is a great idea! So the F() function "grabs" the strings from flash instead of the SRAM? Thank you soo much for answering so soon!

F() is a macro that forces the strings to stay in flash instead of being copied to SRAM (on Harvard architecture systems, anyway). It then causes a different variant of the print function to be called which reads the data directly from flash.


text:
Testing tri-state pin - erroneous results with internal pullup
I'm using an MPC73831 - a LiPo charging IC - in my Arduino project. It has a status pin to allow interface to a microcontroller, which uses a tri-state operation to convey three possible states of charging. I don't have the IC and battery yet, but I wanted to write a quick program to test a generic tri-state pin for HI, LO, and HiZ while I'm waiting for it to arrive.
The algorithm I wrote is very simple:
Set pinTest to input, no pullup.
Is pinTest high?
    Yes - pinTriState is HIGH, done.
Set pinTest to input with pullup.
Is pinTest high?
    Yes - pinTriState is HiZ, internal pullup causes high reading.
    No - pinTriState is LOW, 'cancelling out' internal pullup.

However, I'm not getting the expected results when using the internal pullup resistor - my board is showing correct analysis for HI and LO, but HiZ returns a mixture of HiZ and HIGH. I have tried this on an Uno, a Pro-Micro (32u4) and Uno->Micro and Micro->Uno. All give the same spurious results. I am baffled, therefore some advice would be appreciated. The full code is as below. I have left in code which randomises the time pinTriState stays at in a given state to keep pinTest guessing, but it's ultimately only an elaborate way of cycling through the three states.
#define pinTest 2
#define pinTriState 3

int state = 0;
char stateCh = '?';

int sect1;
int sect2;
int sectMax;

void setup()
{
    Serial.begin(9600);
    randomSeed(analogRead(A0));
    sect1 = random(1, 20);
    sect2 = random(sect1 + 1, random(sect1 + 2, sect1 + 20));
    sectMax = random(sect2 + 1, random(sect2 + 2, sect2 + 20));
}

void loop()
{
    // PART (1) Code to toggle three states of a tri-state pin
    if (state == 0)
    {
        pinMode(pinTriState, OUTPUT);
        digitalWrite(pinTriState, HIGH);
        stateCh = 'H';
    }
    if (state == sect1)
    {
        pinMode(pinTriState, OUTPUT);
        digitalWrite(pinTriState, LOW);
        stateCh = 'L'
    }
    if (state == sect2)
    {
        pinMode(pinTriState, INPUT);
        stateCh = 'Z';
    }

    // PART (2) Code to determine state of tri-state pin
    Serial.print(stateCh);     // Shows what it *should* be
    pinMode(pinTest, INPUT);
    if (digitalRead(pinTest))
        Serial.println(" - HIGH");
    else
    {
        pinMode(pinTest, INPUT_PULLUP);
        if (digitalRead(pinTest))
            Serial.println(" - HiZ");
        else
            Serial.println(" - LOW");
    }

    (state == sectMax ? state = 0 : state++);
}

The necessary pins are connected with a single wire. If I upload the code to two boards I remove PART (2) on the 'triState' board and PART (1) on the 'testing' board. In this case, stateCh has no function.
For a single-board setup, I get the following output:
H - HIGH
H - HIGH
...
L - LOW
L - LOW
...
Z - HiZ        <-- the first Z is correct 95% of the time
Z - HIGH
Z - HIGH       <-- the remaining Zs are a mixture, biased heavily towards HIGH.
Z - HiZ
...
H - HIGH       <-- H always gives HIGH
...

It makes no difference if I change the operating order of pinState. I've thrown in delay(100); between almost every other line, again to no avail.
I tried with a 22k, a 33k, and a 47k external pullup resistor. The results are perfect. However, this requires an extra Arduino pin to make sure that the pullup is only active when necessary. Part (2) becomes:
// PART (2) Code to determine state of tri-state pin
Serial.print(stateCh);     // Shows what it *should* be
pinMode(pinTest, INPUT);
pinMode(pinPullup, INPUT);    // connected to pinTest via resistor
if (digitalRead(pinTest))
    Serial.println(" - HIGH");
else
{
    //pinMode(pinTest, INPUT_PULLUP);   <-- not anymore
    pinMode(pinPullup, OUTPUT);
    digitalWrite(pinPullup, HIGH);    // pulls pinTest to Vdd
    if (digitalRead(pinTest))
        Serial.println(" - HiZ");
    else
        Serial.println(" - LOW");
}

Using the extra pin to provide the pullup is a real pain in the ar...duino. I'm cripplingly short of spare pins and I don't see why this is not resolvable with internal pullups. Help?!

"but HiZ returns a mixture of HiZ and HIGH". That's exactly what you expect for an input pin with no pull-up, and a high-impedance (or no) connection. I would be surprised if it didn't alternate between LOW and HIGH somewhat randomly.

@NickGammon: But the input is pulled up - pinMode(pinTest, INPUT_PULLUP) is the first line in the else block. And that doesn't answer why it works with an external pull-up resistor that's turned on at the right time in leiu of the internal pull-up.

Yes, but setting the pin to input with no pull-up or pull-down (your first test) gives meaningless results. See my code example in the amended reply. It works.

I understand your point know. However, that doesn't explain why using an external pullup doesn't exhibit the same problem - bearing in mind that the 'up' leg of the resistor is switched between a HiZ and HIGH source, i.e.  it is switched in and out the same as the internal one would be. Please note that I'm not disagreeing - I'm happy that I can solve this with a simple pull-down. Is it that the leakage of pinPullup happens to be biased towards Vcc, keeping the resistor slightly pulled up at all times?  Why never pulled down by a leakage?

A pin which is input connected to a high-impedance source is undefined. So I won't try to explain why undefined is more often high than low. Maybe right now an adjacent pin pulls it high. In another scenario it might be pulled low. Your external pull-up solution is, if I remember correctly not at all the same thing because the pin always has a defined state.

No, pinPullup (connected to pinTest through the external resistor) is set to an input (HiZ, so undefined, n'est pas?) except for the second digitalRead(pinTest), at which point it's output HIGH. In my view that copies the electrical characteristics of the internal pullup. I've edited the question to add the code for PART (2) when using an external pullup, in case it's still not clear. Ultimately it's a moot point; your reasoning for the error with the internal pullup is enough to assuage my hair-pulling confusion, and your solution to the problem is a suitable answer.

The internal pull-up is around 50k. So, install an external pull-down (to ground) of a somewhat higher value, like 1M.
Now:
Go to input mode, no pull-up. Get a reading. Turn on the internal pull-up. This should overpower the pull-down. If the reading changes, it was tri-state. Otherwise, if the reading doesn't change the external device is overpowering both pull-up and pull-down and you have the actual reading.
You may need a slight delay to allow the low-value pull-down to change the pin state.

Amended code to demonstrate:
// PART (2) Code to determine state of tri-state pin
Serial.print(stateCh);     // Shows what it *should* be

pinMode(pinTest, INPUT);
delayMicroseconds (100);
byte firstReading = digitalRead(pinTest);
pinMode(pinTest, INPUT_PULLUP);
delayMicroseconds (10);
byte secondReading =  digitalRead(pinTest);

if (firstReading != secondReading)
  Serial.println(" - HiZ");
else if (secondReading == HIGH)
  Serial.println(" - HIGH");
else
  Serial.println(" - LOW");

(Only showing the part that detects the pin state, the rest is the same).
Output:
H - HIGH
L - LOW
Z - HiZ
Z - HiZ
Z - HiZ
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
L - LOW
Z - HiZ
Z - HiZ
Z - HiZ
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
H - HIGH
L - LOW
Z - HiZ
Z - HiZ
Z - HiZ
H - HIGH
H - HIGH
H - HIGH

As you can see, working perfectly. I needed a longer delay after turning the internal pullup off because the fall time was around 100 µs. This actually sounds reasonable, because the 1 megohm resistor will take time to discharge the capacitance on the pin.
So:

10 µs delay after turning the internal pull-up on
100 µs delay after turning the internal pull-up off

Theory for the delays
The Atmega328 pin is specified as having a maximum capacitance of 10 pF (10e-12). It is considered charged/discharged after 5 time-constants, where T = R.C.
Thus for an internal pull-up resistance of 50k and a capacitance of 10 pF, charging should take:
50e3 * 10e-12 * 5 = 2.5e-006 (0.0000025) -> 2.5 µs

And to discharge through 1M (1e6) ohms, discharging should take:
1e6 * 10e-12 * 5 = 5e-005 (0.00005) -> 50 µs

My observed results were about 2.5 µS for the charge, but more like 100 µs for the discharge, however I probably had considerable stray capacitance in the wires used in the test circuit.

Testing shows that with a 1 megohm pull-down resistor, it takes around 5 µS for the pull-up to change the pin's state. So a delayMicroseconds (10) or thereabouts should be plenty, to allow the pin time to react to the HiZ situation.

However discharging the pin through the 1 megohm pull-down takes somewhat longer. 100 µS or more. So the code above shows the longer delay after turning off the internal pull-up. The sensible thing to do would be to turn the internal pull-up off right after testing it, then it could be discharging while the code did something else.

Another option is to use an analog input pin instead of a digital input pin.
Create a balanced voltage divider using equal high value resistors (say 100KΩ each).  Attach the mid-point to the ADC pin, and one end to each of Vcc and GND.  The incoming status signal goes to the ADC pin:

Perform an analogRead() on the pin.  You will get one of 3 results:

Close to 0 = LOW
Close to 1024 = HIGH
Close to 512 = HiZ

When the pin is in HiZ the resistors will hold the voltage at around 50% of Vcc.  When the pin goes HIGH it will pull the pin up and override the resistors, giving a high value reading.  Similarly, when the pin goes low, the resistors will be overridden and a low value reading will be given.

+1; This would have been my solution if I had a spare ADC input. Alas, the Pro-Micro isn't blessed in the pins department.

For the 1M pulldown solution, turning off the internal pullup at the end of the pin check routine MIGHT give enough time for the pin to discharge, and it might not if the code can conditionally do very little else between pin checks.  If you want to leave out the 100 us delay, take care to ensure that your code will always do something that takes sufficient cycles for the pin to discharge between checks.

Nick Gammon's answer seems the most straightforward solution to your
problem, given that you cannot spare an analog input. It has however the
drawback of needing a delay of ≈ 100 µs. This may not be an
issue, but I just figured out a scheme that allows a faster read, and
may be of interest to some: instead of pull-ups or pull-downs, put just
a 10 kΩ resistor in series between the MPC73831's output and you
Arduino input. When you want to read the state:

Take a first reading with the pin in INPUT mode:

if you read HIGH, then your MPC is either HIGH or HI_Z
if you read LOW, then it's either LOW or HI_Z

Now, switch the pin to OUTPUT, write the opposite of what you just
read, switch back to input and take a second reading:

if you read what you just wrote, then your MPC is in the HI_Z state
if you read the same as before, then it's either HIGH or LOW.

Here is the implementation of this scheme:
#define HI_Z 2

/*
 * Read a 3-state pin.
 * Put a 10 kOhm resistor between the output and input pins.
 */
int read3state(int pin)
{
    int reading1 = digitalRead(pin);
    pinMode(pin, OUTPUT);
    digitalWrite(pin, !reading1);
    pinMode(pin, INPUT);
    int reading2 = digitalRead(pin);
    if (reading1 == reading2)
        return reading1;
    else
        return HI_Z;
}

I have tested this a few 104 times with an Arduino sending to
itself a pseudo-random sequence of LOW, HIGH and HI_Z. It works
reliably for me.
Caveat: This scheme relies on the pin being capacitively coupled to
GND or Vcc, and this coupling being stronger than couplings with other
signals in your circuit. If you fear this might not be the case, you can
put something like 100 pF from the pin to ground, but then you
should better wait a couple of microseconds before taking the second
reading.


text:
NodeMCU max draw
1) what is the max draw I can draw from NodeMCU V3 logic and 5v pins?
2) Also, I heard i draw with it more than 500mA, the PC USB port stops working. Is that information actual? Because USB 3 port has 900mA and USB 2 had 500mA max

it is unclear what you are asking ... is what actual?

for ESP8266 (which your NodeMCU is based upon) , the maximum current is about 20mA sinking and 12mA sourcing per [single] pin. so the maximum current of all GPIOs together is a lot lower than the 500mA USB limits.
you have to use external drivers (transistors, MOSFETs) for that purpose.
Sink current: the current which is provided when you pull the pin LOW. e.g. when you provide GND for the cathode of an LED. (the Anode is connected to VCC).
Source current: the current which is provided when you pull the pin HIGH. e.g. when you provide VCC for the anode of an LED. (the cathode is connected to GND).
the difference is for different internal resistance for identical N-MOS/P-MOS, due to their structure. that's why many devices like 7segment drivers, or motor drivers supply GND for the Load (common anode drivers) instead of VCC.

I would guess the question is not about the esp8266 io pins, but about the 3.3 V pin and the NodeMcu 3 on-board regulator

@Juraj it is said "logic" and 5v pins. It seems he means both of them

In that case, the Vin pin (which provides the 5 V from the USB cable) will be limited by the power source or cable and the 3.3 V rail provided by the NodeMCU i wouldn't draw more than about 300 mA from it. I don't know the rating of the actual component but looking at the package and amount of board area for heat dissipation i think that'd be a safe value for most ambient conditions.


text:
Mac OS X Catalina Serial Monitor Problem
I have some problems on MacBook Pro running with Catalina. I bought new nodemcu LoLin board. Its clone. It has ch340 adapter to communicate. And writing on bottom side wemos.cc and use ch340g driver.
I succesfully installed drivers and I can see my lolin boards on port list
I upload a code that doing only print hello to serial port. I tried with 9600 and 115200 baud rates. My serial monitor show garbage data. I am using platform io with VSCode to upload code and upload time is too much.When I am uploading code I got this warning :
"Detected crystal freq 156.04MHz is quite different to normalized freq 40MHz. Unsupported crystal in use?"
I am using cheap thundeIrbolt usb converter too. But I connect with this converter to Windows pc, everything looks fine. I can see hello world on serial monitor. But on my Mac, I can see garbage only. I tried some serial monitors, Arduino IDE and platform io ide but still same.
Are there any solution about this problem?
EDIT :
I fixed issue last night. Catalina has ch340 drivers already and I setup oem driver from GitHub. Apples driver and oem drivers conflicting. If you use Mojave and higher os, you dont need any driver for ch340. So if you installed ch340 oem  driver you should delete it.
I am adding the post:
Platformio post

Can you post a photo of the board? You may have bought an ESP32 board about not an ESP8266. Also try baud rate 74400 - if it is an ESP8266 the boot loader will print messages at 74400.

I can read on chip esp12e. Its not esp32. And chip vendor is DOITING. On windows i can use 115200 or 9600 but on mac it send to serial garbage data.

And i used 74400 still garbage.

You should post the solution you found as a self-answer, and accept the answer...

I fixed issue last night. Catalina has ch340 drivers already and I setup oem driver from GitHub. Apples driver and oem drivers conflicting. If you use Mojave and higher os, you dont need any driver for ch340. So if you installed ch340 oem driver you should delete it.
I am adding the post: Platformio post


text:
What happen with my code? My sensor module LED2 Always ON
I got this code from robojax.com
i have follow all the step but when i try to clap its not turn off or turn on
but when i blowing on the sound sensor it reacts and makes the light turn on
int soundInPin = 2;// connect output to Sound module DO
int relayPin = 8;// Connected to relay or buzzer (or LED)
int extra5V = 12;// define a pin for extra extra 5V

// do not change values bellow
int val = 0; // sound value from pin 2
int relayON = 0;//light status
int heard = 0;//sound heard status

void setup() {

//Robojax Arduino Step By Step Course http://robojax.com/L/?id=338
  Serial.begin(9600);
  pinMode(soundInPin, INPUT_PULLUP);
  pinMode(relayPin, OUTPUT);
  pinMode(extra5V,OUTPUT);// set extra5V as output
  digitalWrite(extra5V,HIGH);// turn the extra5V pin HIGH to get 5V

}

void loop() {
//Robojax Arduino Step By Step Course http://robojax.com/L/?id=338
  val = digitalRead(soundInPin);// read the sound pin

  if(val == HIGH && relayON == LOW){

    heard = 1-heard;// toggle the value of "heard" from HIGH to LOW or from LOW to HIGH
    delay(100);
  }
//Robojax Arduino Step By Step Course http://robojax.com/L/?id=338
  relayON = val;// save the value of pin 2

      if(heard == HIGH){
        Serial.println("Light ON");
        digitalWrite(relayPin, LOW); // turn relay ON

      }else{
        Serial.println("Light OFF");
        digitalWrite(relayPin, HIGH);// turn relay OFF

      }

//Robojax Arduino Step By Step Course http://robojax.com/L/?id=338
  delay(100);
}

Welcome to Arduino:SE.  If you want us to be able to help you, we'll need to see how you wired the hardware together as well as your code.

Is there something on the sound sensor board to adjust the threshold? Like potentiometer ?

With no schematic it is difficult to understand what to expect at soundInPin.  That said, inspecting the code, if "val" changes to 1,  "heard" changes to 1, "relayON" changes to 1, the LED is turned on then the LED is never turned off because "relayON" is 1 which does not allow "heard" to change ever again.  So despite what the hardware does, the code appears to need some more work.

Hello, Mr. Myth! Let's start from the basics: 1. What Arduino board? 2. What is it you are trying to do (explain, please), and 3. (As others have said) what does your schematic look like?

Have you seen this answer? https://arduino.stackexchange.com/a/54495/37523

This is not an answer, so I will delete it after you read it.
Since you are a beginner, here is a comment on programming style.
Your code feels very cluttered and overwhelming because the comments are made a part of the program lines.
There is a difference in readability between these two lines.
digitalWrite(extra5V,HIGH);// turn the extra5V pin HIGH to get 5V
digitalWrite(extra5V,HIGH);                // turn the extra5V pin HIGH to get 5V
The comments are there for future, like next year, to remind you what the program does.
Also the following two lines are on the same indentation level
  relayON = val;     // save the value of pin 2

      if(heard == HIGH){

and should be
  relayON = val;     // save the value of pin 2

  if(heard == HIGH){

With some formatting changes, your code could look something like this.
int soundInPin =  2;                       // connect output to Sound module DO
int relayPin   =  8;                       // Connected to relay or buzzer (or LED)
int extra5V    = 12;                       // define a pin for extra extra 5V

// do not change values below

int val        =  0;                       // sound value from pin 2
int relayON    =  0;                       // light status
int heard      =  0;                       // sound heard status

void setup() {                             // Robojax Arduino Step By Step Course http://robojax.com/L/?id=338

  Serial.begin(9600);

  pinMode(soundInPin, INPUT_PULLUP);
  pinMode(relayPin,   OUTPUT);
  pinMode(extra5V,    OUTPUT);             // set extra5V as output

  digitalWrite(extra5V,HIGH);              // turn the extra5V pin HIGH to get 5V

}

void loop() {                              // Robojax Arduino Step By Step Course http://robojax.com/L/?id=338

  val = digitalRead(soundInPin);           // read the sound pin

  if (val == HIGH && relayON == LOW) {

    heard = 1-heard;                       // toggle the value of "heard" from HIGH to LOW or from LOW to HIGH
    delay(100);

  }                                        // Robojax Arduino Step By Step Course http://robojax.com/L/?id=338

  relayON = val;                           // save the value of pin 2

  if (heard == HIGH) {

    Serial.println("Light ON");
    digitalWrite(relayPin, LOW);           // turn relay ON

  } else {

    Serial.println("Light OFF");
    digitalWrite(relayPin, HIGH);          // turn relay OFF

  }
                                           // Robojax Arduino Step By Step Course http://robojax.com/L/?id=338
  delay(100);
}