text:
How to keep track of millis during sleep mode
In my application, I need to keep track of the time the application has been running as well as use sleep modes. However, when using the sleep modes, Timer0 is disabled, and therefore millis stop counting.
Is there a way to measure/count how long the Arduino was in sleep mode for?
To give you some more background info, this is what I'm trying to achieve:
I am using a pressure sensor which sends an interrupt to the Arduino every 80ms and wakes it up.
The program does various routines to process the data which can take anywhere from 2ms to 60ms.
It then goes into sleep mode until another external interrupt occurs, approx 20-78ms later.
The application has many processes based on time, such as a stopwatch, timer and alarm, so I need to be able to keep track of this, preferably using millis().
The device is running on a single cell 250mah LiPo battery which at present only lasts about 4 hours.
I'm using an ATMega1284.
In most of the sleep modes Timer0 is disabled. Which means that millis() stops counting. Is there a way, without using an RTC (Both Space and weight are at a premium), to keep millis counting whilst in sleep mode?
I notice that SLEEP_MODE_IDLE keeps Timer0 running, but that means that for every millisecond an interrupt wakes up the device. Please correct me if I'm wrong, but given that my loop can take about 60ms to execute, I don't see much advantage to sleeping for 1ms.
Possible solutions:

Use Timer2 for the millis function?
Use the Watchdog Timer to count how much time has passed whilst in
sleep mode and add this to millis() when waking up?
If there was a VERY small SMD RTC which didn't need any external
components such as oscilators etc then this might be feasible.

MAX31343 in a 2.1mm x 2.3mm, 8-Pin WLP Package...?

I think you'd need an RTC anyway, if you are doing alarms. The millis will drift to much to be very useful for accurate time keeping. If space is an issue, you could use the timer2 asynchronous mode and connect a 32khz crystal to the TOSC pins. Then you can use the Power-save sleep mode. I've done in on a clock project, but it's a bit of work figuring out how to set it up the code. After calibration it now accurate to within a minute per year.

@Majenko - the MAX31343 only records seconds, not milliseconds

The only way to keep millis() running is sleep mode is to sleep in
SLEEP_MODE_IDLE. Switching to Timer 2 would make no difference, as
all timers but the watchdog are stopped in other sleep modes. The
watchdog is horribly inaccurate, so you do not want to rely on it for
any kind of timekeeping.

I don't see much advantage to sleeping for 1 ms.

Sleeping for 1 ms saves a little bit of power. But if you do that
60 times every 80 ms you will save a lot of power. I suggest
you do just that: sleep when you are done with your calculations. When
you wake up, if you see that the waking up came from the external
interrupt, the you process it. Otherwise you just go back to sleep.
Note that if the 80 ms period of the external interrupt is
consistent enough, you could use that as time source.

Thanks @Edgar. As soon as I posted the question I went searching through the library at the 80ms interrupt but it turns out that the library just requests data every 80ms, and the sensor sends an interrupt once the data is ready.

I've tried permanently turning off timer 1 and timer 3, as well as turning off the ADC and BOD for 59.95 seconds of every minute, and using sleep mode idle. The main loop checks if an interrupt has happened otherwise it goes back to sleep. The impact this has had on power consumption has been minimal. I'm now trying with a real time clock.

I found a RealTimeClock that I could use: RV-8803.
It's only 3.2mm x 1.5mm x 0.8mm, has an internal XTAL, and can provide time in 100th of a second.
Sparkfun do a breakout board (BOB-16281), and accompanying library.
Given that I've already got a bunch of decoupling capacitors in my circuit and can use the internal pullups of the ATMega1284, I think I can probably integrate the RV-8803 without the need for any additional components.
On the breadboard, interrupts are working well and I can now use EXTENDED_STANDBY sleep mode instead. The only downside is that the RTC records time in 100ths of a second, whereas my program was using milliseconds previously. I'll need to see if 100ths is accurate enough for my needs.
Failing that, I'll have a look at @Gerben's suggestion above.


