text:
Rising and falling edge on GPIO_STM32G4
I am working with STM32G491RE.I am giving pulse to GPIO pin from function generator. That pulse will be 2 msec on time and 8msec off time.I need to make flag high if the signal from function generator lost.
Can anyone suggest me how to do this?
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin==detect_Pin){
if(HAL_GPIO_ReadPin(detect_GPIO_Port,detect_Pin)==GPIO_PIN_SET){
 HAL_UART_Transmit(&huart2, (uint8_t *)"rising:",7, HAL_MAX_DELAY);
 }
else if(HAL_GPIO_ReadPin(detect_GPIO_Port,detect_Pin)==GPIO_PIN_RESET){
 HAL_UART_Transmit(&huart2, (uint8_t *)"falling:",8, HAL_MAX_DELAY);
 }
else
{
 HAL_GPIO_WritePin(led_GPIO_Port,led_Pin,GPIO_PIN_SET);
}

I tried with EXTI interrupt but If input is there from generator its detecting both rising and falling edge and if there is no signal from generator I am not getting  in to else condition.

1.If I want to make flag high for no signal from function generator,above image offtime also it considering as no signal.
can anyone suggest how to do?
Thanks

I do not know how to use the HAL API you are using. I will instead
suggest an approach based on the Arduino API, which is more suitable for
this site.
Take note of the current time on every transition you detect. When the
time since the last detected transition is longer than a predefined
timeout, you know the pulse train has stopped:
const uint8_t pulse_pin = 2;
const uint32_t pulse_timeout = 10;  // milliseconds

volatile uint32_t last_input_change;  // last time we detected a change

void on_input_change()
{
    last_input_change = millis();
}

void setup() {
    Serial.begin(9600);
    attachInterrupt(digitalPinToInterrupt(pulse_pin),
            on_input_change, CHANGE);
}

void loop() {
    // Avoid a data race while reading last_input_change.
    noInterrupts();
    uint32_t last_input_change_copy = last_input_change;
    interrupts();

    if (millis() - last_input_change_copy >= pulse_timeout)
        Serial.println("The pulse train stopped.");
}

Note that, for this to work, your whole code should be non-blocking,
which is a good practice in any case.


text:
How can I get servos to not brownout my Arduinos and power supply?
I have a problem with a project where one servo is resetting (browning out) two Arduino Pro Minis running 3.3v/8mHz. The two Arduinos are connected by SoftwareSerial on pins 9 and 10 and the slave sends yaw data to the master Arduino obtained from an MPU9250 breakout board. The power supply can supply 1 A of current. The servo is a small 2g servo that takes 3.3v at 50mA when moving (measured, not from the datasheet). Everything is hooked up on a breadboard. In case you're wondering, I am using an adaptation of the ServoTimer2 library to control the servos so as to not interfere with SoftwareSerial. I am baffled as to why one small servo is resetting two Arduinos. The Arduinos, along with the MPU9250, are only drawing 10mA. Could back EMF be causing the brownout?
In the past, I have done a similar circuit but with only one Arduino obtaining sensor data and not sending it over SoftwareSerial. This works completely fine with two servos, a Pro Mini, and an MPU9250 breakout board. This leads me to think it is some sort of software issue.
I have already received some guidance on the Arduino Discord stating to connect ceramic capacitors close to the servos, and this seems to sort of work, but I'm wondering if there might be a software way to do it with the least number of components possible.
Any help would be greatly appreciated!

RE: "Everything is hooked up on a breadboard" - How about some images of the breadboard setup?

RE: "This leads me to think it is some sort of software issue" - Can you show us the code, or is it top secret?

use a separate power supply for the motors

Note: Commonly you cannot use software to circumvent physics.
Your symptoms show that the initial current of the servo is too high for your power concept to maintain the voltage. Therefore your Nanos brown out.
An electric motor can easily take a multiple of its average current on acceleration. If blocked, and in the first moment it is blocked by the inertia, you can observe factors in low tens. From 50 mA to 1 A it's just a factor of 20...
Please note that servos often control their motors with PWM, and you measure only the average. During the "active" state the current is higher, and depending on the motor's inductive properties can have "strange" wave forms.
Additionally, each wire adds an inductive and resistive component in series with your Nanos and the servo. The shorter and thicker the wires, the better.
So your case looks quite simple, and you have options:

Decouple your power supply with appropriate capacitors. Ceramics with some tens of nF and an electrolyte or tantalum capacitor with some µF are common to provide the necessary current "reservoir" for the initial moment in different frequency ranges. Put them near the servo(s).
Use a separate power supply for the servo(s). Do not forget to connect the grounds. But also here you might need capacitor(s) to avoid browning out the servo.

You are seeing classic signs of power supply overload. Those motors can draw upto 10x there operating current when starting. Transients etc that are occuring are to fast for your meter to see but the electronics does. To view that you need a scope and a current probe. My recommendation is to get a larger power supply probably in the 3A range.

source: Stack Exchange

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

sort: votes


text:
Understanding ESP8266 OTA Updates: A Question on Limitations
I am currently researching OTA updates for ESP8266 firmware, and I have a question that I couldn't find an answer to:
Question: Is the number of OTA updates limited? According to the documentation, it states: "The flash chip size should be large enough to hold the old sketch (currently running) and the new sketch (OTA) at the same time." Does this mean that the old sketch always remains, and with each new update, the previous versions continue to exist? If so, does this imply that after multiple updates, the flash memory will eventually be full, preventing any further updates?
Thank you for your assistance.

No each update overrites the oldest one (if present) so there are only ever a maximum of 2 versions in flash

This statement takes mainly two reasons into account:

The OTA update needs a complete sketch that executes the update. Overwriting a running sketch with an update crashes in almost all cases.
An OTA update can be disrupted or fail, as a wireless connection is notoriously unreliable. The device needs a working sketch after such events.

That's why the device stores the new sketch in a space separated from the old sketch.
But as soon as the "download" is complete and hopefully checked (by a hash or other means of checksum) to be error-free and valid, the old sketch is not needed any more. The system "switches" from the old sketch to the new sketch, in your case the bootloader overwrites the old sketch with the new sketch, see the last part of the documentation you link to.
The space after the now running new sketch is again free for the next OTA update.
However, there is a physical limit caused by flash memory wear. Commonly this is far away from the number of OTA updates a device will have in its lifetime.

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


text:
How do I write efficient callback functions on a Teensy 4.0?
I am looking at refactoring my code by implementing callback functions in order to be able to reuse the abstract logic of other functions/classes.
However, I feel I need to learn more about the limits of callback functions on embedded systems like the teensy 4.0 I'm using. The reason I ask is because - if I'm correctly informed - std::function is adviced against on embedded systems due to memory overhead. Another reason for asking is that the functions I want to use for callback might run the risk of violating the principle of keeping callback functions short.
I've consulted the chapter devoted to embedded programming principles in Stroustrup's Programming: Principles and Practice Using C++. Unfortunately, he doesn't give advice on callback functions for embedded systems, specifically.
I understand I can simply rely on a trial and error methodology using function pointers, but figured I'd ask for your experience and advice before I rewrite a lot of code. In other words, I'm asking for good principles and guidelines.

I frequently use callbacks in embedded systems, on much less capable MCUs than the Cortex (328p f/ex). The call overhead is minor - a call through a pointer instead of calling direct. This page has a guide to callbacks on the Teensy.

Do your callbacks need to carry state (i.e. be functor objects holding data), or would you just be using naked functions (or non-capturing lambdas)?

@EdgarBonet Off the top of my head it'll primarily be naked functions, but It's possible I'll also need other types of use cases.

I have been using callbacks quite intensively on an Arduino Mega 2560,
for managing RS-485 messages. This board has roughly 8 times less flash
and 128 times less RAM than your Teensy. However, as the AVR core does
not support std::function, I used the good old C idiom for defining
callbacks:
void MyClass::register_callback(
        void (*callback)(some_type some_data, void *callback_data),
        void *callback_data);

It is up to the caller to nicely pack all the state needed by the
callback into a struct, and pass a pointer to this struct as the
last argument of register_callback(). The class will record both the
function pointer and the void* pointer. When the expected event
happens, the class calls the callback, giving it the saved void* as
its last argument. The callback then casts this pointer to a pointer to
the expected struct, and now it can access the state it needs.
Yes, this is a bit clumsy, but it is a tried and true way of handling
callback state in plain C. And the cost is marginal, especially for your
board that has orders of magnitude more resources than my Mega.
If you are afraid of the cost of std::function, I suggest you
implement a simple callback example using this method, then using
std::function, and you compare the memory usage. If the cost of
std::function turns out to be significant, you can always go the C
way. I suspect std::function will be just fine, and it really is more
convenient than handling the function pointer and the state as separate
arguments.

Interesting, I'll look into it. Thanks for your reply!


text:
Square wave generator generates a shorter pulse from time to time
I am  using an arduino Micro to generate 8 square waves on 8 pins. The idea is as follows: on pin 13 is the main square wave. It represents a certain BPM (beats per minute). The other 7 pins should give multiplications or divisions of that BPM.
It uses timer1 to trigger an interrupt at BPM/192 (this number is choosen to enable easy multiplications). It counts those interrupts and changes the states of the outputs when needed.
The codes seems to run fine for most divisions and most multiplications. However in certain cases like /2, there seem to be shorter pulses from time to time that throw the whole timing off.
Adding a short delay at the end of the loop seems to make the system more stable but still the short pulses appear from time to time.
Does anyone have an idea what the problem might be.

int counter[8] = {0,0,0,0,0,0,0,0}; //storing number of interrupts since last pulse
int trip[8] = {191,383,767,1535,3071,6143,12287,24575}; //number of interrupts needed for div/mult
int outputPin[8] = {13,12,11,10,9,8,7,6};

void setup() {

  for (int x = 0; x < 8; x++){

    pinMode(outputPin[x], OUTPUT);
    digitalWrite(outputPin[x], HIGH);

  }

  cli();
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A =2602; // 16000000 / (x * 8) -1
  TCCR1B |= (1 << WGM12);
  TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);//prescaler of 8
  TIMSK1 |= (1 << OCIE1A);
  sei();

}

void pulse(){

  for (int count = 0; count < 8; count++){

    counter[count]++;

  }

}

ISR(TIMER1_COMPA_vect){

  pulse();
}

void loop() {

  for (int y = 0; y < 8; y++){

    if(counter[y] > trip[y]){

      digitalWrite(outputPin[y],!digitalRead(outputPin[y]));
      counter[y] = 0;

    }

  }

  delayMicroseconds(100);

}

There are two issues here:

