text:
Will Setting Interrupt Pin High Damage Bluetooth Module?
I want my HC05 Bluetooth Module to trigger an interrupt when it receives a signal. So I've followed suggestions from the Arduino Forum and connected the Bluetooth TXD pin to the Arduino RX Pin and the Interrupt Pin (2), which I set to high. It is set to detect a FALLING voltage, presumably when BT transfers data. When I connected it this way a funny thing happens. I can clearly see that the interrupt is being called because power consumptions goes way up when Android sends a message to BT module, meaning the device wakes up. However the serial port no longer appears to work on the Nano. I think I narrowed down the possible cause to me damaging the board by removing lineage regulator or damaging serial port somehow with the interrupt. Is the way I wired up the interrupt pin as described correct? Your help would really help me narrow down my problem.
#include <avr/sleep.h>

#define ledPin 7
#define intPin 3
int state = 0;
int stateData = 0;
int ultraPin = 10;
int trigPin = 11;    // Trigger
int echoPin = 12;    // Echo
long duration, cm;
unsigned char inches;
unsigned long timer;

void setup() {
  pinMode(ultraPin, OUTPUT);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(intPin, INPUT);
  digitalWrite(intPin, HIGH);
  attachInterrupt(digitalPinToInterrupt(intPin), interrupt, FALLING);
  digitalWrite(ultraPin, LOW);
  Serial.begin(9600); // Default communication rate of the Bluetooth module
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_cpu();
}

void interrupt(){
  Serial.println("interrupted");
  sleep_disable();
  Serial.write(50);
  delay(500);
  timer = millis();
  digitalWrite(ultraPin, HIGH);
  while (true){
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);
      cm = (duration / 2) / 29.1;   // Divide by 29.1 or multiply by 0.0343
      inches = (duration / 2) / 74; // Divide by 74 or multiply by 0.0135
      Serial.write(inches);
      delay(50);
      stateData = Serial.read();
      if (stateData != 49){
        // receipt from android
        unsigned long timeElapse = millis() - timer;
        if (timeElapse > 5000) {
          break; // exit and SLEEP
        }
      }
      else {
          // reset the timer
          timer = millis();
        }
      }
    sleep_enable();
    sleep_cpu();
}

void loop() {

}

setting pin to high works only in output mode

For an input digitalWrite HIGH will turn on the internal pull-up.

@jsotola not necessarily true: https://www.arduino.cc/reference/en/language/functions/digital-io/digitalwrite/

@ILike that us somewhat correct ... but enabling the pullup resistor is not the same as driving the pin high ... driving the pin high could destroy a sensor output, or the arduino pin, if the sensor drove the pin low ... the pullup resistor would not cause damage because the resulting current would be limited by the pullup resistor ... after all, pullup resistors are used with switches that short the pin to ground when pressed

I'm not sure, if you can rule out the hardware damage (you wrote, that you removed the linear voltage regulator, but didn't explain more there). But with that code you won't get what you want.
I see multiple issues, all boiling down to the same problem: You cannot do that inside of an ISR:

delay() relies on interrupts to happen during its execution. As of my knowledge this leads to delay() never ending, blocking your code. Also it is very bad design to have a long running ISR. So much is depending on interrupts to work and when you have something long running, you can just easily do that inside the main code, triggered by an interrupt flag variable.
millis() will not increment during the run of the ISR.
delayMicroseconds() will work, but you still should keep the ISR very short. Reading an ultrasonic sensor is a no-go.
Serial.write() will fill the libraries internal TX buffer, but the actual transmission of the data also relies on interrupts. You won't get your data that way.

Instead of doing all that inside the ISR, you should just let the Arduino wake up, then set a (single byte) flag variable. In your main code you need to check for that flag with an if statement. In that if statement, you are doing all what you need to do and at the end you are resetting the flag and going to sleep again.

I see, so the main issue is that I am using interrupt inside an interrupt routine, which doesn't work?

You are using code, which relies on interrupts, in an interrupt. You are not using interrupts inside of an interrupt, that is a phrase, that does not make sense. For example the function Serial.write() does not use an interrupt, it just places the data in the TX buffer. But the rest of Serial uses interrupts to actually send the data out


text:
Switching a Solenoid Using Arduino's 5V Output?
I'm a bit stumped on how to switch on a solenoid using a transistor using my Arduino Nano's 5v Output. The solenoid runs on 12V, so I used an NPN transistor to connect the 12V source to the solenoid whenever Arduino sends current to the transistor's base. I connected all the grounds together to the Nano's ground pin, but the solenoid still doesn't switch.
I know the transistor works properly, because the solenoid switches when I use the battery to send base current instead of the Nano. I would think the Nano is capable of sending enough current to activate the Collector -> Emitter path but might be wrong. I'm also wondering if it's an issue with grounding the circuit, but I've made sure there is a common ground. What do you think I'm doing wrong? BTW the transistor I am using is D882P. I would appreciate any help.

simulate this circuit – Schematic created using CircuitLab

This is really an electronics question, because there is nothing specific about the Arduino here, except that it has a maximum output of around 20ma. You have a few problems here, including that the load should be on the "high" side (in series with the collector), there is no flyback protection diode, and that there should be a base resistor to limit current through base. Would you like me to migrate this question to Electronics Stack Exchange?

Please post your code too.

Example answer here: Can arduino be used as a switch?

It would probably be closed as a duplicate if I migrate it, I warn you. Try searching that site for ideas.

I have a page about driving devices from the Arduino on my own web site, if you want some ideas and lengthier discussions about resistor values. However Electronics Stack Exchange is a great site for general electronics questions.

Thanks, I am aware of that stack exchange. Unfortunately, I got banned for asking questions like this. Perhaps I will make a new account

Please don't make a new account. The SE mods particularly dislike people who try to work their way around restrictions by making multiple accounts. You have an answer below, I suggest you take a look at it.

The fact is that the various Stack Exchange sites are supposed to be a repository of useful information. Thus you search for an answer to your question (or something similar) before enraging people by posting a question which has been asked many times before, and has very useful answers.

Low-side switching an inductive load (such as a relay) using a microcontroller (such as Arduino), NPN BJT transistor (with full base resistor calculations), and snubber/flyback diode
Note: this answer demonstrates using the 2N3904 NPN transistor for all of the calculations, since that's what's in the schematic in the question. However, after writing the answer, I noticed the words at the end of the question state it is a D882P (also an NPN type) transistor. So, just follow my methodology here but use the appropriate values for your NPN transistor type, which you can obtain from the datasheet. A quick Google search for "d882p datasheet" reveals this as a potential datasheet.
2N3904 is an NPN transistor (datasheet), as opposed to a PNP transistor, so it must be connected directly to GND and switch the low side of the circuit only, so wire it like this instead:

simulate this circuit – Schematic created using CircuitLab
Notice I've added a diode, D1, to dissipate inductance-induced voltage spikes created when electromagnetic fields (a form of energy storage) collapse in the inductor each time you turn the switch OFF. This diode, due to its function (not type), is called a "flyback", "snubber", or "clamp" diode. Again, it protects the transistor and other components from inductance-induced voltage spikes from the relay coil/inductor. When a voltage spike occurs, it will simply travel around that loop through the diode, relay, and resistor R2 again and again and again until it has all been dissipated as heat in those components and there is no more voltage spike remaining.
I've also added a resistor R2 to limit current through the relay coil. You'll have to size this appropriately to get the correct current through your relay coil, based on the relay's datasheet. If your relay's datasheet says to hook up the relay to 12V directly, you can remove this resistor.
And you'll definitely need a base resistor (R1 in my circuit) or else you'll burn up your Arduino pin.
First, let's collect some necessary values from the Datasheet. These will be used in the calculations below:

VBE(sat) = 0.65 to 0.95V.

This is the diodic voltage drop from Base to Emitter when the transistor is "saturated", or fully ON.

hFE_min = 30

Notice in the screenshots below that I have crossed out all of the 2N3903 transistor hFE entries so they don't distract us from the 2N3904 entries, which is the transistor type I'm using for this example. I then chose the lowest hFE entry for this transistor, which is 30.
This is the "guaranteed" minimum, or worst-case, DC current gain. The formula is simply: I_max_permitted_from_Collector_to_Emitter = gain * I_Base_to_Emitter. So, if your gain is 30, for example, and you drive a base current of 5mA from Base to Emitter, then the "guaranteed" maximum possible current allowed from the Collector to the Emitter will be 30 gain * 5mA = 150mA. Again, this is not what you will get into the Collector, this is what you could get before the transistor itself starts limiting the current into the Collector rather than your load limiting the current through the Collector.

Ic_max_continuous = 200mA

This is the max continuous current you can get from Collector to Emitter without overheating the transistor (assuming, I think, you have adequate cooling through conduction and possibly even convection and radiation via heat sinks--I need to brush up on the thermal and power equations myself). The datasheet may specify if a heat sink is required to achieve this current, but regardless, you should keep your continuous current down to about half this value or less if possible, as the device may reach crazy high temperatures of like 150 C or something with this current and no convective cooling or heat sink. For short bursts, hitting this current is just fine.

Here are some screenshots of where to find these values in the datasheet:

Notice in this next image I've crossed out all of the 2N3903 hFE lines so they don't distract us from the 2N3904 entries, which are for the transistor we care about in this example. Choose the lowest hFE value as the gain you will use in your estimates in order to have a "conservative" estimate, virtually guaranteed to fully turn on your transistor in all cases (ie: for all Collector current values you might like to switch on and off).

Now, let's calculate a Base resistor value for an NPN BJT transistor, assuming your goal is to fully turn on (saturate the Base-Emitter channel of) the transistor:
VBE(sat) has a diodic voltage drop of 0.65 to 0.95V, so your resistor would have to burn off 5 - 0.95 = 4.05V to 5 - 0.65 = 4.35V. Let's just use the lower 4.05V value so we will size for higher currents and faster turn-on speeds.
Your minimum hFE (gain) value for the 2N3904 transistor (not the 2N3903) is 30. Maximum continuous Collector current, Ic is 200mA, so let's increase that by a factor of 2 to 4 and size for 200mA * 3 = 600mA to 1) more fully saturate the Base to Emitter channel and get closer to full turn on under all cases, 2) get faster turn-on, and 3) overcome the fact that decreased gain occurs at higher Collector currents. In Figure 15. DC Current Gain, from the datasheet, for instance, shown below, it shows that the normalized gain decreases from ~0.28 at 100mA Collector current to ~0.13 at 200mA Collector current, which means that the gain of 30 found in the datasheet at 100mA Collector current indicates the gain at 200mA Collector current will actually be approximately 30 gain/(0.28/0.13) = 13.9 gain. Simply multiplying the Collector current we are sizing for by a factor of 2 to 4 (3 in our case) accounts for this fact, so we will use 600mA instead of 200mA in our maximum Collector current calculations below.