text:
How to supply more than 500mA while powered by USB
I'm about to build myself a new BrewPi and I have some Arduino power/USB questions.
Something smiliar to a combination of these projects:
https://i.stack.imgur.com/gZHZt.jpg
https://www.homebrewtalk.com/threads/how-to-brewpi-lcd-add-on.510036/
The device will have a Raspberry Pi Zero W, an Arduino UNO (clone?), a LCD screen with backlight, and some relays and probes. The Pi must be connected to the Arduino via USB. The Arduino will drive the screen and some relays/probes. For simplicity's sake, I would like to power everything from the same regulated 5V power supply, and for ease of wiring I would prefer to power the Pi only and have it power the Arduino via USB, with the Arduino then supplying power to the rest.
My preference:
5V ----> Pi Zero --(USB)--> Arduino --(5V)--> Screen/etc.
However, according to this datasheet the max draw of the screen might exceed 1000mA:
https://www.vishay.com/docs/37314/lcd020n004l.pdf
This obviously exceeds the 500mA limit from the Arduino's 5V pin while being powered via USB. However, a Pi Zero has few safety features and does not limit outgoing current from it's USB port:
https://www.reddit.com/r/raspberry_pi/comments/3zyhuq/pi_zero_usb_power_outputmilliamps/
Given this, is it feasible to short/bypass the Arduino's polyfuse and then draw more than 500ma from the 5V pin of the Arduino without too many problems?
If not, can I 'add' the power supply's 5V to the Arduino's 5V (either from the Pi's 5V pin, or direct from the power supply) at the same time as maintaining the USB connection (which uses the same 5V source)? I'm stretching the limit of my circuit understanding here. If not how should I power the other components?
Would it instead be better to have a 12V supply and power the Arduino directly, then attempt to power everything else from its 5V pin (remembering that there is still a USB connection from the Pi back to the Arduino). What I'd really like to avoid in this situation is having to provide a second 12V->5V conversion.
Any help or advice would be greatly appreciated.

neither the RPi, nor the Arduino are meant to be used as a power supply ... using them as a power supply makes them act as an expensive fuse

just run everything off the 5v, don't use USB connectors.

@dandavis My concern with that option is I must also have the USB connected from the Pi, and I haven't managed to find a source that says that's going to be OK

When you power the Zero and the Uno with the same 5V power supply, the additional USB connection between them should be OK. But the power has to run outside of both boards.

Simply don't connect anything to the Uno's 5V pin, but feed it via USB. (That's how I understand @dandavis' comment) ?

I'm not sure where you got the 1000mA from. The LCD itself only has a max of 10mA. You might be talking about the ratings of the background LED with has a max of 1080mA. I very much doubt you can run the LED at that current. It would probably be very bright for a short while, and then die. That value is probably the max pulsed current (in short bursts).

If you power both your screen and RPi from the same 5V, just add an additional cable from the charger to the screen, that way you won't use the poor RPi as a fuse. In addition to that, if the current draw of the display is potentially high, peaks, then attach a 100-2000uF capacitor to the power pins, it helps to avoid any potential issues.

Do not bypass the fuse. Drive your external components directly from the external 5V power supply. Do not pass everything through the Arduino.
You say you have a regulated 5V power supply. Assuming it provides enough current you should use it to drive your external components directly.
You might need to add a filter capacitor near the feed for the Pi/Arduino, to filter out fluctuations in the 5V supply as your high current components switch on and off. You should be able to google "Power supply filter capacitor" to learn more.

Yeah, this.  They didn't put that fuse there just to stifle you while the thing is actually capable of more.  They put that fuse there so you don't burn up the boards you paid good money for.

source: Stack Exchange

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

sort: votes


text:
NodeMCU wiring for Serial1?
I'm trying to get telemetry data to be sent out Serial1 on the NodeMCU board.  I read that TX is (by default) mapped to pin D4.
Ultimately, there will be a Raspberry that will be listening for these messages, but I don't have it yet.  So to quickly test this, I connected an oscilloscope with Serial decoding to D4 and the GND of the probe to GND on the NodeMCU.  The problem is I'm not getting any indication of activity out D4 when I run the following code:
Serial1.begin(9600);
Serial1.printf("some text");

Am I wiring the probe correctly?  Am I missing another serial command in the sketch?
When I move to the rPI, do I GND both boards together, then write TX (D4) to RX on the rPI?

https://community.blynk.cc/t/how-to-use-2-serial-ports-or-more-in-nodemcu/20282/2. one of the answers insists that the nodeMCU shouldn't be connected to computer to be able to use serial1

You can do Serial.swap() in setup() to swap Serial away from RX/TX pin. Serial is then on D7 as RX and D8 as TX (and you can wire some serial module there).
Bridge with jumper wire D4 pin with TX pin. the Serial1 output will go over the USB chip to Serial Monitor and you will see the prints to Serial1.
This will not disturb the flashing mode, because bootloader will still listen on standard Serial pins.

This code worked for me as Modbus slave
Required this library <ModbusRtu.h>
#include <ModbusRtu.h>
unsigned long TIME = 0;
unsigned long LASTTIME = 0;
unsigned long INTERVAL = 5000;

int i = 0;
// data array for modbus network sharing
uint16_t au16data[16] = {
  3, 1415, 9265, 4, 2, 7182, 28182, 8, 0, 0, 0, 0, 0, 0, 1, 11 };

/**
 *  Modbus object declaration
 *  u8id : node id = 0 for master, = 1..247 for slave
 *  port : serial port
 *  u8txenpin : 0 for RS-232 and USB-FTDI
 *               or any pin number > 1 for RS-485
 */
Modbus slave(1,Serial,0); // this is slave @1 and RS-232 or USB-FTDI

void setup() {
  Serial.swap();
  Serial.begin( 19200 ); // baud-rate at 19200
  Serial1.begin( 19200 );
  slave.start();
}

void loop() {

  if ((millis() - TIME) > INTERVAL) {
    i++;

    if(i == 16){
      i = 0;

      for (int ii = 0; ii < 16; ii++)
      {
        au16data[ii] = 0;
      }
    }

    au16data[i] = 1;

    TIME = millis();
  }

  slave.poll( au16data, 16 );
}

I'm not sure how this answers the question.

Because above mentioned type of wiring, I have done but I can't find the correct code library, after some research, I found a suitable library. So I share this platform to help others. Thank you!

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


text:
Need help with EEPROM not storing array values on ESP8266 after restart
I am struggling through a program. I am trying to store my uploaded string into an array then write that array to EEPROM. I run the program, upload the new array and store it in the EEPROM. all values display correctly until I reset or power off the device. I am sure I am overwriting or something obvious, but i am breaking down and asking for help.
The read and write EEPROM subroutines are at the bottom of the code. I call the EEPROM_Write() in server.on after parsing the http get.
EDIT: per feedback, removed all but the function, with the EEPROM.commit(); suggestion included... still not working

void EEPROM_Write(){
Serial.begin(115200);
EEPROM.begin(280);
  // store values in EEPROM
  for (int i = 0; i < pwmarray1Size; i++)
  {
    Serial.println(pwmarray1[i]);
    EEPROM.put( EEPROMStartAdress + (i * sizeof pwmarray1[0]), pwmarray1[i]);
  }
  Serial.println();
  EEPROM.commit();
 // EEPROM.end();
}

what is EEPROMStartAdress? you can put the whole array in EEPROM with one 'put'

The ESP has no real EEPROM. Instead the EEPROM class for ESPs uses the flash memory. There is a difference in the implementations of this class between Arduinos and ESPs:
On an ESP every data, that you write, will first be placed in a buffer in RAM. You  need to call EEPROM.commit() to actually write that data to the underlying flash memory.
So you need to add
EEPROM.commit();

to the end of your EEPROM_Write() function, or the data will stay in RAM and thus be lost on power cycle or reset.

I think your problem (besides the commit) lies not in your EEPROM_Write() function, but in the EEPROM_Read() function. If it doesn't work correctly, you are just not able to see, if the data gets written correctly. In your code (which can be seen in the edit history), you have this function:
void EEPROM_Read(){
   //load array pwmarray1 with stored values in EPROM
  for (int x = 0; x < pwmarray1Size; x++){
    EEPROM.get(EEPROMStartAdress + (x * sizeof pwmarray1[0]), pwmarray1[x]);
        Serial.print("loading program from EPROM: ");
    Serial.println(pwmarray1[x]);
    }
}

While in EEPROM_Write() you are calling EEPROM.begin(280) every time, you don't EEPROM.end() it there and you are also not begin the EEPROM in the EEPROM_Read() function. I'm not sure about the underlying implementation, but it started to work for me, when I began and ended the EEPROM object in both functions.
I've written a test code, that I composed party of your code and that for me correctly saves and reads an array via the EEPROM object into the flash memory. It keeps the data over resets and power cycles just correctly. You can control it via Serial Monitor. Just type c (for clearing the array to zero), r (for reading the array from EEPROM/flash) or i (for incrementing all array elements and save them to EEPROM/flash).
#include <EEPROM.h>

#define EEPROM_SIZE 280

int array[60] = {0};
const unsigned arraySize = sizeof array / sizeof array[0];

#define EEPROMStartAdress 0

void setup(){
  Serial.begin(115200);
  Serial.println("///////////////////////////////////////");
  delay(2000);
}

void loop(){
  if(Serial.available()){
    char c = Serial.read();
    switch(c){
      case 'c':
        for(uint8_t i=0;i<arraySize;i++) array[i] = 0;
        EEPROM_Write();
        Serial.println("EEPROM RESET");
        break;
      case 'r':
        EEPROM_Read();
        break;
      case 'i':
        for(uint8_t i=0;i<arraySize;i++) array[i] += 1;
        EEPROM_Write();
        break;
    }
  }
}

void EEPROM_Write(){
  EEPROM.begin(EEPROM_SIZE);
  // store values in EEPROM
  for (int i = 0; i < arraySize; i++)
  {
    EEPROM.put( EEPROMStartAdress + (i * sizeof array[0]), array[i]);
  }
  EEPROM.commit();
  EEPROM.end();
}

void EEPROM_Read(){
  EEPROM.begin(EEPROM_SIZE);
  for (int x = 0; x < arraySize; x++){
    EEPROM.get(EEPROMStartAdress + (x * sizeof array[0]), array[x]);
    Serial.print(" ");
    Serial.print(array[x]);
    }
  Serial.println();
  EEPROM.end();
}

Removing begin() and end() from EEPROM_Read() and also end() from EEPROM_Write() gives me the same results, that you described as your problem.

the labels are misleading. I am using "put" and "get". can i use EEPROM.commit() after a put?

put and get are just wrappers around write and read, that help you to write more complex data than single bytes. In the background the exact same is happening. So yes, you can use EEPROM.commit() after EEPROM.put().

I have added the EEPROM.commit() and still am not getting values stored in the EEPROM. Do you know if the "EEPROMStartAdress" location has any effect?

ok, I have spent 30 hours staring and trying to make this work to no avail. i parsed down a test to a single number. posted the new question here: https://stackoverflow.com/questions/62415395/eps8266-writing-number-to-eeprom-fails-to-write-returns-0?fbclid=IwAR1QxJ_EXw8jqKaiLLNoDsChW2l0CpGUlQcmTu3WrKaijchN4qc_8Mn5quo

I'm currently working on a test sketch, but as of now, my your function works with my ESP32. I will make complete a minimal functioning test sketch, that you can test with your board. Maybe I'm able to do this tomorrow evening. The EEPROMStartAdress just tells the function, where to start writing in the provisioned EEPROM. Should not make a problem.

unless EEPROMStartAdress is larger then the allocated size

@deathrace2020 Now I was able to reproduce exactly and get a fix. I've added the solution and also the testsketch, that I used, to the answer

you can write the whole array with one put and read it with one get. `end' calls 'commit'


text:
Arduino Micro 5V Vin and 3v3 pins
I am very confused with the pins on the arduino micro. What are the 3v3, 5v, and Vin pins used for? Are they for power input, or power output, or both?

Vin is a power INPUT. It is connected to the input of the voltage regulator, which enables you to power the Arduino with voltages between 6V and 12V, while the Arduino itself is running on 5V.
The 5V pin can be both an power INPUT and OUTPUT. It is connected to the general 5V power rail inside the Arduino and thus to the power inputs of the microcontroller. This rail/pin needs to be provided with 5V power to let the Arduino work. Where this power comes from (from the voltage regulator, from USB or from your own external 5V power supply connected to the 5V pin) is irrelevant for the Arduino. The 5V pin can even be used to provide power to other components in your circuit (though with certain limitations, see below).
The 3V3 (meaning 3.3V) pin is a power OUTPUT. It is connected to the output of another voltage regulator, which brings the 5V from the 5V rail down to 3.3V. It can be used to power external parts, that need 3.3V to work.

Up to this point I only wrote about voltage. But depending on your circuit you also need to consider the current. The different electrical parts on the Arduino can only handle a specific power (measured in Watts). Thus with a given voltage you can only draw up to a specific amount of current through them, before you destroy them.
As an example, let's assume you provide the Arduino with 9V through Vin and you want to drive a middle sized motor. Motors in general can draw a lot of current. When you now drive the motor from the 5V pin of the Arduino, the motors current will flow through the Arduinos voltage regulator. Thus the regulator will go into emergency shutdown and cut the power (applies for a genuine Arduino) or it will get destroyed (applies for most cheap Arduino clones). To prevent that, you need to connect the motor directly with the power supply (or through an extra voltage regulator, suitable for the needed current), so that the current for it is no longer flowing through the Arduino.
This explanation is only to prevent you from destroying your board. That is always very annoying, when it happens.

Ahh, this makes much more sense! Thank you very very much! :)

Upvoted (also because of the last line, which is quite an understatement).

Excellent answer. One point I would add is that if you are going to supply 5V to the 5V line, you need to make sure it is regulated 5V. If it strays too far from 5V it will cause the board to malfunction and may damage or destroy it.

VIN is power input. IN means INput.
Generally 5V and 3.3V are used for power output, but the 5V one can also be used for power input if you want to power the board from 5V.
But since they are just power they have no "direction" as such, only a voltage level.


text:
arduino pro mini fqbn
Introduction
I am trying to program an arduino pro mini, I have to use this board because of it's size.
I use the arduino-cli to program arduino and one of the steps to upload code to the system requires the board's fqbn and I can't find it anywhere.
Question
Does anybody know this board's fqbn (fully-qualified board name)?

https://github.com/arduino/ArduinoCore-avr/blob/1.6.21/boards.txt#L670-#L697


text:
LiquidCrystal swap lines with interrupt
#include <Wire.h>
#include <LiquidCrystal.h>
int temp;
const int rs = 13, en = 12, d4 = 11, d5 = 10, d6 = 9, d7 = 8;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
char Nick[15] = {' ', ' ', 'T', 'A', 'R', 'I', 'F', ' ', 'Z', 'I', 'N', 'E', 'D', ' ', ' '};
int butonPin = 2;

void setup() {
  Wire.begin(1);
  Serial.begin(9600);
  pinMode(butonPin,INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(butonPin), Rev, RISING);
  lcd.begin(16, 2);
}

void loop() {
  Wire.onReceive(data);
  lcd.setCursor(2, 1);
  lcd.print(temp);

  if (temp < 25) {
    lcd.setCursor(5, 1);
    lcd.print("NORMAL");
    lcd.print(" ");
    lcd.setCursor(12, 1);
    lcd.print(" ");
  }
  if (temp >= 25 && temp <= 30) {
    lcd.setCursor(5, 1);
    lcd.print("HOT");
    lcd.print(" ");
    lcd.setCursor(11, 1);
    for (int i = 0 ; i < 3 ; i++) {
      lcd.print(" ");
    }
  }
  if (temp > 30) {
    lcd.setCursor(5, 1);
    lcd.print("VERY HOT");
    lcd.print(" ");
  }
  lcd.setCursor(0, 0);
  for (int j = 15; j > 0 ; j--) {
    lcd.print(Nick[j]);
  }
  lcd.setCursor(0, 0);
  delay(70);
  int swap = Nick[15];
  for (int i = 15; i > 0; i--) {
    Nick[i] = Nick[i - 1];
  }
  Nick[0] = swap;
}
void Rev(){
   Wire.onReceive(data);
  lcd.setCursor(2, 0);
  lcd.print(temp);

  if (temp < 25) {
    lcd.setCursor(5, 0);
    lcd.print("NORMAL");
    lcd.print(" ");
    lcd.setCursor(12, 0);
    lcd.print(" ");
  }
  if (temp >= 25 && temp <= 30) {
    lcd.setCursor(5, 0);
    lcd.print("HOT");
    lcd.print(" ");
    lcd.setCursor(11, 0);
    for (int i = 0 ; i < 3 ; i++) {
      lcd.print(" ");
    }
  }
  if (temp > 30) {
    lcd.setCursor(5, 0);
    lcd.print("VERY HOT");
    lcd.print(" ");
  }
  lcd.setCursor(0, 1);
  for (int j = 15; j > 0 ; j--) {
    lcd.print(Nick[j]);
  }
  lcd.setCursor(0, 1);
  delay(70);
  int swap = Nick[15];
  for (int i = 15; i > 0; i--) {
    Nick[i] = Nick[i - 1];
  }
  Nick[0] = swap;
}

void data(int numBytes) {
  while (Wire.available()) {
    temp = Wire.read();
  }
}

In lcd's first line i have scrolling text.
Second line it shows current temperature and data from another master device.
My question is i want to change text line when button pressed and text shouldn't go back to old state it need to be stay in changed line and when the button repressed it change again
In my code when the button pressed several times lcd  gone weird :
I tried swap lines with lcd.setCursor() function :
In loop function :
lcd.setCursor(0, 0);
      for (int j = 15; j > 0 ; j--) {
        lcd.print(Nick[j]);
      }

In reverse function :
lcd.setCursor(0, 1);
  for (int j = 15; j > 0 ; j--) {
    lcd.print(Nick[j]);
  }

Thanks for answers guys

your ISR (interrupt service routine) is too long and complex ... a press of a button should call an ISR that only sets a flag and exits .... the flag should be checked and serviced during the execution of loop()

Catching humans pressing buttons is a poor use of an interrupt.  You could do this a lot easier if you just poll the button.  Your interrupt function contains way too much code and uses code like delay that just plain won't work in an interrupt context.  If you don't KNOW what you're doing with interrupts then it's probably best to leave them alone.  You really need a lot of study before you use them.  There's obviously a lot you don't know.

For one, inside an ISR all other interrupts are off.  So things like delay and serial comms and maybe even stuff to do with your LCD simply won't work at best or lock up the program at worst.

I readed all answers and %100 you guys right if i have chance i leave alone this interrupt madness but this project is my final assignment in college and my instructor was made a working one. Actually i am not expert in arduino like you guys said.


text:
Why does my Arduino/Ledstrip combi not work?

simulate this circuit – Schematic created using CircuitLab
I am using an Arduino Uno, and WS2813 led strip (60 leds).
It seems like a default schematics (except I did use a 470 uF (electrolytical) cap instead of 1000 uF electrolytical cap.
(I accidantally marked the VCC pin of U1 VSS).
I don't get any LED of the LED strip glowing.
The program I used is:
#include <FastLED.h>

#define NUM_LEDS 60
#define DATA_PIN 7

CRGB leds[NUM_LEDS];
bool led = false;

void setup() {
    //FastLED.addLeds<WS2813, DATA_PIN>(leds, NUM_LEDS);
    FastLED.addLeds<WS2813, DATA_PIN>(leds, NUM_LEDS);
    pinMode(LED_BUILTIN, OUTPUT);
}

void loop()
{
    for (int i = 0; i < NUM_LEDS; i++)
    {
      leds[i] = CRGB::Red;
    }
    FastLED.show();
    led = !led;
    digitalWrite(LED_BUILTIN, led ? HIGH : LOW);
    delay(1000);
}

What I tried was:

Checking different data pins on the Arduino
Checking different wires
Checking that over D7 and after the resistor there is indeed 330 Ohm resistance (it was 345 Ohm)
Tried different data pins (and adapted the scene to use a different data pin)
Checking that LED D1 is on (5V is flowing)
Checking that at the end of the WS2813 there the VCC and GND 5V difference (it is about 5.1 V)
Checking that there is indeed 5 V difference between the adapter + and - (was 5.2 V, unloaded).
Tried with WS2813's BI grounded and unconnected
Tried without the 330 ohm resistor.
Checked with a the same circuit but WS2812B (and adapting the code to use WS2812B)
Used different timings for the builtin LED to see that the sketch is actually uploaded.
Tried with , RGB) added in line: FastLED.addLeds<WS2812B, DATA_PIN, RGB>(leds, NUM_LEDS);
With a logic analyzer I see that every second there is a short burst of data (not analayzed exactly what, I assume FastLed is reliable).

All no difference.
However, what I did see, is the logic analyzer data AFTER the 330 ohm resistor mostly removes the data, while the data before the resistor is ok. However, when remove the resistance, still the LED strip does not light up.
Channel 0 is before the resistor, channel 1 after:

What did I do wrong?

did you connect to the correct end of the LED strip?

@jsotola YES ... I should have asked earlier :-); If you put it as answer, I upvote/accept it.

It is important to connect the Arduino digital pin to the correct end of the LED strip.
LED strips have a unidirectional data line.
The power and ground connections can be made from either end, but the data IN is at one end and data OUT is at the other end.
That arrangement is for the purpose of daisychaining the LED strips.
The LEDs themselves also have data IN and data OUT, and are also daisychained with their neighbouring LEDs.
The LEDs are serially connected to each other through the data line, and are connected in parallel to the power and ground lines.

Yes, I noticed there is a direction (which is logical). Guess when I tried it before it worked instantly, probably because I randomly selected at that time the right side, and now the wrong one.


text:
LCD stays blank when it is on and all wiring seems correct

So I have to do this project for school and it involves using a lcd display on tinkercad. I followed the wiring on this tutorial here: https://www.arduino.cc/en/Tutorial/HelloWorld. When I turn it on, the display is just blank even though I've tried to print.
Here is the code I have for this
#include <Servo.h>
#include <LiquidCrystal.h>

//TESTING
//ULTRASONIC WORKS
//SERVO WORKS
//BUZZER WORKS
//POTENTIOMETER WORKS

//Variables:

Servo pump;

LiquidCrystal lcd (12, 11, 5, 4, 3, 2);

bool blnPump = true;

long lngTimer = 0;
long lngDistance = 0;

int intPumpTime = 0;
int intLightLevel = 0;
int intCount = 0;

//soundDistance:to use the ultrasonic distance sensor and find the distance of an object above

//input
    //intSignalPin: to indicate which pin to use for the sensor
//output
    //lngDistance: the distance between the sensor and the object in cm

long soundDistance (int intSignalPin)
{
  long lngTime = 0;
  long lngDistance = 0;
  //gather the time is takes for the sound to travel back

  pinMode (intSignalPin, OUTPUT);
  digitalWrite (intSignalPin, LOW);
  delay (2);
  digitalWrite (intSignalPin, HIGH);
  delay (10);
  digitalWrite (intSignalPin, LOW);
  pinMode (intSignalPin, INPUT);
  lngTime = pulseIn (intSignalPin, HIGH);

  //Serial.println (lngTime);
  //calculating the distance

  lngDistance = lngTime * 0.01723;

  return lngDistance;
}

void setup()
{
  pinMode (A0,INPUT);
  pinMode (A1, INPUT);
  pinMode (9, OUTPUT);
  pinMode(13, INPUT);
  Serial.begin (9600);

  pump.attach (10);

  lcd.begin(16, 2);
  lcd.print ("hello");
}

void loop()
{
  //turning lcd off
  digitalWrite (8, LOW);

  lcd.print ("hello");
  //determining how many times the servo will pump
  intPumpTime = analogRead (A0);

  if (intPumpTime >= 0 && intPumpTime <= 341)
  {
    intPumpTime = 1;
  }

  else if (intPumpTime >= 342 && intPumpTime <= 683)
  {
    intPumpTime = 2;
  }

  else //if (intPumpTime >= 684 && intPumpTime <= 1023)
  {
    intPumpTime = 3;
  }

  //Pumping if theres a hand in range of 5cm to 25cm and pumping different amounts of sanitizer based on potentiometer, playing a tone if it does and turning the lcd on or off based on light level

  if (soundDistance (13) >= 5 && soundDistance (13) <= 25 && blnPump == true)
  {
    //turning lcd on or off
    intLightLevel = analogRead (A1);
    if (intLightLevel <= 300)
    {
      lcd.noDisplay();
    }

    else
    {
      lcd.display();
    }

    //playing tone to indicate its pumping
    tone (8, 500);
    delay (100);
    noTone (8);

    //lighting up led to indicate its pumping
    digitalWrite (9, HIGH);

    //pumping
    for (intCount = 0; intCount < intPumpTime; intCount++)
    {
        pump.write (90);
        delay (1000);
        pump.write (0);
        delay (1000);
    }

    //shutting off the led and turning the servo off
    digitalWrite (9, LOW);
    blnPump = false;

    lngTimer = millis();

    //waiting here to display hand scrubing time, no more sanitizer will be dispensed in this 20 seconds
    while (millis() - lngTimer < 20000)
    {

      if (millis() - lngTimer <= 1000)// && intLightLevel > 300)
      {
        lcd.clear();
        lcd.print ("19 seconds left");
      }

      else if (millis() - lngTimer > 4000 && millis() - lngTimer <= 5000)// && intLightLevel > 300)
      {
        //blnPump = true;
      }
    }

    //decide if to use LCD or not here
  }

  else
  {
    pump.write (0);
  }

  //Serial.println (soundDistance (13));
  //long lngTest = soundDistance (13);
}

Sorry for all the extra code, they're for the other parts. I think I have followed what needs to be followed with inputting the pin into the LiquidCrystal class, the begin method but it just doesn't print.

For clarification, I inputted the pins into the liquid crystal class near the top under variables. Begin() and print() is in setup

You're probably taking too much power out of the 5V pin and nothing is getting proper power.  The 5V pin isn't there to power your whole project.  Try using a separate power supply for all the stuff involved there and see if that doesn't help.

You certainly shouldn't be trying to power a motor or servo off the 5V pin.  That's a good way to end up needing a new Arduino.

Never thought about that since I've always just used the 5v pin and everything before worked. I'm going to try that out tomorrow

I hope unused GND pin on LCD is just a mistake in schematic.

Oh I was messing with the wiring on it, might've accidentally took it off but I don't think it worked with it connected anyways

Twiddle with contrast potentiometer. Uninitialized LCD usually has first row blacked - wrong contrast results into either nothing is visible or all pixels are black or something inbetween. But there is also possibility it's already burned by missing GND connection. Those LCDs are pretty sensitive to miswiring power lines.

Most (all?) pins can deliver (source) 20 mA recommendable ( 40 mA max, but better to stay under 20 mA), and there are also maximums for groups of pins. the 5V pin can handle more (not sure out of my head) but it's in the order of 100's of mA, probably too much for the servo, LCD and especially both together.


text:
Arduino IDE Serial Monitor - how to send NUMBERs - not charcters of numbers
Serial link send and recieves Bytes. Serial monitor at Arduino IDE reads it's input as character.
So if I type '0' in serial monitor, then FW will read byte 48 - I don't want to implement some silly translation from character value to int - I want to input NUMBER as byte into serial monitor - how do I do that?
byte inByte = Serial.read(); // read the incoming byte
if(inByte == 1) // do stuff

use a serial terminal program, such as PuTTY ... or write a terminal sketch in Processing that does what you want

The Serial monitor of the Arduino IDE handles only characters, there is no way to send any byte you like.

It doesn't really matter what you want. You are under the mistaken impression that when you send a string (for example: 3.14159265358) you are sending a number. But you're wrong. Consequently, you will have to "implement some silly translation from character value to int", or learn how to use your available tools to do this for you.

On Linux you may xxd -r -p > /dev/ttyACM0 and then just type hex in the terminal.

instead of finding out the ascii code 49 you can simply write if(inByte == '1') // do stuff

they are all strings, you don't have strong types over serial.

@DataFiddler what if I want to send code with value 10, or 17 - instead of sending one Byte I have to send two bytes.

I was suggesting to question the task you want to achieve. You don' need "silly translations" if you want to recognize single bytes.  I admit, it's hard (OK. IMPOSSIBLE) with all 256 potential byte values. But it's easy to recognize all bytes SerialMonitor can send, without "silly translations".

@DataFiddler hmm, even in that case you limit the entire communication to single bytes only. No floats, no strings, etc.

Based on comments under question no one seems to really know the answer.
So the short answer is: IT'S IMPOSSIBLE - to use Arduino IDE serial monitor to send raw data.
@Edgar_Bonet submitted hint for linux users
@jsotola suggested to use PuTTY, but no additional info on how to do that. Short glance at settings and I couldn't find the way to achieve raw input.
After some additional googling i found some reading where I found program called RealTerm which does the job.
Simply setup your port on Port card and then hit Change button.
On card Display change Display As From ASCII to your prefered format, such as Hex(space)
Then swich on card Send - type your number into input box left to button Send Numbers and press that button
Thats all
The input box accepts decimal value from 0 to 255, or a hexadecimal value, which are prefixed with either a "0x" or a '$'. Each value is separated by space.
Following line is correctly accepted: "255 0xff 0xFF $ff $FF"
Yet another useful tool is Serial Port Monitor. With this you can observe what is really transmitted on line without relying on the interpretation of you application.
Usage is really simple: click white file icon, or Session > New session or press
Ctrl+N
Choose port and vizualizer and click Start monitoring... that's it.
I found most useful mode "Dump view"

I think the comments on your question are quite clear. The important point: any asynchronuous protocoll must include the info either how many bytes are transmitted or which byte is the last one. In "raw data", where each value (0-255) can be a legit data value, there is no way to use bytes for meta data. That's why typically only encoded data is transmitted: you have a small range of byte values that can contain the actual info (alphabet and digits) and you have a bunch of values that are free to be used as meta data. E.g. the commonly used \n as endbyte has the int value 10. How would you transmit the int value 10 in that case?
"I don't want to implement some silly translation from character value to int" - it's not silly, that's the way to go! What about float, boolean or negative values (8-bit, 16-bit, etc.)? You may even want to transmit structured data like python dictionaries. The only way the achieve this is using some kind of parser which knows the protocol.

Another weird but common "protocol" is a timeout, e.g. used in Arduino's Stream::readString().

I think you completely miss my point - I don't care about character transmission. I am creating my on communication protocol with commands, data transfer, responses and such. And if for any reason I want in some place to interpret the byte value as character there is no problem to implement it in my protocol. I just want to debug part of my protocol and inject the raw command. I store my commands as Enumeration, I just begun and have already more than 10 - so treating them as characters is certainly not the way to go.


text:
Esp32 external interrupts sometime is missing
In short. ESP32, two water meters (hot and cold). Booth, hot and cold, some interrupts are missed. When i connect ESP32 to serial monitor and watch then all interrupts are detected (about 5-10 minutes). But if i leave to 5v power only, then some interrupts are missed (in one day it can be up to 50 or even more).
About water counter - one pulse per liter. Correct info about sensor is in PDF Original Operating Instructions.
Sensor connections. Brown wire to GND, white to PIN 32(hot),33(cold).
Board. Olimex ESP32-POE Rev C.

Powered via 5v Samsung phone charger (standard 5V charger without 9v)
WiFi enabled (For NTP and to see counter readings)
OTA enabled
WEB server running (plain html, ESPAsyncWebServer)
Bluetooth disabled
SD card attached (stores SQLite database only)
Uses  siara-cc/esp32_arduino_sqlite3_lib  library

Water usage in last month (May)

hot - 4777 liters (counted with sensor - 2675)
cold - 9289, with sensor - 5528

As we can see, difference is huge. Maybe ISR routine exec time is too long and some interrupts are skipped? I know that WiFi too uses interrupts... Is my interrupt code wrong? Water counter reading is stored in SQLite database when 10 liters are used. Thanks for anyone for your time in advance!
Here is image of water counter and sensor
Here is some code, related to interrupts (debug disabled).
struct WaterCounter
{
  const uint8_t PIN; // microcontroller pin...
  volatile uint32_t liters_total; // max 4294967295
  volatile uint16_t liters_in_session; // max 65535
  volatile uint32_t session_started; // unix timestamp
  volatile uint32_t session_last_pulse; // unix timestamp
  const char display_name[5];
  volatile unsigned long pulse_start;
  volatile unsigned long pulse_stop;
  volatile uint32_t isr_prev_time;
  volatile uint32_t liters_last_written;
  volatile uint32_t liters_used_today;
};
WaterCounter wc_hot =  { PIN_WC_HOT, 0, 0, 0, 0, "Hott", 0, 0, 0, 0, 0 };
WaterCounter wc_cold = {PIN_WC_COLD, 0, 0, 0, 0, "Cold", 0, 0, 0, 0, 0 };
void IRAM_ATTR handle_wc(WaterCounter *wc)
{
  uint32_t  t = micros();
  uint32_t dt = t - wc->isr_prev_time;
  if (dt<1500) return;
  wc->isr_prev_time = t;
  if (wc->pulse_start == 0)
  {
    wc->pulse_start = millis();
    #ifdef DEBUG_ISR
      //Serial.printf("Started %s pulse!\n", wc->display_name);
      ets_printf("Started %s pulse!\n", wc->display_name);
    #endif
  }else
  {
    wc->pulse_stop = millis();
    unsigned long pulsew = wc->pulse_stop - wc->pulse_start;
    wc->pulse_start = 0;
    if (pulsew > 40 && pulsew < 55)
    {
      wc->liters_total++;
      wc->liters_in_session++;
      wc->liters_used_today++;
      if (wc->session_started == 0)
      {
        wc->session_started = now;
      }
      wc->session_last_pulse = now;
    }
    #ifdef DEBUG_ISR
      //Serial.printf("%s: pulse_width: %ld\n", wc->display_name, pulsew);
      ets_printf("%s: pulse_width: %ld\n", wc->display_name, pulsew);
    #endif
  }
}
void IRAM_ATTR isr_wc_cold()
{
  handle_wc(&wc_cold);
}

void IRAM_ATTR isr_wc_hot()
{
  handle_wc(&wc_hot);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Boot...");

  // allow some time to pull up pin, interrupt is attached below
  pinMode(wc_cold.PIN, INPUT_PULLUP);
  pinMode(wc_hot.PIN, INPUT_PULLUP);

  Serial.printf("Watchdog timeout: %dms\n", WATCHDOG_TIMEOUT);
  timerWD = timerBegin(0, 80, true);                  //timer 0, div 80
  timerAttachInterrupt(timerWD, &resetModule, true);  //attach callback
  timerAlarmWrite(timerWD, WATCHDOG_TIMEOUT * 1000, false); //set time in us
  timerAlarmEnable(timerWD); //enable interrupt
  timerWrite(timerWD, 0); //reset timer (feed watchdog)

  SD_MMC.begin();

  enqRC = sqlite3_initialize();
  if (enqRC == SQLITE_OK)
  {
    openDb();
    initSensorDatabase();
    timerWrite(timerWD, 0); //reset timer (feed watchdog)
    SetupWiFi();
    closeDb();
  }
  timerWrite(timerWD, 0); //reset timer (feed watchdog)
  pollNtp();
  timerWrite(timerWD, 0); //reset timer (feed watchdog)

  openDb();
  initTotalValues(&wc_cold);
  timerWrite(timerWD, 0); //reset timer (feed watchdog)
  initTotalValues(&wc_hot);
  closeDb();
  timerWrite(timerWD, 0); //reset timer (feed watchdog)

  attachInterrupt(digitalPinToInterrupt(wc_cold.PIN), &isr_wc_cold, FALLING);
  attachInterrupt(digitalPinToInterrupt(wc_hot.PIN), &isr_wc_hot, FALLING);

  timer_session = timerBegin(1, 80, true);
  timerAttachInterrupt(timer_session, &onSessionTimer, true);
  timerAlarmWrite(timer_session, 1000000, true); // every 1 second
  timerAlarmEnable(timer_session);

  EnableOTA();

  //* async web
  webServer.on("/", HTTP_GET, handleRootAsync);
  webServer.on("/heap", HTTP_GET, heapInfoAsync);
  webServer.on("/post", HTTP_POST, handlePostAsync);
  webServer.on("/params", HTTP_GET, handleParameterPage);
  webServer.onNotFound(onNotFoundAsync);
  webServer.begin();

  time(&now);
}

void loop() {
  // put your main code here, to run repeatedly:
  loop_task();
}
void loop_task()
{
  if (time_every_second <= now)
  {
    writeWcTotalToDb(&wc_cold);
    writeWcTotalToDb(&wc_hot);
    time_every_second = now + 1;
  }

  if (time_every_30_seconds <= now)
  {
    pollNtp();
    time_every_30_seconds = now + 30;
  }
}
void IRAM_ATTR finishSession(WaterCounter *wc, time_t tt)
{
  if (wc->session_started == 0)
  {
    return;
  }
  if (tt - wc->session_last_pulse > SESSION_LENGHT)
  {
    //finish session
    #ifdef DEBUG_ISR
      //Serial.printf("# %s liters in session: %d, duration %d(s)\n", wc->display_name, wc->liters_in_session, wc->session_last_pulse - wc->session_started);
      ets_printf("# %s liters in session: %d, duration %d(s)\n", wc->display_name, wc->liters_in_session, wc->session_last_pulse - wc->session_started);
    #endif

    wc->session_started = 0;
    wc->liters_in_session = 0;
  }
}

/* every 1s  */
void IRAM_ATTR onSessionTimer()
{
  timerWrite(timerWD, 0); //reset timer (feed watchdog)
  //ets_printf("\nonSessionTimer()\n");
  time(&now);
  getLocalTime(&timeinfo);
  strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%d %H:%M:%S", &timeinfo);
  if (now % 86400 == 75600) /* works if this function is called every second */
  {
    ets_printf("\n!!!midnight!!\n");
    wc_cold.liters_used_today = 0;
    wc_hot.liters_used_today = 0;
  }
  finishSession(&wc_cold, now);
  finishSession(&wc_hot, now);
}
void writeWcTotalToDb(WaterCounter *wc)
{
  #ifdef DEBUG_WRITE
    Serial.printf("writeWcTotalToDb(%s): begin\n", wc->display_name);
  #endif

  uint8_t ldiff = wc->liters_total - wc->liters_last_written;
  if (ldiff == 0)
  {
    #ifdef DEBUG_WRITE
      Serial.println("writeWcTotalToDb(): diff zero");
    #endif
    return;
  }
  if (ldiff <= LITERS_BEFORE_WRITE && wc->session_started > 0)
  {
    #ifdef DEBUG_WRITE
      Serial.println("writeWcTotalToDb(): ldiff <= LITERS_BEFORE_WRITE && wc->session_started > 0");
    #endif
    return;
  }
  #ifdef DEBUG_WRITE
    Serial.println("writeWcTotalToDb(): start writting procedure!");
  #endif
  if (!openDb())
  {
    char *sql = "INSERT INTO `water_counter` VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
    sqliteResultCode = sqlite3_prepare_v2(sqliteDb, sql, strlen(sql), &sqliteRes, NULL);
    if (sqliteResultCode != SQLITE_OK)
    {
      #ifdef DEBUG
        Serial.printf("writeWcTotalToDb(): ERROR preparing sql: %d -> %s\n", sqliteResultCode, sqlite3_errmsg(sqliteDb));
      #endif
    }else
    {
      #ifdef DEBUG
        Serial.print("writeWcTotalToDb(): Prepare OK\n");
      #endif
      //getLocalTime(&timeinfo); // inside every 1 sec
      //strftime(timeStringBuff, sizeof(timeStringBuff), "%Y-%m-%d %H:%M:%S", &timeinfo);
      sqlite3_bind_int(sqliteRes, 1, now); // datums
      sqlite3_bind_int(sqliteRes, 2, wc->liters_total);
      sqlite3_bind_text(sqliteRes, 3, timeStringBuff, strlen(timeStringBuff), SQLITE_STATIC);
      sqlite3_bind_text(sqliteRes, 4, wc->display_name, strlen(wc->display_name), SQLITE_STATIC);
      sqlite3_bind_int(sqliteRes, 5, 0);
      sqlite3_bind_int(sqliteRes, 6, wc->liters_in_session);
      sqlite3_bind_int(sqliteRes, 7, wc->session_started);
      sqlite3_bind_int(sqliteRes, 8, 0); /* currently not used */

      if (sqliteResultCode = sqlite3_step(sqliteRes) != SQLITE_DONE)
      {
          #ifdef DEBUG
            Serial.printf("writeWcTotalToDb(): ERROR executing stmt: %d -> %s\n", sqliteResultCode, sqlite3_errmsg(sqliteDb));
          #endif
      }else
      {
          #ifdef DEBUG
            Serial.print("writeWcTotalToDb(): data saved!\n");
          #endif
          wc->liters_last_written = wc->liters_total;
          sqlite3_clear_bindings(sqliteRes);
          sqliteResultCode = sqlite3_reset(sqliteRes);
          if (sqliteResultCode != SQLITE_OK)
          {
            #ifdef DEBUG
              Serial.printf("writeWcTotalToDb(): sqlite3_reset(res) result code = [%s] %s\n", sqliteResultCode, sqlite3_errmsg(sqliteDb));
            #endif
          }else
          {
            #ifdef DEBUG
              Serial.print("writeWcTotalToDb(): sqlite3_reset(res) OK\n");
            #endif
          }
          sqlite3_finalize(sqliteRes);
      }
    }
    closeDb();
  }else
  {
    #ifdef DEBUG
      Serial.println("writeWcTotalToDb(): Failed to open database!");
    #endif
  }
  #ifdef DEBUG_WRITE
    Serial.printf("writeWcTotalToDb(%s): finished!\n", wc->display_name);
  #endif
} /* writeWcTotalToDb() */

You should switch to using the "pulse counter" peripheral in the ESP32. Read more here: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html

Trying it tomorrow

@Majenko: can that be used with Arduino?

a binary counter IC would make reliability easy, but if there's a built-in counter we can use, that's even better.

Yes. Arduino used the IDF to control the chip. You'd just be skipping the Arduino layer and calling the IDF directly.

I tried pcnt (with arduino). It works with one input pin, but until no i cannot get to work with two different inputs (for  each water meter). As i understood, i must start two pcnt instances..

Maybe someone knows how to get channel number in pcnt_isr_register handler?

As @Majenko suggested, i created solution with pulse counter.
Here is working code, based on espressif PCNT Example. Arduino studio, Olimex ESP32-POE board.
Each water meter uses separate pulse counter unit. Now I am testing this code and after several days i will accept answer if all works like i want :)
#include "freertos/queue.h"
#include "driver/pcnt.h"
#include "driver/periph_ctrl.h"
#include "driver/gpio.h"
#include "esp_attr.h"

#define PCNT_H_LIM_VAL      1
#define PCNT_L_LIM_VAL     -1
#define PCNT_THRESH1_VAL    0
#define PCNT_THRESH0_VAL   -0
#define PCNT_INPUT_SIG_WC_HOT   32 // hot water counter
#define PCNT_INPUT_SIG_WC_COLD  33 // cold water counter
/*
Cold meter uses PCNT_UNIT_1
hot meter uses PCNT_UNIT_0
*/
xQueueHandle pcnt_evt_queue;   // A queue to handle pulse counter events
pcnt_isr_handle_t user_isr_handle = NULL; //user's ISR service handle

/* A sample structure to pass events from the PCNT
 * interrupt handler to the main program.
 */
typedef struct {
    pcnt_unit_t unit;  // the PCNT unit that originated an interrupt
    uint32_t status; // information on the event type that caused the interrupt
} pcnt_evt_t;

/* Decode what PCNT's unit originated an interrupt
 * and pass this information together with the event type
 * the main program using a queue.
 */
static void IRAM_ATTR pcnt_example_intr_handler(void *arg)
{
    uint32_t intr_status = PCNT.int_st.val;
    int i;
    pcnt_evt_t evt;
    portBASE_TYPE HPTaskAwoken = pdFALSE;

    for (i = 0; i < PCNT_UNIT_MAX; i++) {
        if (intr_status & (BIT(i))) {
            evt.unit = (pcnt_unit_t)i;
            /* Save the PCNT event type that caused an interrupt
               to pass it to the main program */
            evt.status = PCNT.status_unit[i].val;
            PCNT.int_clr.val = BIT(i);
            xQueueSendFromISR(pcnt_evt_queue, &evt, &HPTaskAwoken);
            if (HPTaskAwoken == pdTRUE) {
                portYIELD_FROM_ISR();
            }
        }
    }
}

/* Initialize PCNT functions:
 *  - configure and initialize PCNT
 *  - set up the input filter
 *  - set up the counter events to watch
 */
static void pcnt_example_init()
{
    //Serial.printf("pcnt_example_init(%d, %d)\n", _unit, _pin);
    /* Prepare configuration for the PCNT unit */
    pcnt_config_t pcnt_config = {};
    pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_WC_HOT;
    pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED;
    pcnt_config.channel = PCNT_CHANNEL_0;
    pcnt_config.pos_mode = PCNT_COUNT_INC;
    pcnt_config.neg_mode = PCNT_COUNT_DIS;
    pcnt_config.lctrl_mode = PCNT_MODE_KEEP;//PCNT_MODE_REVERSE;
    pcnt_config.hctrl_mode = PCNT_MODE_KEEP;
    pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
    pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;
    pcnt_config.unit = PCNT_UNIT_0;

    /* Initialize PCNT unit */
    ESP_ERROR_CHECK(pcnt_unit_config(&pcnt_config));

    /* cold water meter */
    pcnt_config.pulse_gpio_num = PCNT_INPUT_SIG_WC_COLD;
    pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED;
    pcnt_config.channel = PCNT_CHANNEL_0;
    pcnt_config.pos_mode = PCNT_COUNT_INC;
    pcnt_config.neg_mode = PCNT_COUNT_DIS;
    pcnt_config.lctrl_mode = PCNT_MODE_KEEP;//PCNT_MODE_REVERSE;
    pcnt_config.hctrl_mode = PCNT_MODE_KEEP;
    pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
    pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;
    pcnt_config.unit = PCNT_UNIT_1;
    ESP_ERROR_CHECK(pcnt_unit_config(&pcnt_config));

    /* Configure and enable the input filter */
    ESP_ERROR_CHECK(pcnt_set_filter_value(PCNT_UNIT_0, 1000)); // filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
    ESP_ERROR_CHECK(pcnt_filter_enable(PCNT_UNIT_0));

    /* Set threshold 0 and 1 values and enable events to watch */
    ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_1));
    ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_0, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_THRES_0));
    /* Enable events on zero, maximum and minimum limit values */
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_ZERO));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_H_LIM));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_0, PCNT_EVT_L_LIM));

    /* Initialize PCNT's counter */
    ESP_ERROR_CHECK(pcnt_counter_pause(PCNT_UNIT_0));
    ESP_ERROR_CHECK(pcnt_counter_clear(PCNT_UNIT_0));

    /* Register ISR handler and enable interrupts for PCNT unit */
    ESP_ERROR_CHECK(pcnt_isr_register(pcnt_example_intr_handler, NULL, 0, &user_isr_handle));
    ESP_ERROR_CHECK(pcnt_intr_enable(PCNT_UNIT_0));

    /* Everything is set up, now go to counting */
    ESP_ERROR_CHECK(pcnt_counter_resume(PCNT_UNIT_0));

    /* PCNT_UNIT_1 configuration  */
    /* Configure and enable the input filter */
    ESP_ERROR_CHECK(pcnt_set_filter_value(PCNT_UNIT_1, 1000)); // filter_val is a 10-bit value, so the maximum filter_val should be limited to 1023.
    ESP_ERROR_CHECK(pcnt_filter_enable(PCNT_UNIT_1));

    /* Set threshold 0 and 1 values and enable events to watch */
    ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_1, PCNT_EVT_THRES_1, PCNT_THRESH1_VAL));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_THRES_1));
    ESP_ERROR_CHECK(pcnt_set_event_value(PCNT_UNIT_1, PCNT_EVT_THRES_0, PCNT_THRESH0_VAL));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_THRES_0));
    /* Enable events on zero, maximum and minimum limit values */
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_ZERO));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_H_LIM));
    ESP_ERROR_CHECK(pcnt_event_enable(PCNT_UNIT_1, PCNT_EVT_L_LIM));

    /* Initialize PCNT's counter */
    ESP_ERROR_CHECK(pcnt_counter_pause(PCNT_UNIT_1));
    ESP_ERROR_CHECK(pcnt_counter_clear(PCNT_UNIT_1));

    ESP_ERROR_CHECK(pcnt_intr_enable(PCNT_UNIT_1));

    /* Everything is set up, now go to counting */
    ESP_ERROR_CHECK(pcnt_counter_resume(PCNT_UNIT_1));
}

void setup() {
  Serial.begin(115200);
  Serial.println("Boot...");
  // put your setup code here, to run once:
  pinMode(PCNT_INPUT_SIG_WC_HOT, INPUT_PULLUP);
  pinMode(PCNT_INPUT_SIG_WC_COLD, INPUT_PULLUP);
  /* Initialize PCNT event queue and PCNT functions */
  pcnt_evt_queue = xQueueCreate(10, sizeof(pcnt_evt_t));

  pcnt_example_init();
  //  pcnt_example_init(PCNT_UNIT_WC_HOT, PCNT_INPUT_SIG_WC_HOT);
    //pcnt_example_init(PCNT_UNIT_WC_COLD, PCNT_INPUT_SIG_WC_COLD);

    Serial.printf("Setup done\n");
}

int16_t count = 0;
pcnt_evt_t evt;
portBASE_TYPE res;

char * chToName(int ch)
{
  if (ch == 1) return "Cold";
  if (ch == 0) return "Hot";

  return "Unc";
}

void loop() {
  // put your main code here, to run repeatedly:
      /* Wait for the event information passed from PCNT's interrupt handler.
         * Once received, decode the event type and print it on the serial monitor.
         */
        res = xQueueReceive(pcnt_evt_queue, &evt, 1000 / portTICK_PERIOD_MS);
        if (res == pdTRUE) {
            pcnt_get_counter_value(evt.unit, &count);
            Serial.printf("Event PCNT unit[%d=%s]; cnt: %d, status: %d\n", evt.unit, chToName(evt.unit), count, evt.status);
            if (evt.status & PCNT_EVT_THRES_1) {
                Serial.printf("THRES1 EVT\n");
            }
            if (evt.status & PCNT_EVT_THRES_0) {
                Serial.printf("THRES0 EVT\n");
            }
            if (evt.status & PCNT_EVT_L_LIM) {
                Serial.printf("L_LIM EVT\n");
            }
            if (evt.status & PCNT_EVT_H_LIM) {
                Serial.printf("H_LIM EVT\n");
            }
            if (evt.status & PCNT_EVT_ZERO) {
                Serial.printf("ZERO EVT\n");
                // here we are increment liter count
            }
        } else {
            pcnt_get_counter_value(PCNT_UNIT_0, &count);
            Serial.printf("Current counter value: %s=%d,", chToName(PCNT_UNIT_0), count);
            pcnt_get_counter_value(PCNT_UNIT_1, &count);
            Serial.printf(" %s=%d\n", chToName(PCNT_UNIT_1), count);
            //pcnt_get_counter_value(PCNT_UNIT_WC_COLD, &count);
            //Serial.printf(", %d on unit: %d\n", count, PCNT_UNIT_WC_COLD);
        }

        /*
        if(user_isr_handle) {
          Serial.printf("Clearing user_isr_handle\n");
          //Free the ISR service handle.
          esp_intr_free(user_isr_handle);
          user_isr_handle = NULL;
        }*/
}

You can use Pulse Counter(PCNT) feature in ESP32 to count the number of pulse in background, Its also possible to configure event when number of counts reached certain threshold and had lot of options,
For get information and available Interfaces and API's for Pulse Counter(PCNT) please follow below link, https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/pcnt.html

Initially I faced lot of issue to make Pulse Counter(PCNT) work in Adrino IDE for ESP-32, After multiple attempt I make it working, And same  sample code is uploaded in GitHub for reference. I have not use all the API's in the official documentation but but used few of them and are working..

I have created a simple sample program for a water flow meter, there also we use to get pulse which needs to count to measure the water flow rate.
GitHub Sample code Path:- https://github.com/Embedded-Linux-Developement/Arduino_Sample_Programs/tree/main/ESP_32/Water_Flow_Pulse_counter_WithOut_Interrupt_Using_PCNT
I have not placing the code here, because its there in GitHub and a simile one and can use it. Its a working code I tested in ESP32 HW.
Hopes Its helpful,
Regards, Jerry James


text:
Matrix and State Space Arduino Implementation
I wrote an Arduino Matrix class. Then I used this class to implement State Space on Arduino.
During tests I stomped upon a problem. After starting the program it stops at some point. I have no idea why this is happening. There are no error messages.
Can you please tell me what im doing wrong?
Here is my code:
//"Matrix.h"
#ifndef _Matrix_h
#define _Matrix_h

#if defined(ARDUINO) && ARDUINO >= 100
    #include "arduino.h"
#else
    #include "WProgram.h"
#endif
class Matrix
{
private:
    unsigned row_number = 0;
    unsigned column_number = 0;
    double* elems;

public:

    //Constructors + Destructor
    Matrix();
    Matrix(double, unsigned row_number = 1, unsigned column_number = 1);
    Matrix(double*, unsigned row_number = 1, unsigned column_number = 1);
    Matrix(const char*);
    Matrix(const Matrix&);
    void operator=(Matrix);
    ~Matrix();

    //Comunication Methods
    unsigned get_rows() const { return row_number; };
    unsigned get_columns() const { return column_number; };
    double& operator()(const unsigned row, const unsigned column);
    double valueAt(unsigned row, unsigned column) const ;
    void print() const;
    bool mRead2();

    //Matrix Operations
    Matrix operator+(Matrix);
    Matrix operator-(Matrix);
    Matrix operator*(Matrix);
    Matrix transpose();

    //Scalar Operations
    Matrix operator+(double);
    Matrix operator-(double);
    Matrix operator*(double);
    Matrix operator/(double);

};
Matrix mRead(unsigned row,unsigned column);
#endif

//"Matrix.cpp"

#include "Matrix.h"
Matrix::Matrix() {
  row_number = 0;
  column_number = 0;
  elems = new double[0];
}
Matrix::Matrix(double val, unsigned row_number, unsigned column_number) {
  this->row_number = row_number;
  this->column_number = column_number;
  elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i < row_number * column_number + 1; i++)
    elems[i] = val;

}

Matrix::Matrix(double* elems, unsigned row_number, unsigned column_number)
{
  this->column_number = column_number;
  this->row_number = row_number;
  this->elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i < row_number * column_number + 1; i++)
    this->elems[i] = elems[i - 1];
}

Matrix::Matrix(const char*)
{

}

void Matrix::operator=(Matrix A){
  this->column_number = A.get_columns();
  this->row_number = A.get_rows();
  this->elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i <= row_number; i++)
    for (unsigned j = 1; j <= column_number; j++)
      this->elems[(i - 1) * (column_number) + j] =  A.valueAt(i, j);

}

Matrix::Matrix(const Matrix& A) {
  this->column_number = A.get_columns();
  this->row_number = A.get_rows();
  elems = new double[row_number * column_number + 1];
  for (unsigned i = 1; i <= row_number; i++)
    for (unsigned j = 1; j <= column_number; j++)
      this->elems[(i - 1) * (column_number) + j] =  A.valueAt(i, j);

}

Matrix::~Matrix()
{
  delete[] elems;
}

double& Matrix::operator()(const unsigned row, const unsigned column)
{

    return this->elems[(row - 1) * (column_number) + column ];

}

double Matrix::valueAt(unsigned row, unsigned column) const
{

    return this->elems[(row - 1) * (column_number) + column ];

}

void Matrix::print() const
{
  for (unsigned i = 1; i <= get_rows(); i++) {
    for (unsigned j = 1; j <= get_columns(); j++) {
      Serial.print(this->valueAt(i, j));
      Serial.print(" ");
      Serial.flush();
    }
    Serial.print("\n");
  }
}
Matrix mRead(unsigned row, unsigned column) {
  int sizeM = row * column;
  double m[sizeM];
  char buffor[64];
  for (int i = 0; i < 64; i++) {
    buffor[i] = 0;
  }
  for (int i = 0; i < sizeM; i++) {m[i]=0;}
  for (int i = 0; i < sizeM; i++) {
    while (!Serial.available()) {
      Serial.write(32);
    }
    int j = 0;
    while (Serial.available() > 0) {
      Serial.println(Serial.available());
      buffor[j] = Serial.read();
      j++;
      Serial.flush();
    }
    m[i] = (double)atof(buffor);
    Serial.flush();
    //for (int i = 0; i < 64; i++) {
    //  buffor[i] = 0;
    //}
  }
  return Matrix(m, row, column);
}
bool Matrix::mRead2() {
  int sizeM = row_number * column_number;
  double m[sizeM];
  char buffor[64];
  for (int i = 0; i < 64; i++) {
    buffor[i] = 0;
  }
  for (int i = 0; i < sizeM; i++) {m[i]=0;}
  for (int i = 0; i < sizeM; i++) {
    while (!Serial.available()) {
      Serial.write(32);
    }
    int j = 0;
    while (Serial.available() > 0) {
      Serial.println(Serial.available());
      buffor[j] = Serial.read();
      j++;
      Serial.flush();
    }
    m[i] = (double)atof(buffor);
    Serial.flush();
    for (int i = 0; i < 64; i++) {
      buffor[i] = 0;
    }
  }
  *this=Matrix(m,row_number,column_number);
  return true;
}
Matrix Matrix::operator+(Matrix A)
{
    Matrix sum = Matrix(0.0, row_number, column_number);
    for (unsigned i = 1; i <= row_number; i++)
      for (unsigned j = 1; j <= column_number; j++)
        sum(i, j) = A.valueAt(i, j) + this->valueAt(i, j);

    return sum;
}

Matrix Matrix::operator-(Matrix A)
{
    Matrix diff = Matrix(0.0, row_number, column_number);
    for (unsigned i = 1; i <= row_number; i++)
      for (unsigned j = 1; j <= column_number; j++)
        diff(i, j) = A.valueAt(i, j) + this->valueAt(i, j);
    return diff;

}

Matrix Matrix::operator*(Matrix A)
{
  Matrix mult = Matrix(0.0, row_number, A.get_columns());
    double temp;
    for (unsigned i = 1; i <= row_number; i++) {
      for (unsigned j = 1; j <= A.get_columns(); j++) {
        temp = 0.0;
        for (unsigned k = 1; k <= column_number; k++)
          temp += this->valueAt(i, k) * A(k, j);
        mult(i, j) = temp;
      }
    }

    return mult;
}

Matrix Matrix::transpose() {
  Matrix transpose = Matrix(0.0, row_number, column_number);
  for (unsigned i = 1; i <= row_number; i++) {
    for (unsigned j = 1; j <= column_number; j++) {
      transpose(i, j) = this->valueAt(j, i);
    }
  }
  return transpose;
}

Matrix Matrix::operator+(double x)
{
  Matrix A = Matrix(x, row_number, column_number);
  return *this + A;
}

Matrix Matrix::operator-(double x)
{
  Matrix A = Matrix((-1) * x, row_number, column_number);
  return *this + A;
}

Matrix Matrix::operator*(double x)
{
  Matrix A = Matrix(*this);
  for (unsigned i = 1; i <= row_number; i++)
    for (unsigned j = 1; j <= column_number; j++)
      A(i, j) = this->valueAt(i, j) * x;
  return A;

}

Matrix Matrix::operator/(double x)
{
  if (x != 0) {
    Matrix A = Matrix(*this);
    for (unsigned i = 1; i <= row_number; i++)
      for (unsigned j = 1; j <= column_number; j++)
        A(i, j) = this->valueAt(i, j) / x;
    return A;
  }
  else {} //throw "Dividing by zero";
}

//"StateSpace.h"

#ifndef _StateSpace_h
#define _StateSpace_h
#include "C:\Users\Wojciech Trybulec\Desktop\Test\Matrix.h"
class StateSpace
{
private:
    Matrix State;
    Matrix A;
    Matrix B;
    Matrix C;
    Matrix D;
    Matrix Out;
public:

    //Constructors + Destructor
    StateSpace();
    StateSpace(Matrix A, Matrix B, Matrix C, Matrix D);
    StateSpace(Matrix A, Matrix B, Matrix C, Matrix D,Matrix InitState);
    StateSpace(const StateSpace&);
    StateSpace operator=(StateSpace);
    ~StateSpace();

    //Comunication Methods
    Matrix get_states() const;
    Matrix get_output() const;
    Matrix* get_all() const;
    void calculate(Matrix Signal);
    void print_states() const;
    void print_output() const;
    void print_matrices() const;

};
#endif

//"StateSpace.cpp"
#include "C:\Users\Wojciech Trybulec\Desktop\Test\Matrix.h"
#include "StateSpace.h"
StateSpace::StateSpace() {
    A = Matrix();
    B = Matrix();
    C = Matrix();
    D = Matrix();
    State = Matrix();
    Out = Matrix();
}
StateSpace::StateSpace(Matrix A, Matrix B, Matrix C, Matrix D) {
    this->A = A;
    this->B = B;
    this->C = C;
    this->D = D;
    this->State = Matrix(0.0,A.get_columns(),1);
    this->Out = Matrix(0.0, C.get_rows(), 1);
}
StateSpace::StateSpace(Matrix A,Matrix B, Matrix C, Matrix D,Matrix InitState){
    this->A = A;
    this->B = B;
    this->C = C;
    this->D = D;
    this->State = InitState;
    this->Out = Matrix(0.0, C.get_rows(), 1);
}
StateSpace::StateSpace(const StateSpace& ss) {
    this->A = ss.get_all()[0];
    this->B = ss.get_all()[1];
    this->C = ss.get_all()[2];
    this->D = ss.get_all()[3];
    this->State = ss.get_all()[4];
    this->Out = ss.get_all()[5];
}
StateSpace StateSpace::operator=(StateSpace ss) {
    this->A = ss.get_all()[0];
    this->B = ss.get_all()[1];
    this->C = ss.get_all()[2];
    this->D = ss.get_all()[3];
    this->State = ss.get_all()[4];
    this->Out = ss.get_all()[5];
}
StateSpace::~StateSpace() {
    delete this;
    //A.~Matrix;
    //B.~Matrix;
    //C.~Matrix;
    //D.~Matrix;
    //State.~Matrix;
    //Out.~Matrix;
}

Matrix StateSpace::get_states() const {
    return this->State;
}
Matrix StateSpace::get_output() const{
    return this->Out;
}
Matrix* StateSpace::get_all() const {
    Matrix all[6];
    all[0] = A;
    all[1] = B;
    all[2] = C;
    all[3] = D;
    all[4] = State;
    all[5] = Out;
    return all;

}
void StateSpace::calculate(Matrix Signal) {
    State = ((A * State) + (B * Signal));
    Out = ((C * State) + (D * Signal));
}
void StateSpace::print_states() const {
    State.print();
}
void StateSpace::print_output() const {
    Out.print();
}
void StateSpace::print_matrices() const {
    A.print();
    B.print();
    C.print();
    D.print();
}

And this Arduino sketch that im using for testing:
#include "Matrix.h"
#include "StateSpace.h"
double a[4]={-0.5,0,0,0.7};
double b[2]={1,2};
double c[4]={1,0,0,1};
double d = 0;
Matrix A=Matrix(a,2,2);
Matrix B=Matrix(b,2,1);
Matrix C=Matrix(c,2,2);
Matrix D=Matrix(d,1,1);
Matrix x=Matrix(0.0,2,1);
Matrix U=Matrix(1.0,1,1);
StateSpace ss=StateSpace(A,B,C,D);
void setup()
{
  Serial.begin(9600);
}
void loop() {
  ss.calculate(U);
  x=ss.get_states();
  Serial.print(x.valueAt(1,1));
  Serial.print("\t");
  Serial.println(x.valueAt(2,1));

  delay(100);
}

I really hope that you can help me

I would say the dynamic memory allocation is the culprit. Everytime you create a Matrix, you are allocating dynamic memory. And you are creating a lot of matrices. Even when deleting everthing correctly, you are making swiss cheese out of your memory, aka heap fragmentation. Rewrite your code to not use dynamic allocation

What the hell is this: delete this;? Are you trying to make recursion inside of destructor? Also forget this->, there is no need for it - it's not PHP

Btw, after longer look at that code - it's really bad. It could be much shorter, also bit faster as it's doing lots actions twice and even more.

This is not a solution (meaning to pinpoint the exact problem), but to find out yourself.
There are mainly two ways to debug this:

On Arduino: Try placing Serial.print statements to see where it stops (like putting them on the beginning of every function, or on other 'strategic' places. When you found which function stops, try putting print statements within. So within two 'runs' you can find which line is causing the problem. What I normally do is just number the print statements, e.g. function 1 you print values 100..200, next function 200.300 etc. So you can easily leave them for later reusage (just comment them out).
Unit test on PC: If you didn't already do, test your class on a PC... this will give you much better debugging tools than an Arduino. When you know the class itself work, create a small test sketch on the Arduino (but high likely it will work, unless you made a mistake in the test sketch). For a PC, consider writing a so-called unit-test ... so even later when you change something, you can test you didn't break anything else.

In both cases (if you start on PC also do this), check for memory usage. The Arduino has only 2 KB SRAM, on a PC you can already check how much is used. The SRAM usage shown during compiling only takes into account global variables. It does not take into account:

Local variables
Dynamic variables (made with new, malloc)
Stack (passed parameters).

During PC debuging I noticed that it keeps using more and more memory. It probably doesnt destroy created objects. Could you please tell me how to fix this or at least give me some tips?

I didn't look good enough, I see a lot of new statements which create dynamic variables. These are not counted. I don't have a quick fix, but for an Arduino with only 2 KB SRAM it's very unrecommendable to use dynamic memory (there are a few exceptions). Also when you assign or pass parameters, maybe those (copy?) constructors are used, creating a copy (maybe temporarily).  But sometimes you might need a copy (if you want to keep the original). That's hard to say, since I don't know  your requirements.

I added delete [] elems in operator=. It solved my problem. Thanks a lot for help.

Great you found it (yourself) ... wonder why this didn't show up in Windows ... however, stay warned for memory issues.

@sanX you should read something about Rule of Three / Rule of Five. You'll find out adding delete into copy assigment operator and destructor is not enough.


text:
Trying a crude water level sensor
first of all, Im from Cuba, that means I may have some problems to find parts...
I have a little system to measure the water level in my house water tank. The system is pretty rough: a proximity sensor HC-SR04 well fixed in the top of the tank, some long wires to an ArduinoNano, and a LCD screen where I display information as: water level in liters and in %.
The problem is the proximity sensor HC-SR04 seems to be broken now, not work at all and I was thinking in replace it by raw cables
Something like in the image below, but maybe with more steps:

So... My questions are:
-Is this posible? I just test it with a glass of water and two short wires and it work, but sometimes it throw me some falses-positives... It may be my code: just light on a led if digitalpin X is high when I put two wires in the water (1 wire to arduino 5V pin and the other to the digitalpin I wanna check if is high), and it do it, but when I pull out the wires the led stay on for more than a few seconds.
-If it is posible, how long can be the wire? Is 10m ok?
Thanks

have you thought of using a float?

Hi @jsotola, how can I connect the float to the arduino in order to show the level tank in a display?

You need large pulldown resistors to prevent the input signal from floating.

@k.Cyborg I'm thinking of a pulley mounted high above the tank ... cable over the pulley ... a weight atached to each end of the cable ... one weight heavier than the other ... the heavier weight inside the tank attached to a float .... the lighter weight outside of the tank .... code disk on the pulley

Several years ago I tried something similar for the company I worked at that time. Since DC (direct current) lets the electrodes corrode faster, we used AC (alternating current) with a rectangular wave form. Sounds scientific, but it was simply done by changing between VCC and GND. The current through the water is different from the current through air, and it can be detected. You might need some analogue circuitry, though, before you can attach your Arduino. However, I don't recall any experiences how long this worked.

make sure to only turn on the 5v when measuring to prevent corrosion. I would read with analog instead of digital, so you get a feel of the values you should be expecting. I would take about 5 samples, sort them, throw away the highest and lowest, the avg the middle 3 to get a stable reading that doesn't jump around from EMI.

As others have said, you need to make sure you have pull-up or pull-down resistors on all digital inputs so their value doesn't "float" (fluctuate between high and low.)
Given that water tanks and wells tend to be strongly earth grounded, I would suggest some changes:
Change the common wire to a ground, not +5V
Change all of your other pins to analog inputs. Connect them to high ohm pull-up resistors (say 10kΩ). They will read a full 5V when their ends are not in water. When the water rises and the ends dip into the water, their voltages will drop. Use analog readings to detect those voltage drops.
You could also use something like graphite a pair of graphite rods in the water, and a voltage divider circuit. As the water level rises, the current would travel through less graphite, and the resistance would drop. I don't know if that would give you enough top-to-bottom measuring distance.

You can also create a capacitive sensor using aluminium foil and plastic piping. https://www.instructables.com/id/Capacitive-Fluid-Level-Sensor/

I sort of stumbled on how to determine the depth of my outside fish pond, about 1.5 meters. I run a air pump to oxygenate the water for the fish and fitted it with a sensitive pressure transducer. I put a meter reading the pressure and added analog alarm set points. I noticed the first summer as the water went down so did the pressure, conversely when the water rose the pressure rose. With some experimenting I was able to determine the water level. The pond is outside, the air pump is in basement with an outside air inlet because of the cold temperatures. It has been operational 5 years


text:
Serial Hangs with multiple PN532 nfc reader and a TCA9548A
I am trying to use multiple PN532 reader. I have put all my readers on a multiplexer (TCA9548A).
The script works well, but when I move my tags on readers sometimes the serial says to me there is an error on reading tag like that : Read failed [number] or like Error. Failed read page [number] where [number] is a Integer.
And sometimes the serial completely hangs and not sends anything anymore, I have to reset the arduino by pressing the reset button.
Other information :
Arduino : My arduino is a Mega.
Here is my code :
#include <Wire.h>
#include <PN532_I2C.h>
#include <PN532.h>
#include <NfcAdapter.h>

#define TCAADDR 0x70

#define RST_PIN 2

PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);

int NB_NFC_READER = 4;

void tcaselect(uint8_t i)
{
  if (i > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();
}

void setup(void)
{
    while (!Serial);
    delay(250);

    Wire.begin();

    // Serial.begin(115200);
    Serial.begin(9600);

    //Serial.println("NDEF Reader");

    /**Initialisation des lecteurs NFC*/
    for(int i = 0 ; i < NB_NFC_READER ; i++)
    {
      //Serial.println("CONFIGURATION DU READER N° " + String(i));
      tcaselect(i);
      nfc.begin();
    }

    pinMode(RST_PIN, INPUT);
    digitalWrite(RST_PIN, HIGH);

    Serial.println("SETUP OK !");
}

void loop(void)
{
  String tag0;
  String tag1;
  String tag2;
  String tag3;

    for(int i = 0 ; i < NB_NFC_READER ; i++)
    {
      //Serial.println("FOR INDEX : " + String(i));
      tcaselect(i);
      if (nfc.tagPresent(100))
      {
          NfcTag tag = nfc.read();
          //tag.print();
          if(i == 0)
          {
            tag0 = tag.getUidString();
          }
          if(i == 1)
          {
            tag1 = tag.getUidString();
          }
          if(i == 2)
          {
            tag2 = tag.getUidString();
          }
          if(i == 3)
          {
            tag3 = tag.getUidString();
          }
          //Serial.println("LECTURE SUR LECTEUR " + tag.getUidString());
          delay(100);
      }
    }
    Serial.print("[");
    Serial.print("{\"tag0\":");Serial.print("\"");Serial.print(tag0);Serial.print("\"},");
    Serial.print("{\"tag1\":");Serial.print("\"");Serial.print(tag1);Serial.print("\"},");
    Serial.print("{\"tag2\":");Serial.print("\"");Serial.print(tag2);Serial.print("\"},");
    Serial.print("{\"tag3\":");Serial.print("\"");Serial.print(tag3);Serial.print("\"}");
    Serial.println("]");
}

Thank you for reading, I hope someone will find why the serial freeze like that.

Set debiggung to verbose in the IDE, maybe this reveals some more info. It's unlikely that the actual serial output of the atmega freezes. I guess, either the sketch hangs somewhere else or it is the software on the frontend failing


text:
MAX9611/2 - receiving junk data
I'm connecting to a MAX9611 on a custom PCB (using a SAMD Cortex M0 running an Adafruit Feather bootloader) using I2C. I have code that reads the voltage, current and temperature from the internal registers, but I'm receiving junk data from the voltage and current registers. Temperature works reliably.
Sometimes voltage and current are 0. Sometimes voltage is 10x what it should be (that's the raw ADC value - this isn't a conversion bug). The current reading depends on whether the temperature request is commented out or not.
I've been reading through the documentation for a day now and can't see what I'm doing wrong. The kicker is that the code to request the register data is essentially identical (just pointing at different registers) between the working temperature request and the non-working voltage and current requests. I have posted it below, along with the relevant schematic section - does anyone have any ideas what I'm doing wrong?
Thanks!
#include <Wire.h>

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

void loop()
{
  Serial.print("mV:   ");  Serial.println(get_MAX9611_voltage());
  Serial.print("mA:   ");  Serial.println(get_MAX9611_current());
  Serial.print("Temp: ");  Serial.println(get_MAX9611_temp());
  Serial.println();
  delay(1000);
}

uint16_t get_MAX9611_voltage (void)
{
  Wire.beginTransmission(0x70);
  Wire.write(0x0A);                             //Select control register 1
  Wire.write(0x03);                             //Set mux to read from RS+
  Wire.endTransmission();

  Wire.beginTransmission(0x70);
  Wire.write(0x02);                             //Select RS+ data register MSB
  Wire.endTransmission();

  Wire.requestFrom(0x70,2);
  uint8_t msb = Wire.read();                    //Read RS+ MSB
  uint8_t lsb = Wire.read();                    //Read RS+ LSB

  uint16_t MAX9611_voltage = word(msb,lsb);
  MAX9611_voltage = MAX9611_voltage >> 4;       //shift right by 4 due to 12 bit value
  MAX9611_voltage = MAX9611_voltage*14;       //57.3V full scale, 14mV per ADC step

  return MAX9611_voltage;
}

uint16_t get_MAX9611_current (void)
{
  Wire.beginTransmission(0x70);
  Wire.write(0x0A);                             //Select control register 1
  Wire.write(0x02);                             //Set mux to read from current sense amplifier with gain 8x, full scale = 55mV
  Wire.endTransmission();

  Wire.beginTransmission(0x70);
  Wire.write(0x00);                             //Select CSA data register MSB
  Wire.endTransmission();

  Wire.requestFrom(0x70,2);
  uint8_t msb = Wire.read();                    //Read CSA MSB
  uint8_t lsb = Wire.read();                    //Read CSA LSB

  uint16_t MAX9611_current = word(msb,lsb);

  MAX9611_current = MAX9611_current >> 4;       //shift right by 4 due to 12 bit value
  MAX9611_current = (MAX9611_current*0.01342)*5;  //ADC value in millivolts, I=V/R where R is 0.2

  return MAX9611_current;
}

int16_t get_MAX9611_temp (void)
{
  Wire.beginTransmission(0x70);
  Wire.write(0x0A);                             //Select control register 1
  Wire.write(0x06);                             //Set mux to read from temp sensor
  Wire.endTransmission();

  Wire.beginTransmission(0x70);
  Wire.write(0x08);                             //Select temp data register MSB
  Wire.endTransmission();

  Wire.requestFrom(0x70,2);
  uint8_t msb = Wire.read();                    //Read temp MSB
  uint8_t lsb = Wire.read();                    //Read temp LSB

  int16_t MAX9611_temp = word(msb,lsb);
  MAX9611_temp = (((MAX9611_temp >> 7) * 480)/1000);                     //shift right by 7 due to 9 bit value, LSB is 480mC

  return MAX9611_temp;
}

That didn't take long to find the bug... Continuous read mode requires 2ms pause between each ADC read. I'm reading far faster than that, especially considering my micro is far faster than the 8 bit 328s that many other examples use. I added 2ms delay between reads and the problem seems to have disappeared, although I will have to check the current measurements when I have access to better equipment.

Happens to me too occasionally, that after writing a post searching for a bug for a long time, I find it myself shortly afterwards. Good that you posted the answer to help others with similar problems.


text:
Arduino Due SPI clock pauses each octet
I'm trying to communicate with SPI slave using Arduino DUE as master. Device requires commands to be 32 bit wide, SPI mode 3.
I've ran the minimum code (using Arduino IDE 1.8.12) to send some 32 bit wide nonsense, and I've noticed that clock stops for a while after each octet is sent. Also the pause after CS goes LOW is too long.
What is the best practice to achieve a clean 32 bit wide transmission?
#include <SPI.h>

const int cs_pin = 25;
const SPISettings spi_settings(2000000, MSBFIRST, SPI_MODE3);
uint8_t tx_buffer[4];

void setup() {
  pinMode(cs_pin, OUTPUT);
  SPI.begin();
}

void loop() {
  tx_buffer[0] = 0xDE;
  tx_buffer[1] = 0xAD;
  tx_buffer[2] = 0xBE;
  tx_buffer[3] = 0xEF;

  SPI.beginTransaction(spi_settings);
  digitalWrite(cs_pin, LOW);
  SPI.transfer(tx_buffer, 4);
  digitalWrite(cs_pin, HIGH);
  SPI.endTransaction();
}

SCLK - CH1 (Yellow)
CS - CH3 (Purple)
MOSI - CH4 (Blue)

Expected signal:

Noticed timing states it's actually 40, not 32 bits, but that doesn't seem to affect the question.

The SPI data register is only 8 bits wide.  So you have to have some time once one byte is out to load the next byte in.  There’s not really anything you can do about it aside from using different hardware.

@Delta_G yep, thought so too. But it actually happens even if I set slower SPI clock. Looks like this is intentional. I guess I should have a look at what's going on in the library.

SPI is synchronous. That means that within certain constraints the timing and the width of any part of the signal is irrelevant.
What makes you think that it's bad to have a slight variance in the timing, or that the "pause after CS goes LOW!" is "too low"?
If you think it's from the timing diagrams, those times are minimum times (generally) and all things happen at either the rising or falling edge of the clock (depending on the SPI mode).

Well if you look at bottom diagram, you can see that after 8 raising edges of clock signal the 9th doesn't happen right away as it would in continuous stream. It pauses for one cycle before transmitting next byte. I understand it will work, just will take a bit longer. Just wonder why and if I can avoid it.

It is completely normal. Why would you want to avoid it?

In SPI there's no requirement to wait so many cycles after pulling CS low before starting transmission. It waits about 6 Tcl extra time.

@IceGlow The Arduino way of working with SPI is that it is blocking. You get a byte. You put it in the SPI data register. You wait for it to send. You retrieve the received byte. You store it somewhere. You get the next byte. You put it in the SPI data register... etc. If you want to make it more "fluid" for some reason then you will have to do it outside the Arduino API and directly interface with the SPI registers. And even use DMA for ultimate background operation.

well I'm playing around with directly controlling currents on the actuator from SPI commands. I'd like to have a predictable and minimum delays between commands, as that increases the accuracy. Does that make sense? But the question is - could I control those delays, before first byte is sent, between bytes, after last byte, if I want to.

And sorry, I didn't mean to say that something is broken. Default library behaviour is not violating any requirements for SPI. There are just some margins, I presume, to increase the stability of some devices. I wonder may I avoid them.

@IceGlow Yes, but not with Arduino API code.


text:
About ATTINY85 Development Board
I am thinking to buy one of "ATTINY85 Development Board"...
Before buying I was checking details/Advantages of it.

First I thought this is just a breakout board & USB for power.
But, then found It can be programmed with "Digispark driver & board manager" directly by the USB.

I checked this Question: EBay “Development Programmer Board for ATtiny”
Someone said there:

"While limited, this type of board can be useful for "blink an LED on
  USB command" type tasks"

My Main question is:
Is it really programmable withut any TTL/ICSP/FTDI extention?
If so, is it possible to program other AVR chip (Attiny/Atmega) with simple codes directly via USB...?
(with same method)

Is it really programmable withut any TTL/ICSP/FTDI extention?

Only if you use an ATTiny chip that has the "Micronucleus" bootloader already installed.

If so, is it possible to program other AVR chip (Attiny/Atmega) with simple codes directly via USB...?

Some can, but most need a bootloader installing. The ATMega32U4, for example, has a "DFU" mode, which is essentially a bootloader in ROM, that you can use directly over USB.  In general, though, the answer is "Not without installing an appropriate bootloader with some hardware programmer first".

Thanks... Now it makes sense... Because most of the tutorials doesn't told about "bootloader" part, maybe the soldered MC already has it... At last found a video with best review & tutorial YT link


text:
Atmega 328pu as stand alone
I am used atmega 328pu as stand alone.i used 7805 as regulator.
I regulated from 12 VOLT 2 amp smps.
When I connect my dc 12 VOLT pump in between 12 VOLT and ground dc motor working fine but Atmega stops working.
Please help me with this.
EDIT: Information added from the comments.
Q: Does the Arduino work with the motor disconnected?
A: Yes it's works fine

The first thing is that you have no decoupling capacitors.

Where I need to put decoupling capacitor .can you please send a diagram if possible.

Also 7805 might be unstable without input and output capacitors.

perhaps the pump drops the voltage below 5v? seems a long-shot, but if the PSU is massively over-loaded that can happen.

I used two 10uf/63 volt capacitor with 7805 in the input and out put.still I have the problem.

When connected pump at the same time I measured the voltage it is still 5 volt.

Perhaps your circuit sketch is different from reality, but: The GND signals should not be connected to a bus type line. especially Pin 8, 22 and 22pF crystal cap GND should be directly connected with short wires and have only one connection to the 12V GND and 7805 GND

Add 0.1uF caps from pin 7 to 8, and from pin 20 to 22. Keep them close to the chip.
If you will be doing any analogRead()s, then add one from 21 to 22 as well.


text:
Arduino emulator to create virtual 3d printer farm
I'm building a system to monitor several 3d printers, but I just have 1 printer. I'm thinking if there is any opensource tool to launch several virtual Arduino based boards running with Marlin firmware to accomplish my task. I'm planning to use Ocoprint for monitoring every board, so I need one serial port to communicate with the virtual printer.
I already modified the firmware in such a way that it runs on a clean ArduinoMEGA (without any shield) and it worked as I need.
I check the suggestions on this related thread but I'm not sure if any of them will work as I need.

Have you tried any of them? I would say it would be a far fetch to think, that any of them can really run the Marlin firmware (which is rather complex). Though you only need idle serial communication, so it might work. You should really try it first, because it is very difficult and complex to answer this. To write an answer without trying it, we would need to know the Marlin firmware and the simulators (not emulators) in detail, with all their requirements and caveats. It is just easier to try it first.

@chrisl I have tried the simulide, simavr, simultron none of them give an answer for serial communicaction


text:
How does the motor shield determines how much voltage to supply to a motor?
Can i connect 6v DC motor and 12v DC motor, or 6v DC and 12V stepper to adafruit motor shield v1, and an external 12v power supply?
also, how does it determine how much voltage needs to be supplied to a motor? is it done by code, when we set the speed of the motor, or the frequency?
do i have to take care of how much voltage i am supplying to the motor shield?

Can i connect 6v DC motor and 12v DC motor to adafruit motor shield v1, and an external 12v power supply?

No.

how does it determine how much voltage needs to be supplied to a motor?

It doesn't. It supplies whatever voltage you supply through the power input.
You must match the power supply to the motor. The motor shield is merely a switch that turns the power on and off in the right way to change the speed and direction of the motor.

can i ask one more thing, when we set the speed and frequency of the motor in the code, what is the motor shield actually doing, is it changing the voltage, or the pwm signal?

It's turning the power on and off very rapidly. The speed at which it turns the power on and off is set by the PWM frequency. The on and off times are set by the PWM duty cycle. Due to the low-pass filter-like nature of an inductive load like a motor the end result is the appearance of a reduction of both voltage and current to the motor, resulting in a change in the overall power and thus speed of the motor. However I would not recommend relying on low PWM duty cycles as a way of "underpowering" a 6V motor from 12V as it is all too easy to get it wrong and smoke the motor.

got it. does it mean that i can't connect a dc motor and stepper at the same time, if the voltage ratings are different?

That is correct. For a 12V power supply you need 12V motors. Or a 12V to 6V voltage regulator (switching regulator ideally) and a second motor shield that you would then run at 6V.


text:
RGB LEd and a push button in TinkerCAD
I'm working on TinkerCAD, I want to design and simulate a circuit in which there are following components. 1. 1 RGB LED 2. 1 Push button 3. 3 Photo-resistors. 4. 1 Arduino board. So the light should be off at the starting. When the push button is pressed for the first ever time, the LED should light up as red, and then the brightness of the red color should be able to controlled by one of the three photo-resistors used, the second time when the push-button is pressed the LED should light up as green and green color this time should be controlled by another photo-resistor..when the button is pressed for the third time , the LED should now change to blue color and the third photo-resistor should be able to control the brightness of the blue color. And this cycle should go on, upon pressing the Push button.
please tell me what's wrong.
Code looks like this
int button_state = 0;//declaring a variable
int counter;//declaring another variable,will keep count of which color to be lighted
const int pRed = A2; //assigning pin A2 as pRed
const int pBlue = A1; //.............A1....pBlue
const int pGreen = A0; //............A0.....pGreen
int inputRed;//adjusted value of led brightness will be stored
int inputGreen;
int inputBlue;
const int ledRed = 9;
const int ledGreen = 11;
const int ledBlue = 10;

void setup()
{
  pinMode(2,INPUT);
  pinMode(ledRed,OUTPUT);
  pinMode(ledGreen,OUTPUT);
  pinMode(ledBlue,OUTPUT);
  pinMode(pRed,INPUT);
  pinMode(pGreen,INPUT);
  pinMode(pBlue,INPUT);
}

void loop()
{
  button_state = digitalRead(2);// reading the button state
  inputRed = analogRead(pRed);// Reading the value from A2 pin
  inputRed = map(inputRed,0,1023,0,255);//value from A2 pin adjusted for led's brightness
  if (button_state == HIGH) {
    counter = 0; // Declaring counter as 0 again
    analogWrite(ledRed,inputRed);
    analogWrite(ledGreen, 0);
    analogWrite(ledBlue, 0);
    delay(10);// Wait for 10 millisecond(s)
    green();// Jumping to green
  }
}
void green()
{
  while (counter == 0){//counter was declared 0 in loop function,so the code won't go ahead till it's 0 only
  button_state = digitalRead(2);//for reading the button state once again
  inputGreen = analogRead(pGreen);//reading the signal from A0 as it is the inputpin for photoresistor for green light
  inputGreen = map(inputGreen,0,1023,0,255);  //value from A0 pin mapped
  if (button_state == HIGH) {
    counter++; // Increasing counter by 1 so that it becomes 1 now.
    analogWrite(ledRed,0);
    analogWrite(ledGreen,inputGreen);
    analogWrite(ledBlue,0);
    delay(10);//wait for 10 millisecond(s)
    blue(); //jumping to function for blue led now
  }
}
}
void blue()
{
  while (counter == 1)//using while, so that the code won't go ahead if counter=1,as made in function for green light
  {
  button_state = digitalRead(2);
  inputBlue = analogRead(pBlue);//reading value from A1 pin
  inputBlue = map(inputBlue,0,1023,0,255);//value from A1 pin mapped
  if (button_state == HIGH) {//
    counter++;
    analogWrite(ledRed,0);
    analogWrite(ledGreen,0);
    analogWrite(ledBlue,inputBlue);
    delay(10);//wait for 10 millisecond(s)
  }
  }
}

please tell me what's wrong.

I'm sorry to say, but pretty much everything. You need to rethink your program flow from the ground up.
Separate out the button from the LED actions. The button should only control the counter. The counter then makes the decision what to do with the LEDs.
Also you have to learn about the concept of change with the button. You don't want to be doing something if the button is high, since that will be being done all the time the button is pressed. Instead you need to learn how to do something only at the moment the button changes from low to high.
As a rough outline to how your program could look, here's a pseudo-listing:

Set the counter to 0
If the button changes from LOW to HIGH

Increment the counter

If the counter is greater than 3

Set the counter to 1

That would give you a sequence of 0-1-2-3-1-2-3-1-2-3 for the counter as you press the button.
Next you have a separate section in your loop to deal with what the counter is.

If the counter is 0

Turn off all LEDs

If the counter is 1

Control the red LED and turn off the others

If the counter is 2

Control the green LED and turn off the others

If the counter is 3

Control the blue LED and turn off the others

If you implement that properly you will have created a finite state machine.

Okay can you give me a rough outline of the commands that can be used when the button is changed from LOW to HIGH, I've really tried everything I know. An example of something similar would also suffice.

digitalRead(), if() and remembering what the button state was.

Plus you'll need to debounce the button presses. (When you detect the button change from low to high, record the value of millis, and ignore further changes for 20-100 mS.)

@DuncanC Depends how many delays you end up littering around the place...  But yes, decent debouncing is always good.

How about NO delays?

@DuncanC Then add an RC network to the button :P Or use one of the myriad of debouncing libraries.

It's not very hard to write debounced button code. See my answer for an outline of how to do it.

@DuncanC I know, but it's not something you want to do every time. That's why I wrote my own library to do it. Write once, use many. Why write the same code every time?

Your code might look something like this
#define debounceTime 50   //Tweak this value to adjust amount of debouncing
unsigned long lastButtonMillis = 0;
uInt8 switchState = 0;
uInt8 oldButtonState = LOW;

void setup() {
   //Your setup code
}

void handleSwitchChange(uInt8 switchState) {
   switch switchState {
      case 0:
         //code for red
         break;

      case 1:
         //code for green
         break;

      case 1:
         //code for blue
         break;

   }
}

void loop() {
    //If enough time has elapsed, check for button presses
    if (millis() - lastButtonMillis >= debounceTime) {
        lastButtonMillis = millis();
        if (oldButtonState == LOW && digitalRead(switchPin) == HIGH) {
            oldButtonState = HIGH;
            switchState = (switchState + 1) % 3; //value will cycle 0,1,2,0,1,2
            handleSwitchChange(switchState);
        }
    } else {
        oldButtonState = digitalRead(switchPin);
    }
}