There is a data race on counter[]: it can be modified in interrupt
context while it is being read (or even modified) by the main
program.

Clearing counter[y] will make you loose ticks if for some reason
(say some interrupt) you do it a little bit late. You should instead
decrement it by trip[channel].

Here is a safe way of managing the counters:
volatile int counter[8] = {...};  // don't forget `volatile`

// Return whether this channel has tripped, and update the count.
bool tripped(int channel) {
    noInterrupts();
    bool did_trip = counter[channel] >= trip[channel];
    if (did_trip) counter[channel] -= trip[channel];
    interrupts();
    return did_trip;
}

void loop() {
    for (int y = 0; y < 8; y++)
        if (tripped(y))
            digitalWrite(outputPin[y], !digitalRead(outputPin[y]));
}

Notice that the critical section (the section with interrupts disabled)
lives within the for loop, rather than around it. It is better to have
multiple small critical sections rather than one large one.
Edit 1: You don't need the delay. It makes the system “more stable”
because it reduces the likelihood that, on any given TIMER1_COMPA
interrupt, the main program is accessing the counters (as it will spend
most of its time delaying). Adding this delay is in a way treating the
symptoms rather than the root cause of the data race.
Edit 2: Answering a comment. If you want the squares waves to stay
in sync, their frequency ratios should be integers. In your program,
this is almost, but not quite the case. For example, if you look at the
ratio between the first two channels:
channel 0: 191 interrupts per signal toggle
channel 1: 383 interrupts per signal toggle
ratio: 383 ÷ 191 ≈ 2.0052
The easy fix is to add 1 to every element of the trip array (384 ÷ 192
is exactly 2).

I tried your code. The pulses themselves seem to be stable now but now all square waves drift apart. None of the waves keeps in sync with the first one now.

@Janw: See amended answer.

Thank you that solved it!


text:
Unable to program with AVR ISP mkII under Linux
I just got an AVR ASP mkII external programmer and I am unsuccessfully trying to program my arduino with it.
All the settings in the IDE are correct. This is the error message that I am getting:
avrdude: usbdev_open(): cannot open device: Permission denied
Typing lsusb in a terminal, I am able to see the programmer.
Bus 001 Device 007: ID 03eb:2104 Atmel Corp. AVR ISP mkII

Do you have a udev rules for it (for example from platformio)? Is it working under root?

@KIIV I just opened the Arduino IDE from the Gnome GUI. Therefore I am guessing it is not root. As for udev.... I don't know much about it and I haven't touched it.

Does this answer your question? Arduino IDE Permision Denied For Upload, Ubuntu

@thebusybee the AVRISPmkII does not create tty device. So closing as a duplicate of that question won't help.

Please [edit] your question and add the command used for avrdude. You might need to enable the verbose output of the upload process in the preferences.

@thebusybee I am not explicitly using avrdude. I am using the AVR IDE, and I select "upload using external programmer".


text:
Not registering complete rotary encoder input
I am working on a project using a Rotary Encoder and I am trying to recieve the output from the encoder. As it stands I am able to get a count for degrees of change and direction of rotation, however depending on the speed the encoder spins I get a varying rotational output. For example if I rotate it slowly I can get 100's of counts for 180 degrees of rotation, but if I do so fast, then I could get 10 or so counts.
I believe my Arduino is running too slow to count each of the signals from the encoder, I measured the wavelength of a signal to be ~25 us when spun quickly but using the following code I found that my arduino is running at a loop rate of 200 loops per second.
void loop() {
  if(counter <= 1000){
    counter++;
    Serial.println(counter);
  }
}

The code for the Rotary Encoder:
Dt and Clk pin representing the 2 signal wires, both being pulled up
void loop(){

  //take clk pin state
  clkState = digitalRead(clkPin);

  //if clk state changed then wheel is rotating, react to rising edge to avoid double count
  if(clkState != preClkState && clkState == HIGH){
    Serial.write(digitalRead(dtPin));
    //check direction of spin based on dtpin
    if(digitalRead(dtPin)== HIGH){
      counter++;

      clockwiseDirection = true;
    }else{
      counter--;

      clockwiseDirection = false;
    }

    //output values
    Serial.write("Direction: ");
    if(clockwiseDirection){
      Serial.write("Clockwise | Counter: ");
    }else{
      Serial.write("Counter Clockwise | Counter: ");
    }

    Serial.print((int)counter);
    Serial.print("\n");

  }

  //update pre pos
  preClkState = clkState;

}

Thanks in advance.

Is it possible that all of the data printed to the Serial Monitor maybe slowing things down a bit?

you should use interrupts instead of digitalRead to ensure responsive scrolling. and yeah, don't print each detent.

Serial transmission takes time. Let's assume that you have set up the Serial with 9600 baud. This means 9600 bits per second. A single byte transmission commonly consists of a start bit, the data bits, and a single stop bit. This gives a total of 10 bits per byte. Therefore, your transfer rate is 9600 bits/s / 10 bits/byte = 960 bytes/s.
Estimating with a quick look at your source, each loop of your sketch sends about 40 characters, commonly encoded as a byte per character. And you claim that it achieves 200 loops per second, so the transfer rate is 40 bytes/loop * 200 loops/s = 8000 bytes/s.
Calculating back to bits/s results in a baudrate of roughly 80000 bits/s. So presumably you set up your Serial with 57600 or 115200 baud.

How to solve the issue?
Separate the acquisition of the encoder data from the transmission of the counter value. You can use interrupts, for example on the clock signal. However, this is not for the faint heart.
The Serial uses a transmission buffer of unspecified size. See the last paragraph of its documentation:

As of Arduino IDE 1.0, serial transmission is asynchronous. If there is enough empty space in the transmit buffer, Serial.write() will return before any characters are transmitted over serial. If the transmit buffer is full then Serial.write() will block until there is enough space in the buffer. To avoid blocking calls to Serial.write(), you can first check the amount of free space in the transmit buffer using availableForWrite().

You can check that the transmit buffer has room for your message. Send only, if there is enough room.


text:
Arduino IDE v 2.2.1 log file not limited in size (on Ubuntu 23.04)
I was learning/building with a new Arduino Nano ESP32 yesterday and left the Arduino IDE running overnight on Ubuntu 23.04 and it used all the space on my hard drive to write log files which broke my system till I booted in with a pen drive and removed some files to make space to then boot normally and find out what the problem was.
How can I limit the size of these log files, or even disable them?

I have been having the same issue. I think it might have something to do with the serial monitor being open, but I haven't found a fix yet.

Well, you could do it at the Unix level if you can't restrict it otherwise say using a volume quota, a script or other trick.


text:
Incorrect reading from DHT22 (on a Nano board)
I have rigged two different DHT22 sensors to an Arduino Nano board. Both temperature readings are more or less comparable but they produce very different humidity readings.
The sensors are:

Sensor No. 1 is an IDUINO-Version of the DHT22 on PIN 2
Sensor No. 2 is a DHT22 in Grove version from Seeeds Studio on PIN 3

The simple code is build on one of the basic examples as followed:
#include "DHT.h"
#define DHTPIN_2 2     // Digital pin connected to the DHT sensor_1
#define DHTPIN_3 3     // Digital pin connected to the DHT sensor_2
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
#define DHTTYPE_11 DHT11   // DHT 11  (AM2302), AM2321

DHT dht_1(DHTPIN_2, DHTTYPE);
DHT dht_2(DHTPIN_3, DHTTYPE);

void setup() {
  Serial.begin(9600);   //consider baud in serial monitor!
  Serial.println(F("DHT22 test!"));
  dht_1.begin();
  dht_2.begin();
}

void loop() {
  delay(5000);
  float h_1 = dht_1.readHumidity();
  float t_1 = dht_1.readTemperature();
  float h_2 = dht_2.readHumidity();
  float t_2 = dht_2.readTemperature();

  //Check if any reads failed and exit early (to try again).
  if (isnan(h_1) || isnan(t_1)) {
    Serial.println(F("Failed to read from DHT sensor_1!"));
    return;
  }

  // Check if any reads failed and exit early (to try again).
  if (isnan(h_2) || isnan(t_2)) {
    Serial.println(F("Failed to read from DHT sensor_2!"));
    return;
  }
  Serial.print(F("Humidities: "));
  Serial.print('\n');
  Serial.print(F("s_1: "));
  Serial.print(h_1);
  Serial.print(F(" s_2: "));
  Serial.print(h_2);
  Serial.print('\n');
  Serial.print(F("Temperatures: "));
  Serial.print('\n');
  Serial.print(F("s_1: "));
  Serial.print(t_1);
  Serial.print(F(" s_2: "));
  Serial.print(t_2);
  Serial.print('\n');
}

The resulting output on the Serial Monitor is:
Temperatures:
s_1: 25.30 s_2: 23.40
Humidities:
s_1: 6.20 s_2: 66.40
Temperatures:
s_1: 25.20 s_2: 23.40
Humidities:
s_1: 6.00 s_2: 66.10
Temperatures:
s_1: 25.10 s_2: 23.40
.
.
.

The humidity reading from sensor_1 seems defective, just having the 10th of the value of sensor_2. Is there a fix for that? Is it possible to re calibrate sensor_1 or is it broken?
Thank you!
Edit: swapping the sensors (suggested by jsotola)
The output results in:
Temperatures:
s_1: 22.60 s_2: 24.70
Humidities:
s_1: 67.80 s_2: 7.30

Its the sensor it seems.

swap the two sensors around

Thanks,@jsotola, i did and posted the results.

the other thing to do is to connect only one sensor at a time

One sensor at a time delivers the same results as above (depending on which sensor is connected). The IDUINO-DHT22 still has this very low value for humidity returned.

The difference in humidity readings may be traced to any number of reasons including faulty parts, incorrect programming or low voltages (please post at what voltage you are running the sensors at) to name a few.
Let us speculate that one of the sensors is reporting relative humidity and the other absolute.  Absolute humidity does not consider temperature where as relative does.  From this web site we get the following conversion equation:

This equation converts relative humidity to absolute. Finding the saturation vapor pressure measured in pascal is not trivial.  So we will use this web site to calculate this value.
Let us use the sample:

Temperature 1: 22.60 C
Temperature 2: 24.70 C
(assumed) Relative Humidity: 67.80 %
(assumed) Absolute Humidity: 7.30