So, 600mA / 30 gain = 20mA Base to Emitter to get rock solid turn-on performance. Arduino can do up to 40mA per pin so this is Ok. Note that I recommend 30mA max per Arduino pin (for the ATmega328 microcontroller), and there is also a combined output limit for the ATmega328 microcontroller of 200mA for all pins combined, which you should keep in mind. I describe this on my website in my article "Arduino Power, Current, and Voltage Limitations" here.
V = IR, so R = V/I, so resistor, R that we need = 4.05V/0.020A = 202.5 Ohms. This is the minimum recommended base resistor size. Don't go too much smaller than 200 Ohms, if you go smaller than that at all. A 100 Ohm resistor, for instance, would allow a maximum base current of I = V/R = (I intentionally use the higher voltage value here) 4.35V/100 Ohms = 43.5mA, which could damage your pin.
Don't go larger than 600 Ohms or else you risk not turning on the transistor fully by not saturating the Base to Emitter channel. A 600 Ohm resistor would give you a guaranteed max Base to Emitter current of I = V/R = (I intentionally use the smaller voltage value here) 4.05V/600 Ohms = 6.75mA, which with a gain of 30 would give you a max Collector current (based on your relay coil resistance now) of 6.75mA * 30 gain = 202.5 mA. However, as indicated from Figure 15 shown above, a more realistic gain at 200mA Collector current might be only 13.9, which means your maximum allowed Collector current with a 600 Ohm resistor would be 6.75mA * 13.9 gain = 93.8mA. But, at this current your gain would actually be > 30, not 13.9, which leads back to the 200mA Collector current number. You can see this is a juggling game of numbers since the gain is NOT constant NOR linear, but rather is a function of Collector current, as shown by Figure 15 above. So, perhaps your actual maximum allowed Collector current with a resistor of 600 Ohms would be more like 130mA or something. The point is: any larger of a base resistor than 600 Ohms and you most likely won't be able to achieve the transistor's rated maximum continuous Collector current even if you wanted to. So, there's a reasonable R value range!: 200 Ohms to 600 Ohms, perhaps even leaning more towards the 200 Ohms side if you expect to have high momentary Collector currents anywhere near your maximum continuous Collector current rating of 200mA.