So, average temperature is 23.65 C.
Using this temperature and the above web page, the vapor pressure is 2923 PA.
AH = (67.80 x 2923) / (462.5 x (273.15 + 23.65) x 100)
AH = 0.014437 Kg/(meter cubed)
As absolute humidity is normally written as grams per cubic meter:
AH g/(meter cubed) = 0.014437 * 1000 = 14.43 g/(meter cubed)
14.43 is not 7.30.  Consider your options.  Check your circuit, voltages and software (does varying the amount of time between samples result in different values). Also consider running more tests in better conditions (placing both sensors inside the same sealed container over a long period of time to mitigate exposure to different conditions).

Added later...
Evidently problems with the DHT11 humidity sensor is a known problem:

Arduino.cc forum
Partical.io forum
Raspberry Pi forum
Another from Arduino.cc form

Thank you so much @st2000 for this detailed answer and the good hints on how to proceed! What I checked: The voltage on the USB to the Nano is 5.06V with 0.023A (no difference if one or both sensors are connected). I tried an USB hub with additional power, no effect. I set the delay(10000), which doubled the time but had no effect. I put the whole setup into a plastic container. After 30 minutes of equilibration the humidity readings are keeping this difference. The temperature however is now 0.1° apart :) . You clearly ruled out that the sensor is reporting AH instead of RH.

The specifications for this sensor in the link above states that it reports RH.
This leaves the programming. Not sure if I am able to go into the DHT.h. I assume the problem is still with the sensor. Coming back to my initial question: is it possible to redo the calibration on that one?

I meant to check the voltage provided the DHT22 sensors. Some Arduinos run at 3.3V and others at 5V. Somewhere I read the DHT22 runs better at the higher voltage. I see the Alexnd webpage says 5V and the Grove web page says 3.3 to 5V.  LOL. Also, you may have a bad sensor. Do you have another to swap out with? Lastly, I've had bad luck w/DHT22 sensors too and switch to Sillicon Lab Si7021 sensors.

Oh! Something you might try. You didn't provide a schematic. But if the internet is anything to go by, about 33% of DHT22 projects posted place a 10K pull up resistor on the DHT22's data pin. This is because most serial interfaces like this one use a open collector output so that multiple devices can share a single digital wire. What about the other 77%? Well, the driver should activate an internal processor pull up resistor. But, these resistors very widely. So, try adding a 10K pull up resistor the the digital pin of the problematic DHT22 ... just to see what happens.

I added some links to some forum discussions about the DHT22 humidity sensor. There are more good suggestions in some of these if you want to go the distance.  But I'd check the voltage at the sensors, I might try the pull up (but I think there's only a slim chance that will work) finally I would switch to some of the recommended sensors and buy from a well established company that has a community of uses who you can ask questions of.

Thanks @st2000 for the further input. As for the additional 10k resistor: The IDUINO version of the DHT22 comes with this little break out board which I assume takes care of that. Like in the schematic here from makerguides.com, such one is not necessary. I am going to try to supply this sensor with a different voltage on the weekend and check out your suggested links. Still I guess it is just broken.


text:
We have Arduino IDE code that needs to stop after a set number of "revolutions"
We have Arduino IDE code that oscillates a plate on a lead screw powered by stepper motor to move back and forth.
We have the lead screw move 8 mm in one direction, then 8 mm in the opposite direction, for a total displacement of 16 mm. After this movement we have a counter that will then count as 1 "revolution" essentially. After reaching a specified count that program will stop.
Currently the program continues to run indefinitely. Any help/suggestions would be appreciated.
// Include the AccelStepper library:
#include <AccelStepper.h>

// Define stepper motor connections and motor interface type.
// Motor interface type must be set to 1 when using a driver:
#define dirPin 2
#define stepPin 3
#define motorInterfaceType 1

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

void setup() {
  // Set the maximum speed and acceleration:
  stepper.setMaxSpeed(40000);
  stepper.setAcceleration(20000);
}

void loop() {
  static int counter = 0; // Initialize a counter variable and start at 0

  // Set the target position:
  stepper.moveTo(400); // is in steps. setting to default

  // Run to target position with set speed and acceleration/deceleration:
  stepper.runToPosition();

  delay(0);

  // Move back to zero:
  stepper.moveTo(0);
  stepper.runToPosition();

  delay(0); //microseconds
  counter++; //adds 1 to the counter

  if (counter >= 2) {
    return; //exit the loop
  }
}

IED means "improvised explosive device"

IED disambiguation

What is "IED"? Do you mean IDE? Or intelligent electronic device? Or Industrial Emissions Directive? Or something else?

if (counter >= 2) {
    return; //exit the loop
  }

The return statement will end the loop, but the loop function is called over and over repeatedly.  So it will just start over again.
There are a few possibilities here.  You can replace the return statement with while(1); which will lock up execution there until the board is reset.
If you don't need the loop function to repeat ever then you can simply move all of your code into the setup function as it will only run once.  Then the loop function can just be empty.
And lastly, you could add a boolean variable and put the code you want to run only sometimes under an if statement that checks that variable.  At the end of the process you set the variable to false to stop the other code from running.  This would allow you to add code later to set it back at the press of a button or something in case you wanted the option to start the process again.
bool running = true;
void loop(){
  if(running){
      // do things
  }
  if (counter >= 2){
    running = false;
  }
}

exit(0) and abort() should also work. On AVR at least they are equivalent to while(1);, while more explicit about the intent.

I thought exit(0) was broken?  Why did I think that?  Was it ever?


text:
Impossible to install the esp_camera library
I cannot install the esp_camera library. When I try to add the .zip, I get "does not contain a valid library.
Everything about this ESP-32 Cam seems to rely on that library, and I can't find a way to install from https://github.com/espressif/esp32-camera or any other way.
Thanks.

It's not a "library" in the way that the Arduino system uses the term. That is, it's not designed to be placed under <sketchbook>/libraries directory way typical Arduino libraries are.
The good news is that you don't need to install it, because you already have it. It comes as part of the SDK files packaged into the ESP32 Arduino core as it is installed through the boards manager.
You'll find the header various places under the <arduino15>/packages/esp32/hardware/esp32/<version-number>/tools/sdk/esp32<architecture>/include/esp32-camera/driver/include/esp_camera.h where arduino15 refers to this, version refers to whatever version of the board package you have installed, and architecture is nothing, or c2, s3, or various other related esp32 suffixes.
The bulk of the code being in <arduino15>/packages/esp32/hardware/esp32/<version>/tools/sdk/esp32<architecture>/lib/libesp32-camera.a

Thank you. It took a bit of time to grasp the difference between platforms when still using Arduino IDE.


text:
Sparkfun canbus shield with LSM6DS33 dual SPI problem
Hello fellow arduino users! I have a question regarding using the Sparkfun Canbus shield in conjunction with the LSM6DS33 sensor on a dual SPI configuration. I have managed to get theese two to initialize but after reviewing the data it seems that the accelerometer is sending wrong readings... I am guessing the SPI devices mess with each other. Any idea on how to fix this? I am using an UNO R3 and here is the code:
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <Canbus.h>
#include <TinyGPS++.h>
#include <defaults.h>
#include <global.h>
#include <mcp2515.h>
#include <mcp2515_defs.h>
#include <Keypad.h>
#include <Adafruit_LSM6DS33.h>
#define LSM_CS 9
#define LSM_SCK 13
#define LSM_MISO 12
#define LSM_MOSI 11
Adafruit_LSM6DS33 lsm6ds33;
TinyGPSPlus gps;
SoftwareSerial ss(3,2);
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad membrane = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
String s;
int IATMP;
float MAF;
int VSPD;
int RPM;
float MAF2=0.0;
float DeltaMAF=0.0;
char iatbuffer[64];
char mafbuffer[64];
char vspdbuffer[64];
char rpmbuffer[64];
unsigned long currtime;
unsigned long deltatime;
const unsigned char UBLOX_INIT[] PROGMEM={
0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A
};

//********************************Setup Loop*********************************//
void setup() {
  ss.begin(9600);
  //Initialize Serial communication for debugging
  Serial.begin(115200);
  while (!Serial){
    delay(10); }
  for(unsigned int i=0;i<sizeof(UBLOX_INIT);i++){
    ss.write(pgm_read_byte(UBLOX_INIT+i));
    }

  if(Canbus.init(CANSPEED_500))  /* Initialize MCP2515 CAN controller at the specified speed */
  {

    Serial.println(F("CAN Init Ok"));
    delay(1500);
  }
  else
  {

    Serial.println(F("Can't init CAN"));
    return;
  }

if (!lsm6ds33.begin_SPI(LSM_CS, LSM_SCK, LSM_MISO, LSM_MOSI)) {
    Serial.println(F("Failed to find LSM6DS33 chip"));
    while (1) {
      delay(10);
    }
  }

Serial.println(F("LSM6DS33 Found!"));
lsm6ds33.setAccelRange(LSM6DS_ACCEL_RANGE_2_G);
lsm6ds33.setGyroRange(LSM6DS_GYRO_RANGE_125_DPS);
lsm6ds33.setAccelDataRate(LSM6DS_RATE_12_5_HZ);
lsm6ds33.setGyroDataRate(LSM6DS_RATE_12_5_HZ);
lsm6ds33.configInt1(false, false, false);

/*int i=0;
char input = membrane.getKey();
char usrid[4]={0};
while(!input){}
if (input){
  usrid[i]=input;
  i++;
  }
input = membrane.getKey();
while(!input){}
if (input){
  usrid[i]=input;
  i++;
  }
input = membrane.getKey();
while(!input){}
if (input){
  usrid[i]=input;
  i++;
  }
input = membrane.getKey();
while(!input){}
if (input){
  usrid[i]=input;
  i++;
  }
s= String(usrid);
*/

}

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

while(ss.available()>0){

gps.encode(ss.read());
if(gps.location.isUpdated()){
sensors_event_t accel;
sensors_event_t gyro;
sensors_event_t temp;
lsm6ds33.getEvent(&accel, &gyro, &temp);
currtime=millis();
Serial.print(s);
Serial.print(",");
Canbus.ecu_req(MAF_SENSOR,mafbuffer);
      MAF2=MAF;
      MAF = atof(mafbuffer);
    DeltaMAF=MAF-MAF2;
     // Serial.print("Engine RPM: "); //Uncomment for Serial debugging
      Serial.print(mafbuffer);
      Serial.print(F(","));
      Serial.print(DeltaMAF);
      Serial.print(F(","));
      delay(10);
Canbus.ecu_req(VEHICLE_SPEED,vspdbuffer);
    VSPD = atoi(vspdbuffer);
    //Serial.print("Engine RPM: "); //Uncomment for Serial debugging
      Serial.print(vspdbuffer);
      Serial.print(F(","));
      delay(10);
Canbus.ecu_req(IAT,iatbuffer);
    IATMP = atoi(iatbuffer);
    //Serial.print("Engine RPM: "); //Uncomment for Serial debugging
      Serial.print(iatbuffer);
      Serial.print(F(","));
      delay(10);

Canbus.ecu_req(ENGINE_RPM,rpmbuffer);
    RPM = atoi(rpmbuffer);
    //Serial.print("Engine RPM: "); //Uncomment for Serial debugging
      Serial.print(rpmbuffer);
      Serial.print(F(","));
      delay(10);
     if (RPM>800){
      Serial.print(F("idling"));
      Serial.print(F(","));
      }else{
        Serial.print(F("running"));
        Serial.print(F(","));
        }

Serial.print(accel.acceleration.x);
Serial.print(F(","));
Serial.print(accel.acceleration.y);
Serial.print(F(","));
Serial.print(accel.acceleration.z);
Serial.print(F(","));
Serial.print(gyro.gyro.x);
Serial.print(F(","));
Serial.print(gyro.gyro.y);
Serial.print(F(","));
Serial.print(gyro.gyro.z);
Serial.print(F(","));
Serial.print(temp.temperature);
Serial.print(F(","));
Serial.print(gps.location.lat(), 6);
Serial.print(F(","));
Serial.print(gps.location.lng(), 6);
Serial.print(F(","));
deltatime=millis()-currtime;
Serial.println(deltatime);

}
}
}


text:
Having an issue conveying array values properly
this is my first time asking a question here, sorry in advance if this is a poor way to ask this question.
I'm at an intermediary point in coding a program, and at this stage I'd like my byte information which I'm inputting into my serial monitor to take the places of my array elements. I'm able to do so, but when I try to use a 5 digit input, I only get a 4 digit input in return.
It seems like my Serial.available() == 4 loop is preventing my Serial.available() == 5 loop from operating. Would there be a simple modification I could make to allow a 5 digit result from a 5 digit input, and a 4 digit result from a 4 digit input? I've tried many things and Chat GPT seems to think the current code should work, but it doesn't. Here's the code:
int fiveArray[5];
int fourArray[4];
const char* colors[] = {"black ", "brown ", "red ", "blue ", "yellow ", "orange ", "white ", "gold ", "green ", "purple "};

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

  Serial.print("Input a number value: ");
  Serial.println();
}

void loop() {
  if (Serial.available() ==5 ) {
    char tempArrayFive[6];
    Serial.readBytes(tempArrayFive, 6);
    tempArrayFive[5] = '\0';

    for (int i = 0; i < 5; i++) {
      fiveArray[i] = tempArrayFive[i] - '0';
    }

    Serial.print("Color Value: ");
    for (int i = 0; i < 5; i++) {
      Serial.print(colors[fiveArray[i]]);
    }
    Serial.println();

  }
  if (Serial.available() == 4 ) {
    char tempArrayfour[5];
    Serial.readBytes(tempArrayfour, 5);
    tempArrayfour[4] = '\0';

    for (int i = 0; i < 4; i++) {
      fourArray[i] = tempArrayfour[i] - '0';
    }

    Serial.print("Color Value: ");
    for (int i = 0; i < 4; i++) {
      Serial.print(colors[fourArray[i]]);
    }
    Serial.println();
  }
}

"It seems like " - great observation, sending one byte (10bits with start and stop bits) using 9600baud per second takes around 1ms. On the other side Arduino on 16MHz during that time can handle 16000 instruction cycles - my guess is over 200 loops() between 4th and 5th character...

Can you please include a sample of what you are sending from the Serial Monitor and what line ending you have set there? Your current code doesn't make much sense to me. As KIIV wrote you have a race condition between the two if statements, but you also read 6 (and 5) bytes but you overwrite the last one with zero for string termination. You talk about byte data, but from your code it seems, that you are using ASCII encoded text (important difference when handling the data)

OT concerning ChatGPT: Never trust a chat bot, it has no idea about programming, it is just good at putting words together. Do not mix perfect grammar and wording with knowledge!

"this is my first time asking a question here": Since you are supposedly a intelligent person, you want to take the [tour] and read "[ask]" as well as other pages of the [help].

Yes, if you send 5 bytes to the Arduino then they will arrive one at a time.  When the 4th byte arrives then the if (Serial.available() == 4 ) statement is true and it runs that code.  That code reads from the buffer which means that the part that checks for 5 bytes will never be able to run.  There will always be 4 before there is 5.
A better idea would be to send your bytes with a start and end marker.  The program on the Arduino will read bytes and collect them in an array until it sees the end marker.  Then you can count how many bytes you have received if you want to take different actions depending on that number.
Here's a nice thread on handling Serial data:  https://forum.arduino.cc/t/serial-input-basics-updated/382007

I have a post here which discusses handling incoming serial data. Also here on Stack Exchange.
For handling serial input like you are trying to do I suggest using an "end of line marker" like newline (which the Terminal Monitor in the IDE will do for you automatically).
Then it's just a case of seeing whatever-it-was you got before the newline. Example code:
/*
Example of processing incoming serial data without blocking.

Author:   Nick Gammon
Date:     13 November 2011.
Modified: 31 August 2013.

Released for public use.
*/

// how much serial data we expect before a newline
const unsigned int MAX_INPUT = 50;

void setup ()
  {
  Serial.begin (115200);
  } // end of setup

// here to process incoming serial data after a terminator received
void process_data (const char * data)
  {
  // for now just display it
  // (but you could compare it to some value, convert to an integer, etc.)
  Serial.println (data);
  }  // end of process_data

void processIncomingByte (const byte inByte)
  {
  static char input_line [MAX_INPUT];
  static unsigned int input_pos = 0;

  switch (inByte)
    {

    case '\n':   // end of text
      input_line [input_pos] = 0;  // terminating null byte

      // terminator reached! process input_line here ...
      process_data (input_line);

      // reset buffer for next time
      input_pos = 0;
      break;

    case '\r':   // discard carriage return
      break;

    default:
      // keep adding if not full ... allow for terminating null byte
      if (input_pos < (MAX_INPUT - 1))
        input_line [input_pos++] = inByte;
      break;

    }  // end of switch

  } // end of processIncomingByte

void loop()
  {
  // if serial data available, process it
  while (Serial.available () > 0)
    processIncomingByte (Serial.read ());

  // do other stuff here like testing digital input (button presses) ...

  }  // end of loop

In your case, you would put code in the process_data function to turn the input text into a number and then do something with that number.
I'm surprised ChatGPT didn't point out my code <grin> but maybe you asked it a too-specific question.

I'd just point out that without a line-terminator character (like newline) then your code will be permanently out of step with incoming data if it starts in the wrong place. For example:
123456789

Depending on the speed at which that arrives, are we seeing 123 followed by 456? Or 12 followed by 34? Or 1234 followed by 5678? The end-of-line delimiter is really essential to avoid those ambiguities.
Or if the code happens to start running after you have sent the 1 but before the 2 it would think you sent 234 rather than 123 and then every other number would be out by one position.


text:
How to use an external 32kHz crystal for ESP32 S3 with Arduino IDE?
I want to use an external 32kHz crystal for RTC with ESP32 S3, but I didn't see any example or tutorial for Arduino IDE, Even when I asked ChatGPT, it gave me some example but the code gave library errors. I don't understand why there is no RTC example in the Arduino IDE.
I have designed a PCB with this SCH for RTC. But I don't know how I can activate an external 32 KHz crystal with Arduino IDE. Please tell me how.

From the ESP32-S3 documentation in section 2.4.2:

ESP32-S3 supports an external 32.768 kHz crystal or an external signal (e.g., an oscillator) to act as the RTC
sleep clock. The external RTC clock source is used to improve the timing accuracy and thus reduce the average
power consumption, but will not affect the functionality.

This document also contains a schematic:

... it is assumed that the schematic in the question is that of the ESP32-S3-WROOM module accounting for the differences between the two schematics.
The wording in the document infers there is only a counter to track / control the processor's sleep state.
This is further enforced by this question / answer found in electronics.stackexchange.com:

The ESP32 RTC module only has a timer that runs even in hibernation mode as well as some RAM that it can retain in deep sleep mode...
... There's no "wall clock" or "calendar" in the ESP32 RTC module.

If still interested in implementing a "wall clock" using the ESP32-S3, the same stackexchange question / answer offers the following:

The ESP32 does not have a real time clock - you cannot tell it to wake up at a particular time. It does have a timer that can wake it from deep sleep after a given time.
You can use the deep sleep wake up timer like this:

esp_sleep_enable_timer_wakeup((uint64_t)sleepTimeSeconds * 1000000);
esp_deep_sleep_start();

You set the sleep timer with esp_sleep_enable_timer_wakeup. The time period is in microseconds. With the timer set, the ESP32 will automatically wake up after the set time period.

Code will then have to be written to pull the last time from the ESP32-S3's nonvolatile memory, increment it by 1 second, store it back into nonvolatile memory and put the processor back to sleep for 1 second.

This is not a simple task: you have to recompile the Arduino core with the external RTC enabled.
Basically, you have to properly set the CONFIG_RTC_CLK_SRC option in kconfig file. You should start to read from here, and practising with ESP-IDF configurator.
I successfully completed this operation for the ESP32-S2 few years ago, but the procedure is very similar. Good luck.


text:
Large arrays crash the arduino
I have three large PROGMEM arrays, in order to store musical notes for a song. One array is the notes, one is the note durations, and one is the pause after the note.
The first array is an int one and the other two are floats. The program works, but after a specific number of elements, the arduino crashes. Meaning, I upload the program without problems, but the device does nothing.
When I have 227 elements (in all three arrays) obviously, the program works. If I increase the number  of elements to 228, nothing happens when I upload...
When the IDE says avrdude: 10606 bytes of flash verified then everything works. When the size gets increased to 10616, everything crashes. Is this normal behaviour?
EDIT: The code is trivial, the only important part of the code is this:
int number_of_stored_values_in_MelodyArray = sizeof(Crash_Melody) / sizeof(int);
int Melody_Array[number_of_stored_values_in_MelodyArray];
memcpy_P(Melody_Array, Crash_Melody, sizeof Melody_Array);