Additional notes on high-side vs low-side driving with NPN BJT or N-Channel MOSFET transistors, for clarity:
An NPN transistor can switch high-side voltages too--you just have to drive the necessary Base to Emitter current is all (and don't exceed any maximum ratings)! That's it! So...if you try to drive the high side, think about it: you turn it on with 5V so your voltage from Collector to GND can't exceed ~5V now because as current starts to flow through the collector, voltage would come up on the Emitter side until your base current no longer flows. Your system would be fighting itself. Even if you gave it 12V before the Collector you'd never see more than ~5V at the Emitter, assuming your Base drive voltage was 5V. If you can design around it, go for it, but generally the "easy" or "normal" way to do things is to use NPN to switch low-side voltages and PNP to switch high-side voltages.
The same goes for N-channel and P-channel MOSFETS. Use N-channel to switch low-side voltages and P-channel to switch high-side voltages, UNLESS you are doing some fancy driving (again), of N-channel to switch high-side voltages, as N-channel MOSFETs are more efficient and can switch higher currents than their equivalent P-channel pairs, due to some electron hardware mumbo jumbo stuff.
Keywords: transistor sizing; BJT transistor circuit calculations, equations, and datasheet; arduino and electrical engineering: transistor (BJT) sizing, equations, datasheet, and calculations example
Additional reading:

[my answer] Electronics Stack Exchange: When is a MOSFET more appropriate as a switch than a BJT? [and a BJT more appropriate than a MOSFET]

They said they had a D882P transistor in fact (still looks like an NPN though).

Ah shoot, you're right. His image is deceiving.

@NickGammon, I went ahead with the calculations anyway. I provide the example. They can figure it out for their case. I needed the practice on these calcs anyway. I haven't done them in a while. I miss electronics and EE. Feel free to migrate this question if you see fit. Your call of course.

Ah shoot. I forgot my flyback/snubber diode too! I'm away from the computer now. Oh well. I'll update it later.

Thanks for the detailed explanation. Why does switching low side voltages with NPN work? Sorry, my understanding of electronics is very basic

@ILike, in order to turn on the large current channel from Collector to Emitter in an NPN transistor, you must drive a small current from Base to Emitter. Since voltage only drives current from a location with a higher voltage to a location with a lower voltage, that means you would have to have >12V at the Base to drive a current to the Emitter if the voltage at the Emitter was ~12V. You don't have >12V at the Base, however, you have only 5V. So, you must position the transistor such that the Emitter is connected to GND so you can drive a current from Base to Emitter with only 5V at the Base.

Furthermore, with the NPN transistor at the high side and with a driving voltage of only 5V at the Base, you will end up in an equilibrium with the voltage at the Emitter being equal to 5V - VBE, and the transistor barely on, allowing only a trickle current from Collector to Emitter, and such that the transistor acts like a resistor, burning off the 12V - (5V - VBE) (the difference between the voltage at the Collector and the voltage at the Emitter) as heat in the transistor. So in your setup, the voltage at the Emitter is about 4.5V or so, with only a trickle from Collector to Emitter.

Update: I discovered I was using the 2N3903 transistor's lowest hFE gain of 15 in all my calculations, so I updated the answer to use the 2N3904 transistor's lowest hFE gain of 30 instead. This doubled the recommended size range result to use for the base resistor.

source: Stack Exchange

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

sort: votes


text:
How to send a number as a byte?
I want to send a number between 0 and 120 as a byte over Serial port. I'm working on a project that involves sending ultrasonic sensor readings over Bluetooth to an Android. I would like to send the entire reading as a byte and I think this can be done because an signed byte ranges from -128 to 127. However, the byte received in my Android app doesn't show the correct sensor reading. Here's the relevant code snippet:
  while (true){
      //ultrasonic sensor sends out signal
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);
      pinMode(echoPin, INPUT);
      duration = pulseIn(echoPin, HIGH);

      cm = (duration / 2) / 29.1;   // Divide by 29.1 or multiply by 0.0343
      inches = (duration / 2) / 74; // Divide by 74 or multiply by 0.0135
      // max range is 156 inches, but our app will only display up to 100 inches
      inches = min(127, inches);
      Serial.print(inches, BIN);
      delay(50);

In my Android app written in Java I read the value like this:
b = (byte) inputStream.read();

For example, if inches is 100 and I send that over Serial port, how can I expect to get the same reading in my Android app?

The problem is the BIN in your print statement.  Everything is ALWAYS binary.  The BIN means to break that binary up into ascii digits 0 and 1.  So if you send
Serial.print(21, BIN);
then the print function takes 21 as a binary number, 00010101 and then sends those binary digits as ascii.  So what goes out on the wire is 8 separate bytes, it goes 48, 48, 48, 49, 48, 49, 48, 49 as 48 and 49 are the ascii codes for 0 and 1.
What you want to do is just to send the raw byte.  So use Serial.write instead.  The print functions convert things to ascii representations but the write function just sends the raw bytes out.  So if you write:
Serial.write(inches);

Assuming that inches is a byte type variable then it just sends the raw byte out.

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


text:
Powering Arduino Components with AA in Parallel and Series

simulate this circuit – Schematic created using CircuitLab
I have 6 AA batteries that I would love to power my Arduino Nano and HCSR04 ultrasonic sensor. However, for my low power application I want to use the bare minimum power required for the components. Since the Nano can run as low as 4.5 volts and the sensor requires 5 volts, I think the best solution would be 4 AA batteries in series to power the hcsr04 and 3 AA batteries in series to power the nano. Since I have 6 batteries I was thinking 3 AA batteries wired in parallel with 3 AA series batteries. I drew the circuit diagram above and realize something is horribly wrong. So I was hoping someone could point me in the right direction.

You've got yourself in a right muddle there. You can't make 3 and 4 or of 6. You need 7. Also there are other factors you need to consider. I'll write a pepper answer when I get to my computer later.

According to specs, HC-SR04 uses 15mA. I think it is safe to power it through Nano 5V pin. And then you need just to power only your Nano.

Newer HC-SR04's will run off 3-5V, which makes things easier.

Yeah, don't try to get cute with "lowballing" the input to the Nano. The built-in linear regulator is a big power waster. As Majenko says in his excellent answer, you're much better off using an external buck regulator to power both devices at a full 5V. Those are a LOT more efficient than linear regulators (which convert excess voltage to heat)

Wiring 6 batteries up so it gives you both a stack of 3 and a stack of 4 is not easy, and although you can do it you shouldn't do it.  The only arrangement is this:

simulate this circuit – Schematic created using CircuitLab
(The grey link is optional and makes little difference if it's there or not).
The reason you shouldn't really do that arrangement is that you have a mismatch in your capacities, as [BAT1+BAT2] || [BAT3+BAT4] has more capacity than BAT5, so the current drawn from the 4.5V output will cause BAT5 to go flat far sooner than the others. This will then cause BAT5 to take a reverse charge as current from the other cells flows through it damaging it permanently (especially bad for rechargeable batteries as you will not be able to recharge it, but pretty nasty for alkaline batteries too).
Another consideration when running from different voltages like this is the communication between the different units. If the Arduino is running at a lower voltage the signals it sends out will be of a lower voltage, and it expects to receive signals at a lower voltage. Likewise with the HC-SR04; it will expect to receive higher voltage signals and will send out higher voltage signals. So you will require some logic level translation between the two devices to correct that mismatch in the signal voltages.
As you can see it's all starting to get a little messy now.
A much simpler solution is to keep everything at one voltage. The ideal voltage is 5V since that is the common voltage that all the devices expect to work at.
Since you are running from batteries you want efficiency. To that end you need an efficient solution for generating a stable 5V. The Arduino's built-in regulator is far from efficient, so that can be instantly discounted.
A more efficient solution is a step-down or "buck" switching regulator.  This uses PWM to rapidly turn the power on and off (before then filtering and smoothing it) to effectively convert voltage into current.
You'd run your system off a voltage higher than 5V then use a switching regulator to reduce the voltage down to 5V. Since you have 6 batteries at your disposal the logical voltage would be 6x1.5V = 9V - all 6 batteries in series:

simulate this circuit
If you're running non-rechargeable batteries then you don't need to worry about low-voltage cutoff (you shouldn't over-discharge rechargeable batteries), so this arrangement will get the most out of your battery life. Depending on the "drop out" voltage of the regulator (you can get some with a "zero drop-out bypass" mode) your batteries could get down as far as 0.8V each before the system starts to become unstable (even lower if your HC-SR04 is one of the "upgraded" ones that can run from 3V).

Thanks, why will only the 4.5V outupt drain BATT5? The upgraded hcsr04 is intriguing since I need my battery capacity to last longer than AA batteries in series.

Not only the 4.5V output. But batt5 will be the first to go flat. It has less capacity than the 1/3 or 2/4 pairs, and it is being used by both outputs. It's the one battery that is weakest in the chain. One of the smallest batteries with the most current being drawn from it. Batt6 has the same capacity as batt5 but only a tiny current being drawn from it for the 6V output.


text:
Arduino exercise that i have no idea how to do
The messages received by the Arduino take the form: $ Ba, Pb, Rc #
Where $ represents the beginning of the message, # represents m, and B, P, and R are characters representing B button, P period and R repetition.

`a 'designates the button to be read, which can be 1, 2 or 3.
`b 'designates the time (in seconds) that the button should be expected to be pressed.
`c 'designates the number of times the button is expected to be pressed during the indicated period.

For example, with the message: $ B2, P4, R2 #
you want to know if button 2 has been pressed twice for four seconds. If condition is verified, then the Arduino must send the message $ MSG, TRUE # where MSG represents the message received without the start and m message characters. Otherwise, you must send the message $ MSG, FALSE #.
Incoming messages must respect the format presented. If not, the condition is not checked and the message $ NOK, MSG, KON # must be sent as a response.
I have no idea how to do this since im new to arduino

Hasn't your teacher given some information on how to start? In how to use Serial, how to parse strings? These things can also be found online via google

There are examples of how to parse a comma separated list of data on our network: https://arduino.stackexchange.com/search?q=parse+comma The website cplusplus.com has a good description of C++ functions: http://www.cplusplus.com/reference/cstring/strtok/

do the project on paper first ... pretend that you are the Arduino ... think about what you would do as the message is arriving

To begin, forget the Arduino for a moment and assume the task of determining true or false from $....# message. Think about what you would have to do, step by step, to accomplish this. (e.g.: Read the buttons; Record the time and the button states. Is there a message from the Serial port beginning with '$'? Then read the rest of the message. etc.) Then, for each of those steps, do the same thing again: write down the smaller steps to accomplish what that step requires. Do that until you can't break it down any further.
Those small steps should each look like something you could do in C++ code (sometimes called "Arduino" code, but it's really C++). Start replacing each English (or your language) steps with the C++ equivalent. Do this until all of the human-language steps are written in C++.
There will inevitably be mistakes. Fix one or a few at a time. When you're stuck, ask here, something like "Here is my (well formatted) code. I tried [this]. I expected to see [that]. But what happened instead was [something else]. How can I fix it?"; or: "I am getting this error message [with its complete text including any line numbers, please] from the compiler. What does it mean, and how could I have found that out on my own?"
Small steps....


text:
NRF24L01 Transmission Problems between Arduino UNO and Arduino Nano
I'm a beginner in using NRF24L01 tranceiver module. I tried sending a simple "Hello world" using Arduino Nano and a Arduino UNO with the use of two NRF24L01 modules. I don't get any output in the serial monitor at the receiver side. I checked the wire connection numerous times. Also checked the baud rate of both receiver code and the serial monitor are same and adddresses of the tranceiver code and the receiver code are same. Looking for a solution. Thanks in advance.
This is my tranceiver code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}
void loop() {
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  delay(1000);
}

And this is my Receiver code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}
void loop() {
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

I use Chinese clone nRF24L01. It has very narrow voltage tolerance. My Arduino is also clone.
The 3.3V output voltage was 3.27. The nRF24L01 was not working.  I added a 3 terminal regulator between Arduino 5V output pin and nRF24L01. The voltage was 3.303V.
Then nRF24L01 was working normally.
///////////////////////////////////////////////
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10);
const byte rxAddr[6] = "00001";
void setup()
{
  radio.begin();
  radio.setRetries(15, 15);
  radio.openWritingPipe(rxAddr);
radio.stopListening();
pinMode(4,OUTPUT);
}
void loop()
{
  const char text[] = "Kawasaki_JP";
  radio.write(&text, sizeof(text));

  delay(1000);
}
////////////////////////////////////////////////

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10);
const byte rxAddr[6] = "00001";
void setup()
{
  Serial.begin(9600);
  while (!Serial);
  radio.begin();
  radio.openReadingPipe(0, rxAddr);
   radio.startListening();
}
void loop()
{
  if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

////////////////////////////////////////////

library ;  https://downloads.arduino.cc/libraries/github.com/TMRh20/RF24-1.4.0.zip

Nevermind, I get it.  That is weirdly specific on the voltage.  Often what happens when you add a regulator closer to the nRF24L01 (on anything else for that matter) is just that you also happen to wind up with better decoupling, or just better current capacity.

@Erick Navarrte @dragonflyrobotics Thank you so much for your response, I've tried each an every option you've mentioned, but for an unknown reason it didn't work out for me. Then I researched more on and found out the NRF24L01 base module.This NRF24L01 base module help you to fix 8 pin NRF24L01 series RF module without any problem. And also this module comes with 3.3V regulator and a built in capacitor and easy pin connection to connect PIC or arduino. Using NRF24L01 module and NRF24L01 base module I was successfully able to transmit data.Thanks again for taking time in answering, highly appreciate it.

I had the same problem and when I tried the isChipConnected () function, it told me that one of the nrf24l01 was not connected to the SPI and I assumed that one was bad. I bought 2 nrf24l01 with antenas and they work well (mostly). ( Here is the link to the library reference. Also, make sure you are using the TMRh20 version of the library, This one. This is more updated and better as far as I'm aware.
Like everyone would suggest, try to solder a 10uF capacitor between GND and VCC (that module requires more power sometimes). And the last thing I tried was to use one of this socket adaptors for the 2 modules here to use the 5v output from the arduino since it can deliver more mA and thus the module can work better.
This guide help me a little bit, I'll drop it here
I don't see anything wrong in the code, but I'm a newbie like you so (It seems we are using the same adress in our codes)

You can also try using the NRFLite library. It is a lot easier to use. Also make sure you have a minimum of 3.3V and 0.5A power at the radio pin. If not, it may not transmit.
Here is a TX and RX example of sending text using the NRFLite. It worked perfectly for me!
TX:
/*

Demonstrates sending and receiving packets of different length.

Radio    Arduino
CE    -> 9
CSN   -> 10 (Hardware SPI SS)
MOSI  -> 11 (Hardware SPI MOSI)
MISO  -> 12 (Hardware SPI MISO)
SCK   -> 13 (Hardware SPI SCK)
IRQ   -> No connection
VCC   -> No more than 3.6 volts
GND   -> GND

*/

#include <SPI.h>
#include <NRFLite.h>

const static uint8_t RADIO_ID = 1;
const static uint8_t DESTINATION_RADIO_ID = 0;
const static uint8_t PIN_RADIO_CE = 9;
const static uint8_t PIN_RADIO_CSN = 10;

struct RadioPacket1
{
    uint8_t FromRadioId;
    uint8_t Counter;
};

struct RadioPacket2
{
    uint8_t FromRadioId;
    char Message[31];    // Note the max packet size is 32, so 31 is all we can use here.
};

NRFLite _radio;
RadioPacket1 _radioData1;
RadioPacket2 _radioData2;

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

    if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))
    {
        Serial.println("Cannot communicate with radio");
        while (1); // Wait here forever.
    }

    _radioData1.FromRadioId = RADIO_ID;
    _radioData2.FromRadioId = RADIO_ID;
}

void loop()
{
    // Pick a number from 0 - 60,000.
    uint16_t randomNumber = random(60001);

    if (randomNumber > 30000)
    {
        // Send RadioPacket1.

        _radioData1.Counter++;

        Serial.print("Sending ");
        Serial.print(_radioData1.Counter);

        if (_radio.send(DESTINATION_RADIO_ID, &_radioData1, sizeof(_radioData1)))
        {
            Serial.println("...Success");
        }
        else
        {
            Serial.println("...Failed");
        }
    }
    else
    {
        // Send RadioPacket2.

        // Create a message and assign it to the packet.
        // Strings need to be converted to a char array and note they cannot be longer
        // than 31 characters since that is the size of _radioData2.Message.
        String msg = "Hello " + String(randomNumber);
        msg.toCharArray(_radioData2.Message, msg.length() + 1);

        Serial.print("Sending '");
        Serial.print(msg);
        Serial.print("'");

        if (_radio.send(DESTINATION_RADIO_ID, &_radioData2, sizeof(_radioData2)))
        {
            Serial.println("...Success");
        }
        else
        {
            Serial.println("...Failed");
        }
    }

    delay(1000);
}

RX:
/*

Demonstrates sending and receiving packets of different length.

Radio    Arduino
CE    -> 9
CSN   -> 10 (Hardware SPI SS)
MOSI  -> 11 (Hardware SPI MOSI)
MISO  -> 12 (Hardware SPI MISO)
SCK   -> 13 (Hardware SPI SCK)
IRQ   -> No connection
VCC   -> No more than 3.6 volts
GND   -> GND

*/

#include <SPI.h>
#include <NRFLite.h>

const static uint8_t RADIO_ID = 0;
const static uint8_t PIN_RADIO_CE = 9;
const static uint8_t PIN_RADIO_CSN = 10;

struct RadioPacket1
{
    uint8_t FromRadioId;
    uint8_t Counter;
};

struct RadioPacket2
{
    uint8_t FromRadioId;
    char Message[31];    // Note the max packet size is 32, so 31 is all we can use here.
};

NRFLite _radio;
RadioPacket1 _radioData1;
RadioPacket2 _radioData2;

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

    if (!_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN))
    {
        Serial.println("Cannot communicate with radio");
        while (1); // Wait here forever.
    }
}

void loop()
{
    // 'hasData' returns the size of the packet that was received, or 0 if there is no data.
    uint8_t packetSize = _radio.hasData();

    if (packetSize == sizeof(RadioPacket1))
    {
        _radio.readData(&_radioData1);

        Serial.print("Received ");
        Serial.print(_radioData1.Counter);
        Serial.print(" from radio ");
        Serial.println(_radioData1.FromRadioId);
    }
    else if (packetSize == sizeof(RadioPacket2))
    {
        _radio.readData(&_radioData2);

        String msg = String(_radioData2.Message);

        Serial.print("Received '");
        Serial.print(msg);
        Serial.print("' from radio ");
        Serial.println(_radioData2.FromRadioId);
    }
}


text:
Arduino Pro Micro not recognized by PC
so I've got myself a Arduino Pro Micro ATmega32U4 5V 16MHz and my PC (Win10 64bit) won't recognize it.
So, after I firstly plugged it in, it was detected as a Leonardo, rather than a Pro Micro, afterwards I installed hte drivers as noted by Sparkfun, and added the board to the IDE. Afterwards, my Arduino got detected as an unknown device where I can't use it anymore. I tried installing the drivers as given by sparkfun over the "unknown device" and no luck by trying, I always get an error saying that Windows has already the best drivers for it already installed.
And later, I uninstalled the "uknown device" in hope that it will re-install itself upon pluggin it back it, and it actually disappeard totally and got repalced by "Unknown USB Device (Device Descriptor Request Failed)" under USB controllers in the Device manager.
And I'm stuck here. In the IDE, the Pro Micro is detected as being on "COM1" no matter what COM port it really is, or is it even plugged it at all. Uploading a code results in the bar being filled up and "Uploading..." message, while maybe after a few minutes a very long error pops up without anything specific since you can plug out the board and get the same error.
I also tried a different PC with Windows 7 64bit on it, and instead of getting recognized as a Leonardo, this time it came straight to becoming a "Unknown device". I tried installing drivers multiple times with no luck, also again tried manually overiding the drivers in the Device manager and it always says that the best drivers are already installed.
I'm really stuck here.
Pics of  the board: https://postimg.cc/gallery/rwCDRfv

What happens if you press RESET (bridge between RST and GND briefly) twice?

Device Descriptor Request Failed has nothing to do with drivers. the PC can't read the PID/VID to install appropriate drivers. it may have many causes from bad cable or a broken solder on the usb socket, to the firmware itself which doesn't provide the needed information for PC.

@Majenko nothing special. The Arduino disconects briefly, and reconnects with the same error. Also, the two leds around the crystal oscilator briefly blink, but with very very very low brigthness compares to the main led which glows all the time, even when you reset the Arduino

@TirdadSadriNejad I heard something about flashing a new bootloader if it's a firmware problem? Could that be it. I'll also check (try to atleast) if the usb socket is badly soldered.

you can use another arduino as a programmer and burn the bootloader on the Pro micro

If it detects ok for a few seconds when you reset then it's good. It's just the sketch that is loaded onto it that is bad. Did you install something to it and then it stopped working? Also, don't install any drivers: you don't need them. The fact that it "says" Leonardo is meaningless.

I made it. I shorted the RST and GND pins in the right moment while uploading the code, and it just uploaded. Now it works perfectly, without the need of reseting it. Thanks for the assistance. It detects the port now, it uploads the code and no more errors show up. Blink code works.

I got similar problem, I was trying to burn some HEX files and somehow, my windows wasn't able to recognize my atmega32u4 anymore, not even in Device Manager. I found that the bootloader was "bricked", and to fix it, you need to burn a valid HEX file, like the simplest led blink code. I've done that by the prompt command, using avrdude. So you reset twice, and you have 8 seconds to upload the hex file. It's faster doing that with prompt command than arduino software. After I uploaded the LED blink code successfully, the windows naturally recognized my atmega32u4 instantly, I could identify it in Device Manager as PCOM 4 since then. So you need to revive your bricked atmega's bootloader.
I guess there's nothing to do with the drivers in this case.

It was wrong of you to try and install the driver as this board SHOULD be recognized as Leonardo. I would try to reinstall the Arduino IDE, it will also reinstall the drivers (hopefully)

I made it. I shorted the RST and GND pins in the right moment while uploading the code, and it just uploaded. Now it works perfectly, without the need of reseting it.

1
I made it. I shorted the RST and GND pins in the right moment while uploading the code, and it just uploaded. Now it works perfectly, without the need of reseting it. –
Marin Sebesic
CommentedJun 26, 2020 at 15:41
I just fixed 2 bricked Sparkfun Pro Micro by following the above process. Try uploading a small program, I used IC2 checker very small.
I used a button to short rst and gnd
It works!


text:
TI ADS7250 Read From SPI and SPI1 Simultaneously
I'm so confused by the ADS2750 datasheet here, I can't seem to figure the proper bit shift to read data from bits 15-27 properly. I'm not even sure what some of the acronyms mean on page 23 table 1. I get that the first 15 bits are empty while the ADC takes a reading and then the last 12 bits for the 12 bit ADC are the value from that ADC that matches the SPI A or B input. Would someone be willing to explain to me how you would read data based on this datasheet using information from table 2 page 24?
My hardware set up to ADC7250
VCC 5 Volts

D5 SS fro Both SPI & SPI1
D13 SCK for Both SPI & SPI1
D11 MISO SPI_A from ADC
D4 MISO SPI_B from ADC
No MOSI connected

I'm not sure what to send in the SPI.Transfer(0x00). I'm also not sure if I'm setting up the modes properly, SPISettings settings(24*MHZ, MSBFIRST, SPI_MODE1); as I not 100% on the clock speed. I also I'm confused if this is LSB or MSB as the datasheet has two conflicting notes, the transfer function used LSB and then two paragraphs say "MSBs of ADC_A and ADC_B are output"
I'd love some help decoding this data sheet and getting a script that can read data from this chip using both SPI and SPI1 simultaneously.
Working on only reading SPI first the will add SPI1.
unsigned int readRegister(byte thisRegister, int bytesToRead);

const int CS_ADC_ISOLATOR = D5;
__SPISettings settings(24*MHZ, MSBFIRST, SPI_MODE0);
const int buffersize = 30;
unsigned char dataBuffer [buffersize];
const byte READ = 0x22;

// setup() runs once, when the device is first turned on.
void setup() {
  Serial.begin(115200);
  pinMode (CS_ADC_ISOLATOR, OUTPUT);
  digitalWrite (CS_ADC_ISOLATOR, HIGH);
  SPI.begin();
  SPI1.begin();
}

// loop() runs over and over again, as quickly as it can execute.
void loop() {
    digitalWrite (CS_ADC_ISOLATOR, LOW);
    SPI.beginTransaction(settings);
    for(unsigned char i = 0; i < buffersize; i ++)
    {
        dataBuffer[i] = SPI.transfer(0x00 << 14);
    }
    digitalWrite (CS_ADC_ISOLATOR, HIGH);
    SPI.endTransaction();
    for(unsigned char n = 0; n < buffersize; n ++)
    {
        Serial.print(dataBuffer[n]);
    }
    Serial.print("::");
}

You can't use the normal SPI library for communicating with this device properly. Well, you can, but you will only be able to use one channel - the other will be completely ignored.
SPI only works on one MISO pin - you need two.  There are two other types of "SPI" that are used by devices, most notably SPI flash chips: DSPI and QSPI (dual SPI and quad SPI). You want DSPI.
Unfortunately the Arduino doesn't do DSPI, so you will have to "bit bang" it, which means manually manipulating the IO pins to create your own SPI signals in software.
Now... on to the datasheet:
The important part is the timing diagram on page 9. From that you can see that you just send 32 clock pulses and the chip responds, after 15 pulses, with the data.
So if you just do 4 8-bit transfers back-to-back then you get the data. It doesn't matter what you "send" in those transfers since the MOSI pin isn't connected to anything.
As far as speed goes, 24MHz is the maximum speed that it will run at. The actual speed is dictated by the Arduino and how fast you manipulate the SCK pin. That can be as slow as 1x10-1000Hz if you really want.
Data should be read on the falling edge of SCK.
So you could write a little routine that looks like:
uint32_t resa = 0;
uint32_t resb = 0;

pinMode(SCK, OUTPUT);
pinMode(SDI_A, INPUT);
pinMode(SDI_B, INPUT);
pinMode(CS, OUTPUT);
digitalWrite (CS, HIGH);

digitalWrite (CS, LOW);
for (int i = 0; i < 32; i++) {
    digitalWrite(SCK, HIGH);
    digitalWrite(SCK, LOW);
    resa <<= 1;
    resb <<= 1;
    resa |= digitalRead(SDI_A);
    resb |= digitalRead(SDI_B);
}
digitalWrite (CS, HIGH);

Serial.print("A: "); Serial.println(resa);
Serial.print("B: "); Serial.println(resb);

So for 32 iterations you pulse the clock HIGH then LOW, then shift each result 1 bit to the left, and then add in the newly read bit into the lowest bit position.
You could speed up operation by using direct port manipulation and avoiding the slow digitalWrite() and digitalRead() functions.

Let's say I selected an MCU with DSPI, it has SPI and SPI1 capabilities, would I be able to use the SPI library then or would bit danging be my best beat still? I'm using a Particle Boron which has DSPI.

No, that doesn't have DSPI (or if it does, you can't tell from that picture. That has two independent SPI channels. That's not DSPI. DSPI, and QSPI, are just one channel, but with multiple data pins on the one channel.

So I'm going to have to bit dang... dang. How would you recommend holding CL low for the correct amount of time without a delay? I'd like something that checks the data and pulls CS pin HIGH again based data's status, but can't confidently think of a solution.

Sorry, I don't understand. You just lower CS, send your clocks and read the data, then raise CS again. There's nothing to "check".

Ok, so I should be able to drow CS low fro 32 CLK cycles and read the data coming from the ADC into any GPIO instead of the standard SPI library. The Boron uses a nRF52840 datasheet page 399 talks about the SPI bus and page 286 talks about the Quad serial peripheral interface. What I understood from reading 6.19 is that the QSPI is not useful here because teh two SPI buses are designed for memory and won't be able to share a single CLK. What recommendation do you have to reading a ADC with two SPI MISO inputs?


text:
Connect two SD cards to one Arduino board and copy from one to another
I'm trying to connect 2 SD cards to an Arduino Uno board.

My first question is: Is it possible to connect two SD cards to one Arduino simultaneously?
The second question is: If it is possible to connect 2 SD cards, How can I copy card 1 data to card 2

My project goal is to copy data from one peripheral memory to another peripheral memory when an external interrupt occurs.
Can anyone help me please ?

Yes, SD cards use the SPI bus so you can connect more than one.  They will each need their own chip select line.  To copy just read from one and write what you read to the other.  Super simple.  If none of this makes sense then do some study on dealing with a single SD card.  Once you got the basics hooking up two will be trivial.

Just watch out cause some cheap SD modules don’t release the line when you deselect them.  They won’t let anything else on the SPI bus work without some minor modifications.  Buy good quality stuff and it shouldn’t be a problem but if you go for the cheapest thing you can find then you’ll need to study this issue as well.

Thanks for your help & good answer :). Actually this is not a real project and I should simulate it using Proteus simulator. Do you have any good tutorial for how to deal with SD cards in Arduino? @Delta_G

@user67463 have you tried googling for a tutorial? There are tons of them

There are literally hundreds of those tutorials all over the internet.  Finding one will be far easier than writing this code.  If you open the Arduino software and check the examples there are examples of how to use an SD card.  Start there.  Or just google “Arduino SD” and start reading.

One extra hint for you since you say you want to do this in response to an interrupt.  Don’t try to do this inside the interrupt handler.  Let the ISR set a flag and have the loop function see that and handle the reading and writing there.

You can't do it with your Arduino-Uno (and usual SD libraries).
SD cards are organized in 512 byte "sectors". You need at least one sector for the file system itself and one sector for the data. If you try to have two files open simultaneously, all your 2048 bytes RAM are required for the SD buffers and you can't return from the file open() call any more.

You could do a block-by-block copy of the SD card, instead of actually reading the file system. Downside is that the SD to copy to has to be as large, or bigger as the original card. And that copying always takes the same (long) amount of time, no matter "full" the card is

@Gerben: correct. (That's my "usual SD libraries" restriction)  If you have old 64 MB SD cards, you might do that full copy. But the sentence "when an external interrupt occurs" makes me think user67463 tries to ride a dead horse.


text:
Arduino Micro: Followed the BlinkWithoutDelay instructions, but somehow it's not working in my code
Any help would be greatly appreciated!
/*
   Jebediah's Launch Control System for Kerbal Space Program
   Alpha Build 2.00
   An Open-Source Project by John Seong
*/

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

const byte ROWS = 4;
const byte COLS = 3;

const int buzzer = A3;

const int ledAbort = 5;
const int ledStage = A5;

const int buttonAbort = 4;
const int buttonStage = A4;

int ledAbortState = LOW;
int ledStageState = LOW;

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

byte rowPins[ROWS] = {12, 11, 10, 9};
byte colPins[COLS] = {8, 7, 6};

Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

unsigned long previousMillis = 0;

const long interval = 1000;

// Show a two-line message on the LCD.
void lcdShow(const char *line0, const char *line1) {
  lcd.clear();
  lcd.print(line0);
  lcd.setCursor(0, 1);
  lcd.print(line1);
}

void lcdShowResult(float result) {
  lcd.print(result);
}

void setup() {
  pinMode(buzzer, OUTPUT);

  pinMode(ledAbort, OUTPUT);
  pinMode(ledStage, OUTPUT);

  pinMode(buttonAbort, INPUT_PULLUP);
  pinMode(buttonStage, INPUT_PULLUP);

  pinMode(buzzer, OUTPUT);
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcdShow("  JEB'S LAUNCH", " CONTROL SYSTEM");
  delay(3000);
  lcdShow("ALPHA BUILD 2.00", " STUDIO HORIZON");
  delay(3000);
  lcdShow("WELCOME, KERMAN.", "PRESS ANY KEY...");
  while (!keypad.getKey()) ;  // wait for key press
}

void loop() {
  static enum {START, MENU, SET_COUNT, COUNT_DOWN, LAUNCH, SET_THRUST, SET_WEIGHT, TWR_COMPUTE} state = START;
  static uint32_t last_second;  // millis() value on last full second
  static int count;
  static float thrust, weight, ratio;

  char key = keypad.getKey();

  switch (state) {
    case START:  // transitional state
      lcdShow("1. LAUNCH SEQ", "2. TWR CALC");
      state = MENU;
    /* fallthrough */

    case MENU:
      if (key == '1') {  // Countdown
        lcdShow("COUNTDOWN TIMER", "SECONDS: ");
        count = 0;
        state = SET_COUNT;
      } else if (key == '2') {  // TWR
        lcdShow("TWR CALCULATOR", "THRUST: ");
        thrust = 0, weight = 0, ratio = 0;
        state = SET_THRUST;
      }
      break;

    case SET_COUNT:
      if (key >= '0' && key <= '9' && count <= 99) {
        lcd.print(key);
        count = 10 * count + (key - '0');
      } else if (key == '#') {
        lcdShow("    T-MINUS", "     SECONDS");
        // Force a refresh on entering COUNT_DOWN:
        last_second = millis() - 1000;
        count++;
        state = COUNT_DOWN;
      } else if (key == '*') {
        state = START;
      }
      break;

    case COUNT_DOWN:
      if (millis() - last_second >= 1000) {
        last_second += 1000;
        count--;
        if (count <= 10) {
          tone(buzzer, 500);
          delay(500);
          noTone(buzzer);
        }
        if (count == 0) {
          Serial.println("Lift off!");
        } else if (count < 0) {
          state = LAUNCH;
          break;
        }
        lcd.setCursor(1, 1);
        lcd.print(count < 10 ? "  " : count < 100 ? " " : ""); // pad
        lcd.print(count);
      } else if (key == '*') {
        state = START;
      }
      break;

    case LAUNCH:
      tone(buzzer, 3000);

      int stageConfirm = digitalRead(buttonStage);
      int abortConfirm = digitalRead(buttonAbort);

      unsigned long currentMillis = millis;

      if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;

        if (ledAbortState == LOW) {
          ledAbortState = HIGH;
          lcdShow(" T-ZERO WARNING", "CONFIRM IGNITION");
        } else if (ledAbortState == HIGH) {
          ledAbortState = LOW;
          lcd.clear();
        }

        if (ledStageState == LOW) {
          ledAbortState = HIGH;
        } else if (ledAbortState == HIGH) {
          ledAbortState = LOW;
        }
        digitalWrite(ledAbort, ledAbortState);
        digitalWrite(ledStage, ledStageState);
      }
      break;

    case SET_THRUST:
      if (key >= '0' && key <= '9' && thrust <= 9999) {
        lcd.print(key);
        thrust = 10 * thrust + (key - '0');
      } else if (key == '#') {
        lcdShow("TWR CALCULATOR", "WEIGHT: ");
        state = SET_WEIGHT;
      } else if (key == '*') {
        state = START;
      }
      break;

    case SET_WEIGHT:
      if (key >= '0' && key <= '9' && weight <= 9999) {
        lcd.print(key);
        weight = 10 * weight + (key - '0');
      } else if (key == '#') {
        lcdShow("THRUST-TO-WEIGHT", "RATIO: ");
        if (thrust != 0 || weight != 0) {
          ratio = thrust / weight;
          lcdShowResult(ratio);
        }
      } else if (key == '*') {
        state = START;
      }
      break;
  }
}

And what exactly is not working? What did you expect and what actually happened? What did you do to debug the problem?

You have to be more specific about the problem. I took a cursory look at the code and saw a delay() within a state machine. This is something you usually want to avoid. In fact, the whole point of a state machine is to avoid calling delay() in order to keep the system responsive.


text:
How to prevent flickering relay upon waking from deep sleep using ESP01 board?
I have a cheap ESP01 relay module and am using it with ESPEasy. I soldered the GPIO pin 16 to RST to allow deep sleep and that all works great.
However when the unit wakes up the relay flickers quite a bit. The application I had in mind was for a 12v fridge which draws quite a bit of current on start up. I think this flickering would damage the fridge compressor or controller pretty quickly, not to mention wearing out the relay itself.
I need the unit to wake up from deep sleep, and keep the relay in the off position, unless triggered by some external criteria.
Perhaps a capacitor would absorb the pin high voltage for a short period until it's booted? Trouble is that I don't really want to hack the module, I'll probably break something.

perhaps the starting point is to ask which IO pin does not change state when ESP01 wakes up ... that relay module may not be suitable for controlling a 12 V fridge (dependent on the current drawn by the fridge at startup)

"Trouble is that I don't really want to hack the module", you already hacking the ESP-01 by connecting IO16 to RST, so what's the difficulty of adding a capacitor compare to the ESP-01 hack?

well yes, that was already pretty difficult, and I succeeded in two out of three I've tried. But these relay boards are hard to come by where I am, so I'd want to be pretty confident to try that. I've already had to remove one smd resistor to get the thing to boot. each time I'm adding more risk of destroying the board

The only two pins that don't glitch or change state during reset and boot are GPIO4 and GPIO5, and neither of them are brought out to the 2x4 header on an ESP-01.
https://rabbithole.wwwdotorg.org/2017/03/28/esp8266-gpio.html
All of the other pins will make your relay click or chatter.  Pick a different module, or try soldering a wire onto GPIO4 or 5. The boot time is ~ 150ms long, so it'd take a long time constant R-C circuit to filter it out, on the order of 1/2 second or more.

Apparently it's a pretty common issue for people using this board. There are a  couple of solutions here that I will try: https://github.com/IOT-MCU/ESP-01S-Relay-v4.0/issues/1
The most non invasive one with Tasmoto firmware didn't work in my case. So I will try another pin and if that fails, bite the bullet and introduce a capacitor.


text:
ESP8266 NodeMCU 3v3 current for fingerprint sensor
From what i see that 3.3Vpin provide 3.3V and 400mA. The fingerprint module i use is AS608. Connecting the fingerprint module power pin to 3.3V of the nodemcu. From the datasheet it only can handle 3.3VDC, operating current<60mA and peak current at <70mA. Do i need to add a resistor to take the current away. Since last time i use another fingerprint module which is R307 connecting to Vin of the nodemcu and now it not working anymore?

400mA is the maximum the regulator can provide. It's not what the regulator does provide. You may have a car with a 1.4l engine. That doesn't mean the fuel tank is only 1.4l as well. The engine only takes what it needs from the fuel tank.

uhmm so it mean if i directly plug the fingeprint power pin to 3.3v it will just draw the current it need and wont burn?

Correct. The 400mA basically means that "the sum of all the peak current requirements of all devices connected to 3.3V must not exceed 400mA".

Be careful using Vin on the NodeMCU for 3.3V devices! If you are powering it by 5V USB power, this Vin pin will probably have something like 4.76V on that pin. The circuit diagram shows that Vusb is connected to Vin with just a schottky diode, which drops the current about .34 volts and provides some noise isolation from the Vusb supply. If you connected a 3.3V device to this pin at 4.76V, you may have damaged your component.
You'd have to check the datasheet or documentation for the fingerprint module, but it sounds like the fingerprint module will only draw 60-70mA when it's given 3.3 volts. Datasheets often provide application examples and may specify that you do need additional resistors, capacitors, etc. The refrain in cases like this is always read the datasheet.
If your NodeMCU datasheet says it can provide 400mA then it should certainly be able to provide the 60-70mA that the fingerprint sensor needs. I've powered an ESP8266 by connecting its Vin pin to the Vin of another NodeMCU and they seem fairly happy together, although there tends to be quite a bit of noise on the Vin pin.

The question clearly mentioned the its 3.3v being connected, this answer is is not wrong, but is unsuitable

Dont want to be bad, but Vin is not a 3V3 output pin. as such the schotky is there just to protect the USB not to drop the voltage.The 3.3 output pis is often marked as 3V

You should not use Vin for taking power out

Dont mix your pins. and use 3V pin (NOT Vin), that should be able to output it.
AMS1117 used in most nodeMCU's I have seen can reasonably provide 800mA medium lenght periods with voltage drop of 8-9 Volts.
The MCU can reasonably take 100mA-350mA. This varies based on the amount of the work it does, running core frequency (I am not advanced enough to mess with that yet), Whether its communicating over wifi and how strong does it have to make the signal (influenced by distence, other wifi devices around). This leaves you with about 450mA to play about. As designers were responsible a good designers 50mA was cut as a margin.
Because of how voltage regulators work, the more voltage you are droping the lover current you can sustain. (worth researching heat decipation) Next is the matter of wether the device is enclosed etc.
So 60mA is OK for most nodeMCU as extra load.
If you reach few hundred mA and are really concerned you can reasonably control consumption simply by controling whether the nodeMCU is sending any majour communication over or if it does encryption (demanding tasks) etc.


text:
Can I use a MCP23017 to connect multiple RC522 modules?
I want to connect multiple (exactly 64) RFID-RC522 modules to one Nodemcu ESP8266.
I already know, that it is possible to connect multiple RC522's by just using different pins for the SDA pin, while the rest of the RC522 pins can be connected to the same pins on the ESP8266. But not that many, of course.
My research on "how do I get more pins", got me to the MCP23017 port expander.
Further research is not exactly clear, if I can use these pins as ChipSelect/SlaveSelect pins for the RC522.
The two libaries I found for MCP23017 (blemasle/arduino-mcp23017 and Adafruit-MCP23017 seem not to support this, when I use miguelbalboa/rfid (which I have to use, as there seems to be no alternative), because the MCP-Libs do not provide a "Pin Number" for the MFRC522 constructor(?).
So, is this just a "software" thing, or a technical limitation, and what I want is simply not possible? My research was not exactly clear about this, but I'm also very new to electronics and might be researching in the wrong direction.

For a chip select pin you just need a digital HIGH or LOW.  Any digital pin on any expander can do that.  You can connect multiple of those expanders to the same SDA and SCL pins as long as they have different addresses.  I'm not sure how many possible addresses there are for those chips.  If there are at least 8 possibilities then you can get this all from two pins on the Arduino.

You will probably suffer from bus capacitance and fanout issues long before you get to 64 devices regardless of expanders. Think outside the box.

Sure, you can use IO expanders for the chip-select pins of SPI devices. You will have to modify the device libraries to support them, though, because no one is going to do that by default unless it's a very very specific library.
However you will probably not have much luck with your project anyway, since you will more than likely run into problems with fan-out and bus capacitance before you even remotely approach 64 devices on your bus.
You would need to be adding extra bus drivers and partition your bus to reduce and spread the load - at which point it would be simpler and cheaper to just use multiple microcontrollers with just a few RC522s one each.


text:
DH11 and uno relay controle fridge
I want to control my bar fridge with temp sensor and relay,
This is my first project with code, i copied this:
https://robojax.com/learn/arduino/?vid=robojax-DHT22_11_TM1637_relay
But
I want some extra code that will prevent the fridge (ie relay) from going on too often.
For my purposes I want the relay to close if the temp is above 4c, but only if the relay has been off for say 20min or more.  FYI this is because my power source does not like to start the compressor when it is hot, so i don't want it cycling if it was just on.

Cool question! ;-) Instead of a fixed timer, I would build in some (so-called) hysteresis, which means turning refrigeration on above a certain temperature (say 4 °C) but only turning off when the temperature has dropped again to a temperature well below that (say 3 °C). This ensures the temperature stays within set limits while at the same time preventing fast cycling. You don’t need any timers for this and it will work in any situation (even when it’s very hot or very cold outside of the fridge). This is how commercial thermostats work.
If you really need to ensure the compressor cools enough between cycles, you just need to start a timer when it turns off, and not turn on again before it expires. Look at examples like BlinkWithoutDelay for some coding ideas.

Thanks, I actually found BlinkWithoutDelay about an hour before reading your message.  But i am relay out of my wheel house here, how to i put the 2 together?  BTW I like the Hysteresis idea, but the door opining can cause a 5 degree rise in temp, that takes a few minutes or longer to stabilize again.

You could add a tactile / magnetic (Reed / Hall Effect) switch to detect when the door is open, you could use this as a trigger to tell the software why such a dramatic drop has occurred and to wait x time till temperature settles again. The Hysteresis idea sounds like a good solution as well, you could achieve the same effect by calculating a rolling average over a defined time period and only enable the fridge when this rolling average drops below the trigger temp. This would help smooth out the sensor readings a little.


text:
Add nRF24L01 to a project
I Have a Liquid Level Project that Currently uses an Oled display.  I have just discovered the existence of the nRF24L01 wireless communication module; and it is exactly what I need to make my project more user friendly.
Eventually I want to have a dashboard that brings all my info together in one place, but for now I just want to figure out how to get my Liquid Level Project transmitting, and receive the data on another Arduino and view it on the Serial monitor.  As is all it does is print out "?" in the Serial monitor.
I have this Sketch on the Liquid Level Project Arduino:
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
SSD1306AsciiAvrI2c oled;
#define I2C_ADDRESS 0x3C
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

double SensorAnalogValue;
uint8_t calculation=1;
String Show_value;

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{

  Serial.begin(9600);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(CalLite24);
  oled.clear();

  radio.begin();

  //set the address
  radio.openWritingPipe(address);

  //Set module as transmitter
  radio.stopListening();

}

void loop()
{

  SensorAnalogValue = analogRead(A0) * 5.0 / 1023.0;
  if (SensorAnalogValue < 1.726) {
    calculation=0;
    Show_value="Low";
  }
  if (SensorAnalogValue > 4.04) {
    calculation=0;
    Show_value="High";
  }
  if(calculation!=0){
  //  Serial.println(SensorAnalogValue);
    Show_value=(String)Liquid_Volume(SensorAnalogValue);
  }
  Serial.println(SensorAnalogValue);

oled.setCursor(20, 0);
  oled.print(Show_value);
  oled.print(" L");
  oled.println(" ");
  oled.print(Show_value);
  oled.print("L");
  oled.println(" ");
delay(500);
   oled.clear();

  radio.write(&Show_value, sizeof(Show_value));
  delay(1000);

  calculation=1;
}
int Liquid_Volume(double Volt) {
  double A =   2.81842;
  double B = -11.00151 ;
  double C =  14.4765 ;
  double D =  28.73579 ;

  return A * Volt * Volt * Volt + B * Volt * Volt + C * Volt + D;
}

And the Receiver has this:
//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

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

  radio.begin();

  //set the address
  radio.openReadingPipe(0, address);

  //Set module as receiver
  radio.startListening();
}

void loop()
{
  //Read the data if available in buffer
  if (radio.available())
  {
    char Show_value[32] = {0};
    radio.read(&Show_value, sizeof(Show_value));
    Serial.println(Show_value);
  }
}

I think the problem is in:
radio.write(&Show_value, sizeof(Show_value));

I believe "radio.write" is used kinda like Serial.print, or oled.print,  But I don't really understand the "sizeof" part, maybe that is the problem?

radio.write(&Show_value, sizeof(Show_value));

I believe "radio.write" is used kinda like Serial.print, or
oled.print, But I don't really understand the "sizeof" part, maybe
that is the problem?

Sort of.  There's kind of two interrelated problems.  The major one is that the actual data of a String is not contained with the actual String type itself.  It's allocated on the heap.  What the String class contains is a pointer to it and some numbers for tracking the allocated size and amount used.
So the first problem is you're not reading the memory that actually contains the text inside the string.
sizeof(Show_value) evaluates to the size in bytes of the String class itself, which is the size of a pointer and a couple of integers, about 6 bytes, and not the size of the content of the string.
So you're sending a pointer (a memory address) that the receiver wouldn't know what to do with, and some information about how much was allocated and used and nothing of the String content.
Try:
radio.write(Show_value.c_str(), Show_value.length());

.c_str() gets a pointer to the actual string content itself.  And .length() is the actual size of the used part of the String's allocated area on the heap.
That said, it's better to avoid String where you reasonably can.

Regarding:

Does this also mean I need to replace radio.read(&Show_value, sizeof(Show_value));

It would. Doing that is a bit more complicated since .c_str() yields const char *; String isn't designed to make write-access to its underlying data as easy.
Without hacking your way around String's expectations, that would require using a temporary buffer. Something like:
char buffer[33] = "";  // Note: this will actually fill the entire buffer with '\0', which some find a surprise.
// The idea in the above is to accommodate the maximum RH24L01 packet size 32 bytes plus room for a null terminator.

radio.read(buffer, sizeof buffer - 1);  // We're only making the 32 byte chunk available to the .read() call, and leaving the last byte to it's '\0' value to force null termination in any case.

String s = buffer;

This assuming that you're either filling the packet with bytes, or including the null terminator in the packet, or both.  If you're using a dynamic payload size, rather than initializing the array with = "";, it could be left uninitialized and the received packet size could be used to place the null terminator at the location needed.
You could wrap this in a function if you plan on doing it a lot.  But again, it's probably better if you can just use the array and not work with String.

Thanks timemage,
Does this also mean I need to replace
radio.read(&Show_value, sizeof(Show_value));
With:
radio.read(Show_value.c_str(), Show_value.length());
In the receive sketch?

I've updated to try to address that, which is more or less "yes" to the first part, "no" to the  second.  I'm going to be done for a bit, so it's written hastily, but it should give some shape to the answer.  Your second part to the above comment didn't exist when I started updating the question.

I missed the fact that you're more or less doing the above already with respect to having a buffer and filling it, just not adding the extra byte room or assigning it to a String.  If the only thing you're doing with the string is sending it out through Serial, you can switch from println() to using write() with the size argument set to the correct number, in which case you don't need to terminate at all.


text:
ESP32 cam offline
Can the ESP32 cam be used with no internet connection.
I have my newly acquired ESP32-CAM up and running as per this really great tutorial:
https://randomnerdtutorials.com/esp32-cam-video-streaming-face-recognition-arduino-ide/
But I just realized the sketch has no HTML in it and must rely on internet access.
I need to stream video to my tablet when I don't have an internet connection.
Possible using the ESP32 Cam?

You could make your own WiFi-Network with the ESP32, just google for it. Then you'd have to connect your tablet to it and open the Website.

Why do you think, that the linked tutorial requires internet access?

When I shutdown my access to the internet (via my phone hotspot) the ESP32 CAM stops streaming.   But upon closer examination if I reboot the router as well.... even with no inter connection it works again.  Guess I have egg on my face.

Of course it's possible. Just write a sketch that does what you want. The camera operation has nothing to do with the internet. Only the pretty website that is coded into that sketch.


text:
Adding another flow sensor to sketch
Adding another flow sensor to sketch
I have a water flow sketch I use for my freshwater consumption.  I would like to adapt it to use for diesel fuel consumption.  The difference is with a diesel motor the fuel pump sucks more fuel than it burns from the fuel tank and simply returns the excess to the fuel tank.  ie there are 2 hoses from the fuel tank, one to the motor, and one back to the tank.  The difference between what went to the motor and what went back to the tank is how much fuel the motor burned.
So my plan is to have 2 flow sensors (Yf-s201), and subtract the out put of one from the other and print the difference.
I have a sketch that already works to print L/m and total L.  For one sensor on PIN D2.
I have defined another sensor on PIN D3.
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

byte sensorInterrupt2 = 1;  //11 = digital pin 3
byte sensorPin2       = 3;

My first road block is to print them individually. as is they both just add to a single total.
I have tried to just copy bits of code and add a "2" but I really don't have any programing knowledge so I am just stabbing in the dark.   I don't understand how to call upon the value the code has calculated.
This is the whole sketch:
/*
Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

Measure the liquid/water flow rate using this code.
Connect Vcc and Gnd of sensor to arduino, and the
signal line to arduino digital pin 2.

 */
// include the library code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,20,4);

byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

byte sensorInterrupt2 = 1;  // 1 = digital pin 3
byte sensorPin2       = 3;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 7.55;  //biger more / min

volatile byte pulseCount;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

unsigned long oldTime;

void setup()
{

  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
lcd.init();
lcd.backlight();
     lcd.begin(16, 2);
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("S.V. SAVANNAH");
   lcd.setCursor(0,1);
   lcd.print("DAY TANK FLOW METER");

  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached

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

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{

   if((millis() - oldTime) > 1000)    // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);

    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();

    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;

    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;

    unsigned int frac;

    // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space

    // Print the cumulative total of litres flowed since starting
    Serial.print("Output Liquid Quantity: ");
    Serial.print(totalMilliLitres);
    Serial.println("mL");
    Serial.print("\t");       // Print tab space
  Serial.print(totalMilliLitres/1000);
  Serial.print("L");

      lcd.clear();
      lcd.setCursor(4,0);
      lcd.print(int(flowRate));  // Print the integer part of the variable
      lcd.print("L/min ");

    // Print the cumulative total of litres flowed since starting
    lcd.setCursor(2,1);
    lcd.print("Total ");
  lcd.print(totalMilliLitres/1000.00);
  lcd.print("L");

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}'''

Your code currently does not use the second flow sensor. I guess you have problems in designing the code, so I try to walk you trough.
First let's look at the prerequisites, that are needed for the two flow sensors. You already have defined the pins of the flow sensors. You are also defining the number of the corresponding interrupts. In fact you don't have to do that. You can easily get the number of the interrupt through the function digitalPinToInterrupt(pin). So we are left with the pin definition. I would suggest using clearer names:
int flow_out_pin = 2;
int flow_in_pin = 3;

flow_out meaning leaving the tank, flow_in coming back into the tank.
Then in setup() we need to initiate the pins. You have this
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);

This can be then made shorter in one line per sensor:
pinMode(flow_out_pin, INPUT_PULLUP);
pinMode(flow_in_pin, INPUT_PULLUP);

Now we attach the interrupts to the pins:
attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

I used the mentioned function to get the interrupt number and changed the name of the ISR. Here comes a different principle, than your firstly intended way: I would let the sensors count in their own ISR and own variables and only calculate the difference to display it. For that we need to define our 2 ISRs:
void flowOutPulseCounter()
{
    flowOutPulseCount++;
}
void flowInPulseCounter()
{
    flowInPulseCount++;
}

The count variables of course need to be defined (globally at the top of the sketch):
volatile byte flowOutPulseCount = 0;
volatile byte flowInPulseCount = 0;

Now we have left the code in loop(), which calculates flowrate, fill level and such and displays them. First: When handling interrupt data in the main code, you want to absolutely minimize the time spend with the interrupts deactivated (since in that time you might miss pulses and thus introduce errors). Normally you would just copy the data into local variables, turn on the interrupts again and do the calculation with the local variables. Something like this (inside the millis() if statement):
// Detach interrupts
detachInterrupt(digitalPinToInterrupt(flow_out_pin));
detachInterrupt(digitalPinToInterrupt(flow_in_pin));

// copy pulse count variables
byte local_flow_out_count = flowOutPulseCount;
byte local_flow_in_count  = flowInPulseCount;

// reset pulse counter variables
flowOutPulseCount = 0;
flowInPulseCount = 0;

// Reattach interrupts
attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

// Do calculations using above local variables and display the results
...

For the calculations you would then calculate a flow rate and the total flow from each pulse count. With that you can then calculate the total net flow and the fill level.
Note: You might wanna change the variable type for the counters to unsigned int to get a greater margin, before they overflow, since that would mean incorrect results and it doesn't hurt you to use it.

Thanks for the great response.  I have worked through your suggestions, and I have got as far as:
void flowOutPulseCounter()
{
flowOutPulseCount++;
}
void flowInPulseCounter()
{
flowInPulseCount++;
}
But I get "a function-definition is not allowed here before '{' token" error. Which I don't really even remotely understand.

That means either you have put these functions into another function, which is wrong, or you have mismatched curly braces in the code above these functions

As chrisl already provided a very good answer, I am just adding some
notes here to complement it.
The variable pulseCount is only 8-bits. It will overflow if the flow
rate gets above 33.7 L/min. If the possibility exists that the
actual flow exceeds this rate, then, as pointed out in chrisl's answer,
you should use a 16-bit counter. If, on the other hand, you are sure
that this value cannot be exceeded, then you can keep an 8-bit counter,
and benefit from the fact that accesses to 8-bit values are atomic.
This means you do not need to ever disable interrupts:
// In global scope:
byte oldPulseCount;

// Within loop(), once per second:
byte newPulseCount = pulseCount;  // atomic read
byte pulseCountDifference = newPulseCount - oldPulseCount;
oldPulseCount = newPulseCount;  // save current value

then you compute the flow rate from pulseCountDifference. Note that
overflows of pulseCount are harmless, as the difference
newPulseCount - oldPulseCount wraps modulo 256 to the correct value.
Note also that pulseCount is never reset, as doing so could lead to
miscounting whenever an interrupt fires after pulseCount is read but
before it is reset.

// Note the time this processing pass was executed. Note that because
// we've disabled interrupts the millis() function won't actually be
// incrementing right at this point, but it will still return the value
// it was set to just before interrupts went away.
oldTime = millis();

This comment is wrong. The statement detachInterrupt(sensorInterrupt)
disables only an external interrupt. It does not disable interrupts
globally, and specifically does not disable the timer interrupt that
increments millis(). There is therefore no guarantee that the various
calls to millis() will return the same value within one iteration.
Instead, millis() should be called only once, and its value
remembered:
void loop()
{
    unsigned long now = millis();  // save this value
    if (now - oldTime >= 1000) {
        // ...
        oldTime = now;
    }
}

Note that I use >= for checking the delay: with the > operator the
period is at least 1001 ms.

flowMilliLitres = (flowRate / 60) * 1000;

This is incorrect. It should be
flowMilliLitres = (flowRate / 60) * (now - oldTime);

for the same reason that now - oldTime is used in the computation of
flowRate. It may be noted that this can be simplified to
flowMilliLitres = (1e3/calibrationFactor/60) * pulseCountDifference;

as the factors now - oldTime cancel out.


text:
Calculating the Distance between a Special Object and Center
I just want to detect a small object specified in the system and show the distance between it and the object. If I need to explain briefly; I want to detect a small object that I put on the foot of a bird when it approaches 10-15 meters to its cage and measure the distance between them. I plan to have a device that scans around, like a radar. When there is a special object approaching this tool 15 meters, I need to detect it and measure the distance between them. (for example, 12 meters now, and 9 meters after 3 seconds). I thought that if i use a very small (electromagnetic or infrared ray, etc.) signal emitted by the small object attached to the bird's foot, the continuously operating radar can detect this particular signal. Also, it should measure the distance between radar center and the signal. It's like a bluetooth device. But also, it should measure the distance between radar center and the signal.
But I could not find a sensor to do this. (I tried to explain briefly in the photo)

Do you think which product should i use or what should i do for this?
Thank you

How big a bird are we talking? Anything "active" will need a battery, and that will need a golden eagle to carry it on its ankle.

How long does it need to last?  A super cap is light and might last for minutes to hours.  But will eventually need an energy source.  Also, you never required a heading - only distance.  So any number of COTS technologies which indicate signal strength should work.

Dear @Majenko , Thank you for your comment. Unfortunately it’s not a golden eagle :( . I understood what you mean. I’ve been searching this subject. And I learnt that there are products to find out where homing pigeons went to by saving coordinates for weeks. I think saving enough energy in a small battery can be possible to do this. I just want it to work 2 or 3 hours

Dear @st2000 , Thank you for your comment. I want it to work 2 or 3 hours. And you're right about energy source. Do you think which product is the best to measure the distance in this situation? If you don't mind, could you please give a product name ?


text:
I am using an accelerometer as an input and a stepper motor as an output and it will have these weird delays after about 30 sec
I have a stepper motor (kysan 1124090) turning CW and CCW based on the y direction of my accelerometer(MU6090). I am using an Arduino uno. It works great but after about 30 seconds there will be these pauses in the communication between the accelerometer and the stepper motor every 3-4 seconds. I can turn rotate the accelerometer and the stepper wont move for about half a second. I am wondering if its a storage issue, where after a while it has stock piled so much data that it needs that delay to keep it alive? When I verify the sketch it says I am only using 31% of the program storage space and 27% of dynamic memory. Maybe there is a way to get rid of all the data i dont need every time i run through my loop to get rid of this problem? I am attaching the code along with this. If anyone has any advice or things I could try, that would be awesome. Thanks.
#include <Wire.h>

#include "Kalman.h"

#define RESTRICT_PITCH

Kalman kalmanX;
Kalman kalmanY;

double accX, accY, accZ;
double gyroX, gyroY, gyroZ;
int16_t tempRaw;

double gyroXangle, gyroYangle;
double compAngleX, compAngleY;
double kalAngleX, kalAngleY;

uint32_t timer;
uint8_t i2cData[14]; // Buffer for I2C data

Stepper stepper2(200, 8, 10, 9, 11);
int cantidad = 1;

int previous = 0;
void setup() {

  stepper2.setSpeed(350);
  Serial.begin(115200);
  Wire.begin();
  TWBR = ((F_CPU /400000L) - 16) / 2; // Set I2C frequency to 400kHz

  i2cData[0] = 7;
  i2cData[1] = 0x00;
  i2cData[2] = 0x00;
  i2cData[3] = 0x00;
  while (i2cWrite(0x19, i2cData, 4, false));
  while (i2cWrite(0x6B, 0x01, true));

  while (i2cRead(0x75, i2cData, 1));
  if (i2cData[0] != 0x68) { // Read "WHO_AM_I" register
    Serial.print(F("Error reading sensor"));
    while (1);
  }

  delay(100);

  while (i2cRead(0x3B, i2cData, 6));
  accX = (i2cData[0] << 8) | i2cData[1];
  accY = (i2cData[2] << 8) | i2cData[3];
  accZ = (i2cData[4] << 8) | i2cData[5];

#ifdef RESTRICT_PITCH // Eq. 25 and 26
  double roll  = atan2(accY, accZ) * RAD_TO_DEG;
  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  kalmanX.setAngle(roll); // Set starting angle
  kalmanY.setAngle(pitch);
  gyroXangle = roll;
  gyroYangle = pitch;
  compAngleX = roll;
  compAngleY = pitch;

  timer = micros();
}

void loop() {

  while (i2cRead(0x3B, i2cData, 14));
  accX = ((i2cData[0] << 8) | i2cData[1]);
  accY = ((i2cData[2] << 8) | i2cData[3]);
  accZ = ((i2cData[4] << 8) | i2cData[5]);
  tempRaw = (i2cData[6] << 8) | i2cData[7];
  gyroX = (i2cData[8] << 8) | i2cData[9];
  gyroY = (i2cData[10] << 8) | i2cData[11];
  gyroZ = (i2cData[12] << 8) | i2cData[13];

  double dt = (double)(micros() - timer) / 1000000;
  timer = micros();

#ifdef RESTRICT_PITCH // Eq. 25 and 26
  double roll  = atan2(accY, accZ) * RAD_TO_DEG;
  double pitch = atan(-accX / sqrt(accY * accY + accZ * accZ)) * RAD_TO_DEG;
#else // Eq. 28 and 29
  double roll  = atan(accY / sqrt(accX * accX + accZ * accZ)) * RAD_TO_DEG;
  double pitch = atan2(-accX, accZ) * RAD_TO_DEG;
#endif

  double gyroXrate = gyroX / 131.0; // Convert to deg/s
  double gyroYrate = gyroY / 131.0; // Convert to deg/s

#ifdef RESTRICT_PITCH
//Serial.print("kalAngle is:"); Serial.print(kalAngleX);
  if ((roll < -90 && kalAngleX > 90) || (roll > 90 && kalAngleX < -90)) {

    kalmanX.setAngle(roll);
    compAngleX = roll;
    kalAngleX = roll;
    gyroXangle = roll;
  } else
    kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt);

  if (abs(kalAngleX) > 90)
    gyroYrate = -gyroYrate;
  kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);
#else

  if ((pitch < -90 && kalAngleY > 90) || (pitch > 90 && kalAngleY < -90)) {
    //Serial.print("pitch:"); Serial.println(pitch);
    kalmanY.setAngle(pitch);
    compAngleY = pitch;
    kalAngleY = pitch;
    gyroYangle = pitch;
  } else
    kalAngleY = kalmanY.getAngle(pitch, gyroYrate, dt);

  if (abs(kalAngleY) > 90)
    gyroXrate = -gyroXrate;
  kalAngleX = kalmanX.getAngle(roll, gyroXrate, dt);
#endif

  gyroXangle += gyroXrate * dt;
  gyroYangle += gyroYrate * dt;

  compAngleX = 0.93 * (compAngleX + gyroXrate * dt) + 0.07 * roll;
  compAngleY = 0.93 * (compAngleY + gyroYrate * dt) + 0.07 * pitch;

  if (gyroXangle < -180 || gyroXangle > 180)
    gyroXangle = kalAngleX;
  if (gyroYangle < -180 || gyroYangle > 180)
    gyroYangle = kalAngleY;

#if 0 // Set to 1 to activate
  /*Serial.print(accX); Serial.print("\t");
  Serial.print(accY); Serial.print("\t");
  Serial.print(accZ); Serial.print("\t");

  Serial.print(gyroX); Serial.print("\t");
  Serial.print(gyroY); Serial.print("\t");
  Serial.print(gyroZ); Serial.print("\t");

  Serial.print("\t");*/
#endif

 // Serial.print(kalAngleX); Serial.print("\t");

 // Serial.print("\t");

 // Serial.print(kalAngleY); Serial.print("\t");

#if 0
  //Serial.print("\t");

  //double temperature = (double)tempRaw / 340.0 + 36.53;
  //Serial.print(temperature); Serial.print("\t");
#endif

  //Serial.print("\r\n");

int valuex = kalAngleX;
//Serial.print("Valx:"); Serial.println(valuex);

stepper2.step(valuex - previous);

  previous = valuex;

}

the accelerometer does not communicate with the stepper motor ... the accelerometer communicates with the arduino ... the arduino controls the motor

right sorry, i was skipping the middle step. Do you have any ideas for the problem I am running into?

a lot of beginners read these posts ... some would think that a sensor is directly connected to the motor

isolate the area of failure ... try making the motor position independent of sensor readings .... maybe use millis() to determine motor position ... see if it still pauses

how would millis() work, doesnt that just have to do with keeping track of time?

i have not examined your code logic in detail ... maybe one of the if statements is getting an unexpected value .... put in some debugging Serial.print() statements

millis()/1000 would give you seconds ... use the value to move the stepper motor ... it should move every second ... basically use anything other that the sensor data to keep the motor moving ... if it does not stop as it did before, then that means it was previously commanded to stop

yeah that makes sense, okay i will try to make this work. Thank you

I couldn't figure out how to move the motor only based on only the millis(), is there any more help you can provide?


text:
How can I get my LCD display to display Chinese and Japanese characters?
I'm making a project that requires me to display Chinese and Japanese characters on an LCD. However, the 16x2 LCD display I have does not seem to support displaying Chinese and Japanese characters.
If I do something like lcd.print("おはよう世界"); or lcd.print("简体中文测试");, it seems to display just a bunch of jumbled random characters (which I am assuming have their character values add up to the values of the characters in the code).
How can I get my LCD to display Chinese and Japanese characters?
Or, if there's no way to do it without buying a new one that supports it, where can I buy one?

Displaying Kanji or Chinese characters is way beyond the ability of an LCD that displays 5 pixel by 7 pixel characters.
To understand the limitations, take a piece of graph paper and draw out a set of 5x7 rectangles. See if you can define ANY recognizable Japanese or Chinese characters on your graph paper.
Maybe a couple of characters? (Then again, maybe not.)
You need a display with a lot more resolution, like an OLED graphics display. You are also struggling against a microcontroller that doesn't have support for Unicode. It's just not up to the job. You'd be much better off with a Raspberry Pi and a screen like a smart-phone color LCD screen. Install Linux and you can have native support for Unicode.
As others have pointed out, hiragana or katakana would be more practical, and there are some low-res LCDs that support those characters.

There are two ROMs available for those LCDs. One has Latin extended characters in 128-255. The other has Japanese hiragana (or maybe it's katakana, I forget). These Japanese characters can be displayed fine. Kanji is a no no of course, so is Chinese, both simplified and traditional. Select the right model of LCD and you get some Japanese.

This one has a single ROM, with what looks like a mix of extended Latin, Katakana and Greek. It can also display up to eight different user-defined glyphs.

Good point about Katakana/Hiragana, Majenko and Edgar Bonet. Those are a lot easier to manage. I should have specified that Kanji and Chinese were beyond a 5x7 LCD (And an Arduino) in my answer.

Your LCD uses a single byte for the character to display, so there are < 256 characters possible. 8 of them are userdefineable, the others are predefined in the LCD-ROM.
The Arduino IDE uses utf-8 code, which takes more than a single byte for all non-ascii characters like in your "おはよう世界".
Even if the character set contains the ones you want to display, you need an escape sequence to have them properly in your print statement.


text:
How to Set RTC in ES32 using NTP server?
I am working on ESP32 And want to set RTC from the NTP server. How can I get epoch value I have done this thing on CC3200 launchpad and used an NTP server library to obtain epoch value.

this snippet from setup() sets on esp32 the NTP for internal RTC and uses epoch seconds to set time to TimeLib library.
  configTime(gmtOffset_sec, daylightOffset_sec, "pool.ntp.org");
  time_t now = time(nullptr);
  while (now < SECS_YR_2000) {
    delay(100);
    now = time(nullptr);
  }
  setTime(now);

The ESP32 examples library in IDE examples folder has example SimpleTime.

Is configTime() a blocking function? Seems like it would have to be, seeing as how the Arduino is not a multi-tasking system.

@DuncanC, it is not blocking as you can see on the following while cycle. esp32 core is on esp32 RTOS SDK. arduino is one thread but configTime is a C function from SDK, so the function only activates SNTP