I am using memcpy_P() in order to copy the arrays from PROGMEM to RAM.
I do this for the int and the two float arrays. With 221 elements in each array, I guess I am out of RAM.
The reason I have an array for the pause as well, is because I am using an online midi to tone() converter and that is the format that it uses. So I have to stick to that format.
I think if I did the assignment incrementally - like for example copy only 20 elements from the array, play the song, then repeat until the end, I would have no problem.
Is there a way for memcpy_P() to specify not the whole array to copy, but index them? Does it take a starting index value?
EDIT 2:
This is a snippet of code after trying Edgar Bonnet's approach.
int number_of_stored_values_in_MelodyArray = sizeof(My_Melody) / sizeof(int);
for (int i = 0; i < number_of_stored_values_in_MelodyArray; i++)
{
  int note = pgm_read_word(&My_Melody[i]);
  float duration = pgm_read_word(&My_noteDurations[i]);
  float pause_duration = pgm_read_word(&My_Delay[i]);
  playMelodyExtended2(note, duration, pause_duration, number_of_stored_values_in_MelodyArray, 10, 400);
}

int playMelodyExtended2(int melody, float noteDuration, float pauseDuration, int number_of_notes, int music_pin, int delay_var)
{
  for (int thisNote = 0; thisNote < number_of_notes; thisNote++)
  {
    tone( music_pin, melody, noteDuration );
    delay( pauseDuration );
    noTone(music_pin);
  }

  delay(delay_var);
}

EDIT 3:
This is the newest iteration of the code:
 int number_of_stored_values_in_MelodyArray = sizeof(My_Melody) / sizeof(int);
 for (int i = 0; i < number_of_stored_values_in_MelodyArray; i++)
 {
    int note = pgm_read_byte_near(&My_Melody[i]);
    note << 8;
    note += pgm_read_byte_near(&My_Melody[i+1]);
    float duration = pgm_read_float_near(&My_noteDurations[i]);
    uint16_t pause_duration = pgm_read_byte_near(&My_Delay[i]);
    pause_duration << 8;
    pause_duration += pgm_read_byte_near(&My_Delay[i+1]);
    playMelodyExtended2(note, duration, pause_duration, number_of_stored_values_in_MelodyArray, 10, 400);
  }

int playMelodyExtended2(int melody, float noteDuration, uint16_t pauseDuration, int number_of_notes, int music_pin, int delay_var)
{
  for (int thisNote = 0; thisNote < number_of_notes; thisNote++)
  {
    tone( music_pin, melody, noteDuration );
    delay( pauseDuration );
    // stop the tone playing:
    noTone(music_pin);
  }

  delay(delay_var);
}

why are duration and pauses represented by floats? ... they are not floats in music notation

What Arduino are you using? Could you share your code (without the array contents)?

also share the messages in the arduino IDE ... copy the text and paste into your question ... do  NOT use a screenshot ... do not put in a comment

the three arrays can be of type byte ... you only need two arrays ... a pause is just an unvoiced note ... use value 0 for pauses

As long as the last message of the compile and link tells you that you don't fill the flash over 100%, everything is fine. Anyway, please [edit] your question and provide a minimal, reproducible, and complete example. It can consists of just a big enough array and empty setup() and loop(). Add the output log.

Which Arduino? This is kind-of important. Assuming you have 32k of programmable memory (for example, on the Uno) then 2280 bytes of array should not crash it. I would be wondering about your code, frankly. The code you didn't post.

When the IDE says avrdude: 10606 bytes of flash verified then everything works. When the size gets increased to 10616, everything crashes. Is this normal behaviour? No, of course not.

I updated the question.

Is there a way for memcpy_P() to specify not the whole array to copy, but index them?  yes, well you could do: memcpy_P(&Melody_Array[10], Crash_Melody, 10); to get 10 bytes, but what Edgar Bonet said is a much better solution. Just access each note one at a time. There is no point in making the code complex by getting chunks of notes.

With your "Edit 2": Looks like the wrong number of bytes are being read for your floats or some number format conversion issue produces basically random numbers for your durations. Try pgm_read_float for reading the floats.

@orithena Thanks! Tried it as well, but now I hear a periodic beeping. All the beeps and pauses between are the same... I also tried pgm_read_byte_near() for the int variable, but with the same results...

@user1584421 This sounds as if there are some conversion issues. By using the pgm_read_* methods, you are basically saying "Read n bytes from Progmem and just put the bits into the variable". That means you need to know which bitsize the values are in your Progmem array, how many bits are read by the pgm_read_* methods, how many bits are in the target variable and whether it is a signed int, unsigned int or IEEE768-formatted float. Try to output the numbers (Serial.println as first line in playMelodyExtended2, outputting all arguments) and compare them to your input arrays.

@user1584421 It may also be a good idea to use the type int16_t, uint16_t, int32_t or uint32_t instead of a plain int. int actually is an alias, denoting the "standard int" for the CPU/platform you're compiling for; using one of the types above, you'll always know the bitsize of your variable. But this is a problem far off your original question, so a new question might be a good idea here (please also post the code that creates the PROGMEM array, as there might be some clues in there).

In the edited version of your question, you wrote:

I am using memcpy_P() in order to copy the arrays from PROGMEM to
RAM.

The whole purpose of PROGMEM is to avoid having to store the data in
RAM. If you copy the arrays to RAM, you are defeating PROGMEM. Your
Arduino has much more Flash than RAM, and it will crash if you eat up
all the RAM. This is why the PROGMEM optimization is valuable whenever
you have large arrays of constant data.
The proper way to use those arrays is to copy to RAM one element at a
time: get the data for the next note you have to play, then play it,
then move to the next one. E.g.:
for (int i = 0; i < melody_length; i++) {
    int note = pgm_read_word(&Crash_Melody[i]);
    // etc...
}

Copying small chunks to RAM, as you suggest in your question, would make
the code more complex and add absolutely no value.

Edit: In the second edit of your question, you have this:
float duration = pgm_read_word(&My_noteDurations[i]);

What this does is:

read the first two bytes of My_noteDurations[i] (which is a
four-byte quantity, thus you are truncating it)
interpret that as an integer (which it is not)
convert that to float

The result will have little to do with the original number. The correct
way to read a float from PROGMEM is to use pgm_read_float().
That being said, I see now that you use this number as a parameter for
delay(). Given that this function takes an integer, there is no point
in storing the delay as a float. This will only add a (somewhat costly)
float-to-integer conversion to your program, with no added benefit.
Also, since the delays are likely to be less than 65 seconds, a
16-bit unsigned integer should be enough.
Further down, you have this:
for (int thisNote = 0; thisNote < number_of_notes; thisNote++)
{
  tone(music_pin, melody, noteDuration);
  delay(pauseDuration);
  noTone(music_pin);
}

I fail to see the purpose of this loop. You are repeating each note
a number of times that is equal to the total number of notes in the
song. Why?

Answer to edit 3: there are a few issues I can see in this version
of the code.

Consistency of the data types: in the previous version, it looked
like the pause durations were floats. Now they are integers. You have
to make sure you use the pgm_read_*() function suitable for the
actual data type of the array.

Reading by bytes: there is no point in reading a 16-bit integer one
byte at a time: use pgm_read_word() to read it all at once. Reading
byte by byte only makes the code more complex and increases the
chances of bugs. In fact, your way of reconstructing the numbers is
buggy.

The loop in playMelodyExtended2() makes no sense to me. Please, try
removing it.

Here is what I suggest at this point:
for (int i = 0; i < number_of_stored_values_in_MelodyArray; i++)
{
    int note = pgm_read_word(&My_Melody[i]);
    float duration = pgm_read_float(&My_noteDurations[i]);
    uint16_t pause_duration = pgm_read_word(&My_Delay[i]);
    tone(10, note, duration);
    delay(pause_duration);
}

This snippet makes some assumptions about the rest of your code, and
specifically about the way your arrays are defined. If these assumptions
are incorrect, this will not work. Thus, I second @orithena's comment
and urge you to post a full, testable version of you sketch (three notes
would be enough).

Thanks! I tried your approach but it didn't work. I have posted the code in my question. All I hear is a constant buzz.

Thanks Edgar!  I tried pgm_read_float() as well, but all I heard was a periodic beeping. All the beeps and pauses between are the same... I also tried pgm_read_byte_near() for the int variable, but with the same results. I will try to trim the float array, since delay() receives only ints... As for why the code is like that.... Yes, I am iterating for every number of notes in the melody. I have found an online midi to tone() converter that outputs three arrays. The pitch, the note duration and the delay. So I created this function in order to handle it. This works but I am out of RAM

@user1584421: This iteration makes no sense. Try playing each note only once.

But how it should be done? This works. Like I said, the website the performs the conversion gives three arrays for each given note. Pitch, duration and delay....

However, since that function works, and its compatible with the format, why change it? There is an error probably, in how I parse that data from PROGMEM. I updated the question with what I last tried.

@user1584421 Yes, it works, but probably not in the way you want it to. If your array has 1283 notes, you call playMelodyExtended2 with number_of_notes = 1283. Then this for loop plays the first note 1283 times. It then returns, the next note/duration/delay is read, then playMelodyExtended2 is called again for that second note. And it plays that second note 1283 times. Repeat until all 1283 notes are played 1283 times each. Your Edit 3 also does not fix that.

I also tried the first approach, with memcpy_P, but I made the delay[] array as uint16_t. And this works, but then it suddenly stops.... So it is better, because with the original approach, it didn't play at all. But now, it still does not play the whole melody.

@orithena I get it now. I should remove the for loop inside the playMelodyExtended2() function. EDIT: I just did, and it does not work as intended.

@user1584421 Yes. You then may also remove the argument number_of_notes Or, alternatively, always call playMelodyExtended2 with number_of_notes = 1, if you need that argument in the future for other purposes.

@user1584421 Then it is time to finally post full code, especially the actual declaration of the PROGMEN arrays (the first three values of each array would suffice). Also, add that debugging output of the actual values in playMelodyExtended2 I mentioned yesterday, compare them to your input arrays, and after that, we may be able to help you further.

@EdgarBonet Thank you so much! This was it!

@orithena The last edit in this answer worked! My code was included in my question, it was what I posted. The PROGMEM definitions were trivial. `const int My_Melody[] PROGMEM =
{
55,
//...
};
const float My_noteDurations[] PROGMEM =
{
200.7139,
//....
};
const uint16_t My_Delay[] PROGMEM =
{
214,
//...
};`


text:
Where to find interrupt flag for 3rd-party Arduino board cores?
This question might be a bit broad, but I'm running into an apparently classic problem with Arduino interrupts, where the rising or falling edge flag is triggered prior to a rising or falling edge technically occurring before a pin is pulled high/low and the microcontroller "remembering" that event occurred, running the interrupt the moment it gets attached to a pin. In this case, I'm working with Sparkfun's Artemis module (using the Apollo3 microcontroller). The code in question can be seen below:
#define SLEEP_INTERRUPT   4

void setup
{
    pinMode(SLEEP_INTERRUPT, INPUT);
#ifdef DEBUG
  Serial.print("About to attach interrupt");
#endif
  attachInterrupt(digitalPinToInterrupt(SLEEP_INTERRUPT), sleepModeSwitch, FALLING);
#ifdef DEBUG
  Serial.print("Interrupt attached");
#endif
}

void sleepModeSwitch()
{
#ifdef DEBUG
  Serial.print("Interrupt triggered! button status: "); Serial.println(digitalRead(SLEEP_INTERRUPT));
#endif
  if(sleep_mode_status == false)
  {
    goToSleep();
  }
  else
  {
    wakeUp();
  }
}

void goToSleep()
{
  sleep_mode_status = true;
#ifdef DEBUG
  Serial.println("Going to sleep");
  delay(50);  //Wait for serial to finish
  Serial.end(); //Power down UART(s)
#endif
  // turn off the led.
  digitalWrite(LED_BUILTIN, LOW);

  // Stop the BLE advertising.
  BLE.stopAdvertise() ;

  powerControlADC(false);

  for(int x = 0; x < 50; x++)
  {
    if(x != 4)
    {
      am_hal_gpio_pinconfig(x, g_AM_HAL_GPIO_DISABLE);
    }
  }
  //Power down Flash, SRAM, cache
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_CACHE); //Turn off CACHE
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_FLASH_512K); //Turn off everything but lower 512k
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_SRAM_64K_DTCM); //Turn off everything but lower 64k
  //am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_ALL); //Turn off all memory (doesn't recover)

  // // Enable interrupts to the core.
  am_hal_interrupt_master_enable();

  // //Enable the timer interrupt in the NVIC.
  // NVIC_EnableIRQ(STIMER_CMPR6_IRQn);

  //Go to Deep Sleep.
  am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}

void wakeUp()
{
  am_hal_pwrctrl_memory_deepsleep_powerdown(AM_HAL_PWRCTRL_MEM_MAX);

  // Re-enable UART0 pins
  am_hal_gpio_pinconfig(48, g_AM_BSP_GPIO_COM_UART_TX);
  am_hal_gpio_pinconfig(49, g_AM_BSP_GPIO_COM_UART_RX);

  am_hal_pwrctrl_periph_enable(AM_HAL_PWRCTRL_PERIPH_UART0);

  initializeADC();

#ifdef DEBUG
  Serial.begin(115200);
  Serial.println("Waking up! Hello world!");
#endif
  deepSleepTimer = millis() ;
  sleep_mode_status = false;
}

Based on my research, the solution for this is to just clear the interrupt flag manually before attaching the interrupt to your desired pin. Unfortunately, so far the methods for doing so that I've found only work for AVR boards, and I'm not certain where to look to find more information about how to access an interrupt flag in a sketch for a 3rd-party Arduino core. Does anyone have a suggestion or two on where to start?

Not sure I understand the issue, but it sounds like you could declare a volatile bool, isReady=false, and in the top of the handler say something like if(!isReady)return;, and add isReady=true; after your attachInterrupt call. Or maybe just snuff the first call with if(!isReady){ isReady=true;return;} in the handler.

Can you rule out the following possible cause of your problem? https://github.com/sparkfun/Arduino_Apollo3/issues/416

@6v6gt Would a 10k pullup resistor negate this issue?

It does appear from that problem report, if it is relevant to your case, that an external pullup would solve it. If you are invoking attachInterrupt() in setup() only then you could also do a trick (workaround)  with a global variable say endOfSetup and ignore any calls to the ISR where this was not set. Cleaning up, clearing flags etc., before using attachInterrupt() is very common so IMHO it is wrong that you have to go under the abstraction layer to do it.

@6v6gt I followed advice from elsewhere (and from dandavis) and made a software debounce with the millis() function to prevent the interrupt from getting too far if it's called too often. I also talked with someone on the Sparkfun forums about this and we might have fixed it. Seems it was a problem in the core's commonInterrupt.cpp file. Not certain, but I've at least stopped that premature interrupt from screwing up the device, even if I'm not certain I've stopped it from running at all. Still experimenting

the rising or falling edge flag is triggered prior to a rising or falling edge technically occurring before a pin is pulled high/low and the microcontroller "remembering" that event occurred, running the interrupt the moment it gets attached to a pin

There is no "technically" about it. This is what is supposed to happen. Once you configure the interrupt to happen (as you do in setup) then the processor will remember that the condition has happened, whether or not interrupts are enabled.
If you want the interrupt only to be processed after a certain point, then yes, you should clear the "interrupt has happened" flag in the MCU, before enabling interrupts.
Your question is pretty non-specific about exactly which processors you are talking about, but I would certainly clear any appropriate flags before attaching the interrupt.

I'm not certain where to look to find more information about how to access an interrupt flag in a sketch for a 3rd-party Arduino core

The datasheet of the device on this particular core?

Judging by the datasheet for the Apollo3 Blue SoC:

6.3.2.15 INTCLR Register
IO Master Interrupts: Clear
OFFSET: 0x00000228
INSTANCE 0 ADDRESS: 0x5000C228
Write a 1 to a bit in this register to clear the interrupt status associated with that bit.

However I don't have one of those processors around to test it.

Added a link to the device and a link to the datasheet for the microcontroller it contains. In this case, it's Sparkfun's Artemis module, containing Ambiq's Apollo3 Blue SoC. And you're right, I was asking this in a more general fashion, intending to learn in general where to learn how to clear these flags for when I'm working with another microcontroller I'm getting to grips with

@E.HP.S See amended answer.


text:
Why won't my servo and ultrasonic sensor work together?
I have a school project due tomorrow, and I'm planning to connect a servo motor with an ultrasonic sensor. If the distance is under 10cm, the servo motor should turn 180 degrees and will return to 0 degrees when there's no object in front of the sensor. I've tried them separately, the sensor by itself works and could read distance as usual and the servo works too. However, when I put the two code together, it just seems to cancel each other out. I don't know much about coding but pretty sure the sensor is supposed to print the distance on the serial monitor, but it just stops working, I also put some code to try and get the servo to turn, but it also doesn't work... So now I'm stuck pls help me, it's due tomorrow :(
Could it be my power source? I'm using my laptop to power it... but my friend did the same project, and it worked well using laptop as a power source, but i saw some post like this that encourages me to change power source, but isn't a laptop a huge power source? (genuinely asking)
#include <Servo.h>
#define servopin 9
#define echoPin 4
#define trigPin 5

Servo Myservo;
int long duration;
int distance;

void setup() {
    Myservo.attach(servopin);
    pinMode(echoPin, INPUT);
    pinMode(trigPin, OUTPUT);
}

void loop() {
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    duration = pulseIn(echoPin, HIGH);
    distance = (duration * 0.034 / 2);

    if (distance < 10)
    {
        Myservo.write(180);
    }
    else
    {
        Myservo.write(0);
    }
    delay(500);
}

you have no debugging code ... add some ... right now, you have no way to know the value of distance

"but isn't a laptop a huge power source? " Most USB ports are only obliged to supply 500mA.  In fact, some will go into constant current mode to protect the computer.

I tried your code on online simulator, and it works perfect!
Maybe just try another distance check like if(distance<30) (at least) and let's know what will happen.
I don't think using the laptop as a power source is your problem

I know rightt, this is very confusing. It works fine on tinkercad but it won't work in real life, I'll try your suggestion. Thanks a lot :D


text:
ESP32 thingboard broker mqtt error
Hello so i have this code, but it gives me this error , i have no idea why is not connection to broker mqtt? on the dash board say is active
"Conectando ao broker MQTT...Falha na conexao ao broker - Estado: 5"
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <ArduinoOTA.h>
const char* ssid         = "MEO-743D70_plus";
const char* password     = "861f6cbe4a";
const char* mqttServer   = "demo.thingsboard.io";
const int   mqttPort     = 1883;
const char* mqttUser     = "soundmeter";       //User name
const char* mqttPassword = "esp32";        //Password
const char* mqttClient   = "soundmeteresp32"; //ID

WiFiClient espClient;
PubSubClient client(espClient);
const int capacity = JSON_OBJECT_SIZE(21);
StaticJsonDocument<capacity> doc;

int contador = 1;
char mensagem[30];

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println("Iniciando conexao com a rede WiFi..");
  }
  Serial.println("Conectado na rede WiFi!");
}

void loop() {
   reconectabroker();

  doc["Dado0"] = random(100);
  doc["Dado1"] = random(100);
  doc["Dado2"] = random(100);
  doc["Dado3"] = random(100);
  doc["Dado4"] = random(100);
  doc["Dado5"] = random(100);
  doc["Dado6"] = random(100);
  doc["Dado7"] = random(100);
  doc["Dado8"] = random(100);
  doc["Dado9"] = random(100);

  String string1 = "v1/devices/me/telemetry";
  char Buf1[256];  string1.toCharArray(Buf1, 256);
  Serial.println(Buf1);

  char docBuffer1[256];
  size_t n = serializeJson(doc, docBuffer1);
  Serial.println(docBuffer1);
  client.publish(Buf1, docBuffer1, n);
  sprintf(mensagem, "MQTT ESP32 - Mensagem no. %d", contador);
  Serial.print("Mensagem enviada: ");
  Serial.println(mensagem);

  client.publish(Buf1, mensagem);
  Serial.println("Mensagem enviada com sucesso...");
  delay(1000);
  contador++;
}

void reconectabroker() {
  client.publish("v1/devices/me/telemetry", mensagem);
  Serial.println(mensagem);
  String string1 = "v1/devices/me/telemetry";
  char Buf1[256];
  string1.toCharArray(Buf1, 256);
  Serial.println(Buf1);
  client.setServer(mqttServer, mqttPort);

  while (!client.connected()) {
    Serial.println("Conectando ao broker MQTT...");
    if (client.connect(mqttClient, mqttUser, mqttPassword )) {
      Serial.println("Conectado ao broker!");
    }else {
      Serial.print("Falha na conexao ao broker - Estado: ");
      Serial.println(client.state());
      delay(2000);
    }
  }
}

client.state() returned 5 when attempting to connect to the MQTT broker. According to the PubSubClient documentation for int state(), this means the client was not authorized to connect. I.e. you used a wrong username and/ or password. Please add the code to your question.

i posted the code trought a link because is not formating correctly in the post, now i just edited, im using the correct user and password

Working now, thanks


text:
Give zero volt to specific servo motors in a certain time
I have a robot that uses 4 mechanical arms. Each mechanical arm has 4 "READYTOSKY 30kg" servo motors on them.
At some point, I need to use the absolute maximum force of only two mechanical arms (while the other two will stay still). Even though I do not change the coordinates of the other two mechanical arms (which I am not using),they consume voltage and "take away" the full potential of force from the other two.
Is there a way to stop the voltage consumed by the two other arms just for a brief moment using Arduino code? Shortly afterwards they will get back the voltage they need.
    if(level==25)
      {
        pwm.setPWM(12, 0, 200);
        pwm.setPWM(13, 0, 255);
        pwm.setPWM(14, 0, 430);
        delay(100);
        pwm.setPWM(1, 0, 380);
        pwm.setPWM(2, 0, 520);
        delay(500);
        pwm.setPWM(0, 0, 170);
        delay(600);
        stepperten.setCurrentPosition(0);
        while (stepperten.currentPosition() != (-3*200))
        {
        stepperten.setSpeed(-600);
        stepperten.runSpeed();
        }
        steppertwist.setCurrentPosition(0);
        while (steppertwist.currentPosition() != (100))
        {
          steppertwist.setSpeed(200);
          steppertwist.run();
        }
        stepper1.setCurrentPosition(0);
        while(stepper1.currentPosition() != (30))
        {
          stepper1.setSpeed(200);
          stepper1.run();
        }

        pwm.setPWM(1, 0, 295); //THIS IS THE MOMENT I NEED TO STOP VOLTAGE FOR OTHER ARMS
        pwm.setPWM(2, 0, 400); //AND GET THE MAXIMUM VOLTAGE POSSIBLE ON THESE TWO ARMS
        delay(1500);
        pwm.setPWM(12, 0, 125);

        array1[25][0] = 170;
        array1[25][1] = 295;
        array1[25][2] = 400;
        array1[25][3] = 153;
        array4[25][0] = 125;
        array4[25][1] = 255;
        array4[25][2] = 395;
      }

You mean they consume current? Cutting the other servos power would also mean, that they are not able to hold their position against outside forces (like gravity). Would that be a problem? You can control the power lines of a servo with a p-channel MOSFET

Did you try to detach() the servo, then attach() it again later?

chatgpt told me to use detach and attach. I thought it might not work during a code

I thought about getting a bigger trasformatore. The one I am currently using is 6.5[v] w/ 2.5[A]. The servo can get 4.8-7.2[V]. What is the optimal current I need for better results? The model is "readytosky td-8130mg". Thanks!

If you want to keep the maximum flexibility, then add together all the stall currents of your servos. If you google for the TD-8130mg datasheet 2.1A for 4.8V and 2.7A for 7.2V. So you will have stall current of about 2.6A. Make sure, that your power source can accommodate your maximum current.

If you want to turn off power for some external parts you could try to power them via the digital pins. See this example code:
void setup(){
   pinMode(YOUR_ARM_POWER_SUPPLY_PIN, OUTPUT);

   // switch arm on
   digitalWrite(YOUR_ARM_POWER_SUPPLY_PIN, ON);
}

void loop(){
  if(armMustNotUseAnyPower()){
      // switch arm off
      digitalWrite(YOUR_ARM_POWER_SUPPLY_PIN, OFF);
  }

}

Keep in mind that the digital Pins cannot output as much power as VCC. But since you drive some servo motors over it I assume they get their power externally anyway. You might need to add some transistor or another way on how to switch the power on and off from the big power source. Hope this helps you in some way.


text:
How to connect nRF24L01+ with Arduino Giga R1?
I have bought 2 Arduino Giga R1, 2 nRF24L01+ modules and 2 nRF24L01+ adapters. I am using the Arduino SPI in order to connect it with nRF24L01+. And I am using the following code with this change in the code only:
RF24 radio(7, 10); // CE, CSN

This is the Arduino GIGA R1 SPI documentation, and this is the nRF24L01+ modules, and the related adapter (the links of the modules are from a random Google search, just to show you the images + the documentation of the modules).
However I don't see something working. I added the following command both in the Receiver and Transmitter codes:
SPI.begin();
SPI1.begin();

in order to activate both SPI of each Arduino, because I don't know which is which. The result: Nothing works on Arduino GIGA R1... The same code above works fine on Arduino MEGA 2560 R3, so all the modules and the code are fine. The problem is on Arduino GIGA R1...
I supply the nRF24L01+ and the related adapters with 5V/1.5A power supply. I supply each Arduino GIGA R1 with 5V/1.5A power supply.
I have also tried this code, and I got this message:

We have lost connection, preventing unwanted behavior

Does anyone has any idea how to make the 2 Arduino GIGA R1 communicate via the nRF24L01+ link?

please no links to code and no pictures of code ...  copy your code and paste it into your question ... format as code

I cannot copy paste code from other sites. There are terms of use in every website. It is not my code...

then how do you know that the code has no errors?

It runs if I use Arduino MEGA 2560 R3 instead of Arduino GIGA R1.

Not sure if you found a solution but I had a similar problem and found a solution, which may work for you.
As you know, the Giga has two SPI buses.  The default are the ones on the ICSP header, the second one is on pins 11-13.
The NRF24L01, by default, assumes that you want to use the default one - SPI in this case.  If you want to use the other one (SPI1), all you need to do is call begin on SPI1 and pass that to the NRF begin function, as follows:
    SPI1.begin();
    radio.begin(&SPI1);

This worked for me, hopefully it will for you as well.

I just want to note that You Do Not Need An External Antenna module, because  the Arduino Giga R1 has a micro UFL antenna connector, and an antenna is shipped with every arduino giga(sorry for you if they forgot to include it in your one),
However It IS probably more for wifi porpuses than enclosed communication, still the nRF24L01+ is a great way to actually communicate between two mcu's, especially if an mcu doesnt come with a built in wifi or some sort of wireless communication


text:
RF24Network not compiling
I am trying to run a simple test of RF24Network which requires to use nrf_to_nrf library.
My compiler is pulling all the libraries and when is trying to compile I can see the object NRF_RADIO not being found/declared.
I tried to look around the doc in case I needed to include something extra but nothing... anybody has a simlar issue?
To clarify, I just tried any of the examples from the official library
https://github.com/nRF24/RF24Network/tree/master/examples
Oddly using Arduino IDE, the compiler is not throwing any errors but platformio is not able to compile.
Yes I checked that all the libraries were present when building. It seems like there is an extra library that Arduino automatically download? I can't find any reference of NRF_RADIO in any of RF24, RF24network and nrf_to_nrf.
                                                                                ^~~~~~~~~~~~~~~~~~~~~~ .pio/libdeps/huzzah/nrf_to_nrf/src/nrf_to_nrf.cpp:1172:155: error: 'RADIO_PCNF1_BALEN_Pos' was not declared in this scope
     NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | ((a_width - 1) << RADIO_PCNF1_BALEN_Pos) | (pSize << RADIO_PCNF1_STATLEN_Pos) | (staticPayloadSize << RADIO_PCNF1_MAXLEN_Pos);
                                                                                ^~~~~~~~~~~~~~~~~~~~~ .pio/libdeps/huzzah/nrf_to_nrf/src/nrf_to_nrf.cpp:1172:190: error: 'RADIO_PCNF1_STATLEN_Pos' was not declared in this scope
     NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | ((a_width - 1) << RADIO_PCNF1_BALEN_Pos) | (pSize << RADIO_PCNF1_STATLEN_Pos) | (staticPayloadSize << RADIO_PCNF1_MAXLEN_Pos);
                                                                                ^~~~~~~~~~~~~~~~~~~~~~~ .pio/libdeps/huzzah/nrf_to_nrf/src/nrf_to_nrf.cpp:1172:239: error: 'RADIO_PCNF1_MAXLEN_Pos' was not declared in this scope
     NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Disabled << RADIO_PCNF1_WHITEEN_Pos) | (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) | ((a_width - 1) << RADIO_PCNF1_BALEN_Pos) | (pSize << RADIO_PCNF1_STATLEN_Pos) | (staticPayloadSize << RADIO_PCNF1_MAXLEN_Pos);
                                                                                ^~~~~~~~~~~~~~~~~~~~~~ .pio/libdeps/huzzah/nrf_to_nrf/src/nrf_to_nrf.cpp: In member function 'void nrf_to_nrf::printDetails()': .pio/libdeps/huzzah/nrf_to_nrf/src/nrf_to_nrf.cpp:1182:20: error: 'NRF_RADIO' was not declared in this scope

You need to show the concerned source at least, optimally a minimal, complete, and reproducible example. BTW, each of us has a similar issue now and then, but I'm sure you don't want to know that.


text:
Sounds are being played at the same time
I'm making a school project that allows plants to 'talk'. As in when the plant is in an un-ideal environment (low or high soil moisture, not ideal temperature or humidity and not enough light). I have currently made some demo code for my presentation as the real code has real thresholds and is hard to trigger instantly during the presentation.
The problem im facing is that the sound is almost always cut off by another one, how can i stop this, also the recordings are all 7 seconds or less.
#include <DHT.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <LiquidCrystal_I2C.h>
//-----------------DEMO---CODE-------
#define DHTPIN 3
#define DHTTYPE DHT22
#define SOIL_MOISTURE_PIN A0
#define LIGHT_SENSOR_PIN 2
#define TEMP_THRESHOLD 25.0
#define HUMIDITY_THRESHOLD 60
#define LIGHT_THRESHOLD 1  // 1 for dark, adjust as needed
#define LOWER_SM_THRESHOLD 20 // Adjust as needed
#define UPPER_SM_THRESHOLD 50 // Adjust as needed
#define LCD_ADDR 0x27  // I2C address of the LCD
#define LCD_COLUMNS 16
#define LCD_ROWS 2
#define MESSAGE_INTERVAL 20000  // 20 seconds in milliseconds

DHT dht(DHTPIN, DHTTYPE);
SoftwareSerial mySoftwareSerial(10, 11);  // RX, TX for DFPlayer
DFRobotDFPlayerMini myDFPlayer;
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLUMNS, LCD_ROWS);

unsigned long lastTempTrigger = 0;
unsigned long lastHumidityTrigger = 0;
unsigned long lastSoilMoistureTrigger = 0;
unsigned long lastLightTrigger = 0;

void setup() {
  dht.begin();
  Serial.begin(9600);
  mySoftwareSerial.begin(9600);
  myDFPlayer.begin(mySoftwareSerial);

  myDFPlayer.volume(30);

  // Initialize the LCD
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Initializing...");
  delay(2000);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Plantastic!");
  lcd.setCursor(0, 1);
  lcd.print("System Ready");
  delay(2000);
  lcd.clear();
}

void loop() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  int lightValue = digitalRead(LIGHT_SENSOR_PIN);
  int soilMoistureValue = analogRead(SOIL_MOISTURE_PIN);
  int soilMoisturePercentage = 100 - (map(soilMoistureValue, 0, 1023, 0, 100));

  if (temperature > TEMP_THRESHOLD && millis() - lastTempTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(3);  // Play "Too Hot" message
    lastTempTrigger = millis();
  } else if (temperature < TEMP_THRESHOLD && millis() - lastTempTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(1);  // Play "Too Cold" message
    lastTempTrigger = millis();
  }

  if (round(humidity) < HUMIDITY_THRESHOLD && millis() - lastHumidityTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(2);  // Play "Low Humidity" message
    lastHumidityTrigger = millis();
  }

  if (soilMoisturePercentage < LOWER_SM_THRESHOLD && millis() - lastSoilMoistureTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(6);  // Play "Thirsty" message
    lastSoilMoistureTrigger = millis();
  } else if (soilMoisturePercentage > UPPER_SM_THRESHOLD && millis() - lastSoilMoistureTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(5);  // Play "Enough Water" message
    lastSoilMoistureTrigger = millis();
  }

  if (lightValue == 1 && millis() - lastLightTrigger >= MESSAGE_INTERVAL) {
    myDFPlayer.play(4);  // Play "It's dark in here" message
    lastLightTrigger = millis();
  }

  // Update the LCD display
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("T: ");
  lcd.print(temperature, 2);
  lcd.print(" H: ");
  lcd.print(humidity, 2);
  lcd.setCursor(0, 1);
  lcd.print("SM: ");
  lcd.print(soilMoisturePercentage);
  lcd.print("% L: ");
  lcd.print(lightValue == LIGHT_THRESHOLD ? "Dark" : "Light");

  delay(1000);
}

You could check, if something is playing before executing play()

no the first bit of sound plays, like the first second or half second but it is then cut off by another sound so you can't hear t completely

Can't you just wait for the sound to end before continuing? If you loose an iteration because of the sound being played is probably not an issue (you're updating at most every second anyway)

I'm not talking of the user waiting the sounds to be finished. What you describe indicates that you execute the play() function, before the last sound ended. The dfplayer should also have a command, which will return the play status. If you insert an if clause for every call of play() to check if something is already playing, then you can prevent this interruption

There are 2 approaches which address the problem of not playing a sound to completion.

Place a delay loop after each call to myDFPlayer.play() designed to last as long as the played sound. This is likely the most straight forward solution.  However, adding delays where no other code is able to run is considered bad programming form.  It also creates problem when adding new features to the program.
Create a finite state machine where the loop() function has no delays.  Instead use a variable to track the state the state machine is in and only change that variable when the conditions to go to the next state have been satisfied.  For instance, do nothing until a threshold (dryness, light, ect) has been crossed.  At which point switch to the state where you play back the associated sound & clear that threshold flag.  Do not exit that state until millis() has increased past the duration of the played sound.  Finally, repeat these state transitions for any other thresholds that have been crossed.  Complex behaviors dealing with how long before repeating a sound can then be added with additional states.


text:
MKR GPS shield inconsistent GPS connection/data printing...library issue?
I have been using a MKR WiFi 1010 board with GPS shield for a very long time (year+) and have not been able to solve my problems with the GPS data dropping out.
The setup for my field application is a MKR WiFi 1010 stacked with the MKR GPS shield, the MKR ENV Shield (version1), and 2 analog sensors, with data saved to a microSD card onboard the ENV sensor and GPS data transmitted over BLE to a phone app (this was done to try to keep an eye on the GPS connection in real time).
This field application runs on battery power, so uses no serial commuincation with the laptop (i.e. no Serial Monitor). This code has run for long periods of time, collecting hours worth of data on the SD card... but this is not EVERY time. In fact, it's only about half. Other times, I use the same sketch and check the SD card to find that only the headers have printed and no data was saved. I've explored forums and taken the suggestions of removing delays and editing the library (MKR GPS Shield Sampling Frequency) but to no avail.
Now, I have gone entirely back to basics and am still left puzzled. I am using the GPSLocation example sketch that comes with the Arduino_MKRGPS library (only edit is the line that initializes the GPS in shield mode, GPS_MODE_SHIELD).
There are no delays in this sketch, and of course I have the SM open on the correct baud rate. It is supposed to just continuously print 5 parameters to the SM. I have run this sketch repeatedly in the same, unobstructed location over the last few days and this is what has happened:

Sometimes, the initial connection is quick (<30 s- 1 min). Sometimes it takes a few minutes, and sometimes I wait an extremely long time (25 mins with still no connection) at which point I give up.
Once the GPS has connected, it does not appear to stay connected in a consistent manner. I've attached a part of the SM printout with time stamps. The time between printing varies from 1s to tens of seconds, to over a minute. All with 6+ satellite connections.

Being that there are no delays in the code to regulate the frequency of printing to the SM, my thought is that the inconsistent gaps of time between printing come from either:

an unstable connection to the GPS, which I would have no clue how to solve.
Or, more likely,
something wrong with the way the GPS.available() function is structured in the library.

I have made my way into the CPP files of GPS, minmea, and SerialDDC and right now it is beyond my current programming abilities / comprehension. I will be doing some reading to understand NMEA and parsing and how the data being received by the GPS actually gets printed to the SM.
Being that time is a very precious resource and this problem is currently holding up field work for my dissertation, I am hoping you kind people may be able to help me narrow down my issue.
Just getting the GPS to print at a consistent rate to the SM is step 1. Then I can get to figuring out if this fixes my problem in my field application.
Link to the Arduino_MKRGPS library with the sketches and files I mention: https://github.com/arduino-libraries/Arduino_MKRGPS/tree/master

I've found this in the GPS.cpp file- and I'm wondering if it could be messing things up for my battery-op application bc it calls for serial print when I am not connected to a SM.
void GPSClass::poll()
{
if (_stream->available()) {
char c = _stream->read();
#ifdef GPS_DEBUG
Serial.print(c);
#endif


text:
Arduino and Arduino-Cli how to specify include paths?
While this might appear to be a duplicate of this question Loading local libraries it isn't, and for one very simple reason.  That question deals with libraries that are expected to be used by multiple sketches, while the problem I have is to do with the architecture of a single sketch.
I have a sketch where it makes a lot of sense to divide the source into multiple subdirectories.  To give some idea of the scale I'm talking about it's ~20,000 LOC spread over ~100 .cpp/.h files, along with the obligatory .ino.  So I have the following layout:
sketch/
    sketch.ino
    src/
        module/
            module.h
            module.cpp

which while much smaller than the actual project is enough to demonstrate the problem.
Forget about "flattening" it all out into the sketch folder, no sane minded software engineer should ever consider doing that, not with a project the size I've outlined.
If I place the line
#include "module.h"

in sketch.ino I get the following error from the Arduino IDE:
C:\path\to\sketch\sketch.ino:3:10: fatal error: module.h: No such file or directory
    3 | #include "module.h"
      |          ^~~~~~~~~~
compilation terminated.

exit status 1

Compilation error: module.h: No such file or directory

I get the same error when using Arduino-Cli.exe to compile the sketch.
EVERY other C/C++ compiler on planet Earth offers an option akin to the -I of GCC and MSVC to allow me to specify other folders to include in the header search.
How is this done with Arduino, so that I can get module to compile correctly?  As noted in the linked question, I could use a full path, but that's (A) ugly, and (B) unnecessary.
Header search paths are a thing, how do I do them with the Arduino toolchain?

It's not in the same folder is it? How about trying: #include "src/module/module.h". However I'm not convinced that will work. The IDE copies your files into a working directory.

my guess would be #include "module/module.h". src is searched. src/module isn't. https://arduino.github.io/arduino-cli/0.35/sketch-specification/#src-subfolder

Looking at the arduino-cli doc, can't the flag --libraries do the job?

@nickb That's a bit of a hack, and might be able to solve the problem for arduino-cli, but it does nothing for the ide itself.

@dgnuff Then Platformio might better fits your needs. IIRC, you can setup multiple include and libraries per project.

@NickB That's a good suggestion.  I finally bit the bullet, and did the transition over to PlatformIO.  There were a few teething troubles as I got everything set up, but the end result is a development environment that's vastly superior to the Arduino IDE.  I'm able to use Visual Studio as my IDE, and just use an NMAKE project configuration with a call to pio run to build the project.  Since GCC does the heavy lifting, adding a -I option  is trivial ...

...  and the icing on the cake is that I can have metadata in platformio.ini that allws me to build for multiple target platforms.  Another project I have can be built for either ESP32-S2 or Pi Pico W.  PlatformIO handles this flawlessly, while Arduino trips over it's own feet trying to do such a simple thing.


text:
D1 mini ESP8266 no sound on speaker
I am new to Arduino and microcontrollers, I want to make a tone with my D1 mini and a LSM-50F speaker. But I don't get any output. Any idea what I am doing wrong? Tested it with two D1 mini boards.
This is how I wired everything:

Specifications:
Impedance   45 Ohm
Power (Nominal)   0,2 W
Power (Maximum)   0,5 W
Resonance frequency   450 Hz

The D1 mini's GPIO pins have a maximum of 10 mA, so I am using a 330 Ohm resistor in series to the 45 Ohm speaker to avoid overloading.
I = U/R
I = 3.3 V / 330 Ohm + 45 Ohm
I = 3.3 V / 375 Ohm
I = 8.8 mA

My code:
int Speaker = 5;

void setup()
{
}

void loop()
{
tone(Speaker, 450);
delay(1000);
noTone(Speaker);
}

I also tried a piezo from an old computer in the same setup. Not sure if the piezo is active or passive, so I tried using:
digitalWrite(Speaker, HIGH); // Play a tone on an active piezo.

And
tone(Speaker, 450); // Play a tone on a passive piezo.

Yes! 3.3 V / 375 Ohm = 0.0088 A conversion to mA

You are plugged into D5 and have int Speaker = 5;
However, D5 and 5 are actually different things.
static const uint8_t D5   = 14;

The plain number refers to the GPIO number of the esp8266 chip. The "D5" type numbers that are silk screened are mapped onto those. So you need int Speaker = D5; or alternately int Speaker = 14; /*D5 is GPIO14*/ or you need to move the wire to the actual GPIO5 which is labeled D1.
You may find your speaker is very quiet, maybe inaudible. If you're going to try driving a speaker from a GPIO pin the piezo is a better choice. But really it would be better to have some kind of amplification. This is the sort of thing I've used with piezos before. You can test that you're affecting the pin at all with a meter. You may get a weird reading, but you should at least be able to tell the difference between that and a pin you aren't trying to use.