text:
Making a servo work for just once after a specific time period without hindering the sensors that are reading the data in a loop
I am making a cansat which will be launched on a sugar rocket. The cansat's Arduino nano will be operating sensors which will read the data and store it in an sd card and also a servo to deploy the parachute.
The problem is that I am not able to make code where I want all the sensors to be logging data in the sd card in a loop and a mini servo should perform a sweep angle of 90 degrees after 2 minutes of power supply to the Arduino.
I have made the code for sensors inputting data into sd card but the servo part is confusing me due to no possibility of putting servo code in void setup as the setup will first do the servo sweep after 2 minutes and then record data, neither can I put it in the loop as that also records the data after 2 minutes and I tried to put that into a new function but that's also not working.
Please give me a solution for this.
The code that I have made is below : ( just for sensors logging data in sd card )
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#include <DHT.h>
#include <SD.h>

#define DHTPIN 10
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);

const int MQ2 = A0;

File dataFile;

void setup() {
  Serial.begin(9600);
  dht.begin();
  if (!bmp.begin()) {
    Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    while (1) {}
  }
  if (!SD.begin(4)) {
    Serial.println("SD card initialization failed!");
    while (1) {}
  }
  dataFile = SD.open("data.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.println("Temperature, Humidity, Pressure, Gas");
    dataFile.close();
  } else {
    Serial.println("Error opening data file!");
  }
}

void loop() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  sensors_event_t event;
  bmp.getEvent(&event);
  float pressure = event.pressure;
  float gas = analogRead(MQ2);
  dataFile = SD.open("data.txt", FILE_WRITE);
  if (dataFile) {
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(humidity);
    dataFile.print(",");
    dataFile.print(pressure);
    dataFile.print(",");
    dataFile.println(gas);
    dataFile.close();
  } else {
    Serial.println("Error opening data file!");
  }
  delay(1000);
}

For a parachute I wouldn't code a sweep, I'd just write the servo to 90 so it moves as quickly as possible.  Releasing a parachute is not usually a gradual process.   As far as how, just test millis() in your program to see how long it has been since launch and at 120 seconds write the servo to 90 degrees.

examine the blinkWithoutDelay example sketch in the Arduino IDE

I assumed you would want to collect the data after you opened the parachute. And as Delta_G suggested, you would want to open the parachute as fast as possible and not gradually.
I also assumed you want to collect the data every second, based on your provided code, because it has a 1000-millisecond delay. With all that here is a code that might work: (I haven't tested it, but it should give an idea of how to get going)
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#include <DHT.h>
#include <SD.h>

#define DHTPIN 10
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);

const int MQ2 = A0;
const long parachute_timeout_ms = 2 * 60 * 1000;   // Open parachute after two minutes.
bool parachute_opened = false;

const long data_collection_interval_ms = 1 * 1000; // Collect data every second.
bool start_collecting_data = false;
unsigned long previous_ms = 0;

File dataFile;

void setup()
{
  Serial.begin(9600);
  dht.begin();
  if (!bmp.begin())
  {
    Serial.println("Could not find a valid BMP085 sensor, check wiring!");
    while (1) {}
  }
  if (!SD.begin(4))
  {
    Serial.println("SD card initialization failed!");
    while (1) {}
  }
  dataFile = SD.open("data.txt", FILE_WRITE);
  if (dataFile)
  {
    dataFile.println("Temperature, Humidity, Pressure, Gas");
    dataFile.close();
  }
  else
  {
    Serial.println("Error opening data file!");
  }

  previous_ms = millis();
}

void loop()
{

  // Check to see if it's time to open the parachute.
  unsigned long current_ms = millis();

  if ((parachute_opened == false) && (current_ms - previous_ms >= parachute_timeout_ms))
  {
    // Your code to open the parachute
    // ... ... ..

    // Make sure this code doesn't execute again.
    parachute_opened = true;

    //...and then set the flag that tells the other part of the code
    // that it should start collecting data.
    start_collecting_data = true;
  }

  if ((start_collecting_data) && (current_ms - previous_ms >= parachute_timeout_ms))
  {
    collect_data();
    previous_ms = current_ms;
  }
}

void collect_data()
{
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  sensors_event_t event;
  bmp.getEvent(&event);
  float pressure = event.pressure;
  float gas = analogRead(MQ2);
  dataFile = SD.open("data.txt", FILE_WRITE);
  if (dataFile)
  {
    dataFile.print(temperature);
    dataFile.print(",");
    dataFile.print(humidity);
    dataFile.print(",");
    dataFile.print(pressure);
    dataFile.print(",");
    dataFile.println(gas);
    dataFile.close();
  }
  else
  {
    Serial.println("Error opening data file!");
  }
}


text:
ESP32-CAM OV2640 AS A SUN SENSOR
I want to use the ESP32-CAM as a sun sensor, the problem is that I would need to remove the lenses in order to put a membrane with a pinhole (like it's illustrated in the image) upon the CMOS, but I want to know first, will this make unoperable the OV2640? I want it to be working fine without the lenses, the second image is an illustrative of what I want to do.

what is preventing you from determining the results experimentally?

It is a bit expensive here in Mexico, 227.00 pesos (13.14 USD), so I only have one shot to buy it, I know It may not be that expensive in other currencies, but here is like a week worth of food haha, so that's why... I dont want anyone to make the experiment and possibly hurt their ESP32-cam, I just would like to know If someone has tried it.

that is a very good reason for not determining the results experimentally

what exactly are you trying to do? ... what does the sun sensor measure?

I want to measure the azimuth and elevation angle, thanks to the incident angle of the sun!

if you know your geographic location and the correct time, then those values can be calculated without the need for a camera

As an alternative to disassembling the camera, you may consider keeping the lens, and pointing the whole camera to the sun through a high-density neutral density filter. A B&W negative fully fogged and developed may serve as a cheap filter.

Yes, they can be calculated, but I want to make a sun sensor to use it to simulate an ADCS for a cubesat, this will be a second sun vector, I already have the sun position vector, thru the Vallado algotihm

Consider using the ESP32-CAM as is. Instead use a pin hole camera box. Put the ESP32-CAM inside the box pointing it at the image of the sun at the back of the box. This approach mitigates problems associated with exposing the sensor to the elements and direct exposure to sun light.
In order to measure azimuth and elevation, consider mounting the device such that it points directly up from the surface of the earth.  And such that it is aligned to true North. Consider using an accelerometer to detect the device is normal to the surface of the earth. And a magnetometer to detect magnetic north.  And a GPS receiver to detect the position on earth.  Combine the GPS data with  World Magnetic Model (WMM) data to correct for magnetic declination.

Yeah!! I thought of that, but I think that the aperture diameter of the camera already kinda serves as a pinhole, what I want to do is to have oportunity to make it myself so I will have the possibility of control the values that I want, like the FoV for example.

Unless you find someone who has done this, you are asking for opinions which stack exchange is not equipped to handle.  You added that you need azimuth and elevation. You will need to add a tilt compass in order to get azimuth and elevation. I'll add that to the answer.

That is a good idea, Im going to consider it, thanks!!

I am not sure how you would do this, but I believe that a SHARP distance measurement sensor has a linear optical sensor.  So it may be possible to modify 2 of these to measure the angle of the sun along the north south axis and along the east west axis.  Again, not sure how you would do this.  But these sensors my be less expensive to experiment with.

source: Stack Exchange

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

sort: votes


text:
How much maximum current do the Arduino Wemos D1 (R1 & R2) consume?
I have been powering my WeMos D1 R1 and D1 R2 Arduinos (with ESP8266) using a simple USB cable connected to a standard charger whose rating is 3.1 amps.  Is this sufficient to charge two such Arduino boards (it has two USB slots) simultaneously?
Also, should I be using the other Power Input which I understand is 9V?
All the specs I have seen specify the voltage but not the current usage.
Either way, what is the maximum amperage that the board might need/is rated for?  Is it different for the R1 vs. R2?  Is it possible to measure how much it is using from any of the pins?

an USB 2 port gives max 500 mA. so 3.1 A should be more than enough.

You can use a USB meter like this.

It is possible to measure how much it is using from any of the pins?

Put an ammeter (multimeter in current mode) in series with the power supply and measure it, when configured in the way you intend to use it.

Good suggestion, but it will be hard to do without splicing the USB cable.  Now this becomes a project! :-) If I were to do that, which would be the right wire to put the multimeter on?

Just about every USB wire I've cut into contain a red (+5V) black (ground) and green & white (data).  You can cut either the black or red wire in such a cable and insert an amp meter.  Note, always try the high Amp meter first! When you are confident you can not read a current because it is too small, then switch to the mA meter configuration. That said, there are many Common Off The Shelf (COTS) USB devices that measure Amperage.

I will do that.  Meanwhile, is there any place a maximum rating is specified?

I believe USB 2.0's maximum is 500mA. Other USB definitions exist.  Later versions of USB exist. Some companies have done odd things to detect and support higher current capabilities.  And then there is negotiations between the USB peripheral and USB host. You are going to have to do some digging for your specific situation.

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


text:
MacBook + BLE Microcontroller Incompatibility?
I've programmed an Adafruit Feather nRF52840 board to send MIDI signals to my computer via BLE. I can confirm that the board pairs successfully with an Android phone and a Windows PC, but my laptop (MacBook Pro 2021) will not recognize the board; it does not appear in the Bluetooth menu as an option for pairing. I've tried the following troubleshooting options:

Turned bluetooth off & on on laptop
Turned device off & on
Added the name of the board in the code (advertisement.complete_name = "BOARD_NAME")
Downloaded Bluefruit Buddy, Bluefruit Connect & Bluetility to find any BLE signals coming from the board (verdict: no trace!)
Tried a BLE smart dongle
Unpaired/forgot device from Android phone, attempt to re-pair with laptop
Attempted to connect the device via Apple’s Audio MIDI setup (https://support.apple.com/guide/audio-midi-setup/set-up-midi-devices-ams875bae1e0/mac)
Tried steps 1-7 with two additional MacBooks (2016 & 2022)

I know that the BLE pairing functionality of the board is working, since it consistently pairs with an Android phone and a PC laptop; I just cannot figure out why it won't pair with my MacBook. I want to resolve this issue and ensure that the board can be used across platforms.
Are there any other troubleshooting actions I should try?

try pairing with a Windows PC and a Linux PC

this is not a question about the Arduino until you determine why a Mac does not accept the connection

@jsotola, I tried pairing with a Windows PC yesterday and the board showed up in the Bluetooth menu and paired successfully. This is a good sign, however I still need the bird to work across all platforms.
I posted the question in this forum to see if possibly there was any hardware setting on the board that may impact its ability to pair with a Mac (i.e. double-tapping the reset button or holding down for a certain amount of time).  Generally, I just wanted to know if anyone else had run into this issue or could suggest helpful ways to troubleshoot beyond what I’ve already done.

What macOS version do you have?

Ventura for two computers, Catalina for the 2016 MacBook

Have you tried Bluefruit Connect from Adafruit? It is available in the Apple store. Don't quote me on this, but I read a long time ago, that Mac requires encryption for a BLE device to be recognized, whereas, most of the out-of-the-box Adafruit example doesn't use it.
I had a similar issue. And I used Bluefruit Connect to connect my device to my Mac.

Item not available in my country? Got a download link to the app not involving the "app store"? What versions of OSX are supported?

Unfortunately, I can't seem to find the information about what OSXs are supported on the app page, but I have "macOS 10.14".

Too bad it's not available in other countries besides the US.

That's unfortunate. Also, I found what OS are supported: "Requires macOS 12.0 or later and a Mac with Apple M1 chip or later."

Yes, I have tried Bluefruit Connect, Bluefruit Buddy & Bluetility.  None of these apps are able to detect the board.


text:
ESP32 - TWAI Timing Problems (cant receive messages below 5ms period)
I am currently trying to read an existing canbus (Car) with my ESP32 Rev3.
I got it to work fine with an external MCP2515 shield using a default library.
But when i connect an transceiver and trying to use the internal TWAI controller built into ESP32 i am starting to get troubles. When receiving messages with at least >5ms period, it works fine but as soon the period gets under 5ms, its rapidly filling up the RX buffer and once its full, its starting to drop packets. When i set the RX buffer to a higher value, this only extend the time until the first error appears. It seems like the transceiver works fine but the twai_receive() function can't catch up. Does anyone have an idea, what i can do here.
For receiving, i am using the following, wich works kind of fine for ESP32 Wroom Rev3.
https://github.com/halfroad/TWAIMessager
Before, i was directly accessing the API by using this documentation, but this has the same behaviour:
https://docs.espressif.com/projects/esp-idf/en/release-v4.4/esp32/api-reference/peripherals/twai.html#examples
If the internal limitation is >5ms per message period, the CAN controller is pretty useless as in most modern cars canbus you have periods as low as 0.4ms per message.
To verify, that i'm not missing anything i setup two ESP32 and sending from A to B.
The code/setup of the receiving part is like this:
#include "driver/twai.h"
twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(GPIO_NUM_33, GPIO_NUM_32, TWAI_MODE_LISTEN_ONLY);
    twai_timing_config_t t_config = TWAI_TIMING_CONFIG_500KBITS();
    twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL();

    //Install TWAI driver
    if (twai_driver_install(&g_config, &t_config, &f_config) == ESP_OK) {
        Serial.println("Driver installed\n");
    } else {
        Serial.println("Failed to install driver\n");
        return;
    }

    //Start TWAI driver
    if (twai_start() == ESP_OK) {
       Serial.println("Driver started\n");
    } else {
        Serial.println("Failed to start driver\n");
        return;
    }

The processing of ingoing messages in the loop() function is something like this:
twai_message_t message;

void loop() {
    while (twai_receive(&message, 0) == ESP_OK) {
        // process message (which will only arrive every 5ms
        Serial.printf(msgString, "STD CAN-ID: 0x%.3lX       DLC: %1d  Data:", message.identifier, message.data_length_code);
            for(byte i = 0; i<message.data_length_code; i++){
                        Serial.printf(" 0x%.2X", message.data[i]);
            }
        Serial.println();
    }

return;
}

Here is the receiving side's output when sending in a 5.1ms period:

On the left you can see the period between this, and the previous message.
The ID in green on the right side confirms, that the message is a valid follow up to the previous message (data).
As soon as im trying to go <5ms, 3ms in this example it looks like this:

Here, it starts to drop messages as soon the RX buffer is filled up.
In the last image, you will see a log of the drivetrain canbus of a 2013 VAG car using the ESP32 and a MPC2515 controller externally.
It has periods between 0.41 and 9ms between each package and its not missing a single one of it.

I hope, someone here can actually help with this or had experienced the same behaviour before.
Br Chris

all of this is dependent on your code, which you have not posted

I linked the exact library i used, i am simply SENDING and RECEIVING can messages, and i explained, it doesnt matter which configuration i am using. My problem is not, that i fail to send messages, rather then the timing issues.
But i will post the code..


text:
Is it possible to get the RSSI value of the connected client or phone in esp8266 if it is set as an access point
Is it possible to obtain the RSSI value of the connected device to the esp8266 similar to obtaining MAC address?


text:
Turn ESP8266 into an Arduino IDE-like "sketch uploader" (over hardware serial)
I have an ESP8266 module which has downloaded a hex file for an Arduino Mega2560. This hex file (call it mega2560.hex) is sitting in the ESP's SPIFFS file system. What I want to do is basically emulate the behavior of the Arduino IDE when we press the upload button on a sketch (except in my case here, the sketch is already compiled and ready for transfer). What I need is some library or small code example that can steer me in the right direction. On the Mega's end, the processor will be restarted, and the bootloader will wait for the hex file, receive it from the ESP and flash it to application memory.
Here is the basic structure:
// Code for ESP8266

SoftwareSerial mega(D1, D2); // since hardware serial is occupied for serial monitor
// Mega will use its hardware serial (Tx1, Rx1)

void setup()
{
    Serial.begin(115200); // use up hardware serial
    mega.begin(115200); // connect to mega

    SPIFFS.begin();
    File hexfile = SPIFFS.open("mega2560.hex", "r");

    // IDE-like "upload"
    upload(mega, hexfile);
    Serial.println("Done uploading.");

    hexfile.close();
}

// emulate Arduino IDE-like upload behavior
void upload(SoftwareSerial& mega, File& hexfile)
{
    // reset Mega to start bootloader which will first wait to accept new hex file
    reset(mega);

    // send out the hex file for the bootloader to accept and store to Mega's flash
    send(mega, hexfile);

    // reset Mega to start bootloader again, this time so that previously uploaded hex file can be run
    reset(mega);
}

I am fairly new to working with bootloaders and would like to know if the above top-down code is correct in trying to achieve what I have in mind. Can I simply reset the Mega and transfer it as per usual via Serial within the bootloader's "waiting window" ? or are there more considerations that I am missing.
I am trying to avoid using ISP or SPI because that would erase the Mega's bootloader as well and I want to keep the bootloader preserved.

Yes, you are thinking in the right direction. You can simply reset the mega to get the mega bootloader started, but you can not just send the bytes through the serial port. Arduino bootloader uses STK500 commands for reliable handshaking. AVRdude uses the same protocol to talk to an Arduino. Here is a link that might give you some direction: https://www.electronicwings.com/arduino/basics-to-developing-bootloader-for-arduino

other option https://github.com/JAndrassy/lab/blob/master/AvrDudeTelnet/AvrDudeTelnet.ino


text:
Pass typedef to a function
I'm working with a ESP32S3 that will manage 2 I2S ports, so for the cleanness of my code and also because i'll work multiple I2S installations - deinstallations, i want to move all the functions to and ".cpp .h" file.
something like this

I2S_functions.h
#ifndef I2S_FUNCTIONS_H
#define I2S_FUNCTIONS_H
#include <Arduino.h>
#include <driver/i2s.h>

void i2s_install(i2s_port_t I2S_PORT, i2s_mode_t I2S_MODE, float I2S_SAMPLE_RATE,
i2s_bits_per_sample_t I2S_SAMPLE_BITS,i2s_channel_fmt_t I2S_CHANNEL,i2s_comm_format_t I2S_COMM_FORMAT_STAND_I2S,int buf_count, int buf_len, bool apll);

#endif

I2S_functions.cpp

#include "I2S_functions.h"

void i2s_install(i2s_port_t I2S_PORT, i2s_mode_t I2S_MODE, float I2S_SAMPLE_RATE,
i2s_bits_per_sample_t I2S_SAMPLE_BITS,i2s_channel_fmt_t I2S_CHANNEL,i2s_comm_format_t I2S_COMM_FORMAT_STAND_I2S,
int buf_count, int buf_len, bool apll)
{
  const i2s_config_t i2s_config =
  {

    .mode = I2S_MODE,
    //.mode = (i2s_mode_t)(I2S_MODE),
    .sample_rate = I2S_SAMPLE_RATE,

    .bits_per_sample = I2S_SAMPLE_BITS,
    .channel_format = I2S_CHANNEL,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),

    .intr_alloc_flags = 0, // default interrupt priority
    .dma_buf_count = buf_count,//cambiado de 8 a 64
    .dma_buf_len = buf_len,
    .use_apll = apll
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}

main.ino

#include "I2S_functions.h"

// I2S config //////
#include <driver/i2s.h>

#define I2S_PORT I2S_NUM_0
//#define I2S_SAMPLE_RATE  (44100)
float I2S_SAMPLE_RATE=44100;
int I2S_SAMPLE_BITS=32;
//#define I2S_SAMPLE_BITS  (32)
#define bufferLen 1024
#define I2S_READ_LEN (16*1024)

void setup ()
{
  i2s_install(I2S_PORT,I2S_MODE_MASTER|I2S_MODE_RX,I2S_SAMPLE_RATE,
I2S_BITS_PER_SAMPLE_32BIT,I2S_CHANNEL_FMT_ONLY_LEFT,I2S_COMM_FORMAT_STAND_I2S,8,bufferLen,false);

}

But when i compile this, i got errors passing the second argument which is "I2S_MODE_MASTER|I2S_MODE_RX,I2S_SAMPLE_RATE"
a copy from the error:
C:\Users\.ino: In function 'void setup()':
test_10seg_V2:52:39: error: invalid conversion from 'int' to 'i2s_mode_t' [-fpermissive]
   i2s_install(I2S_PORT,I2S_MODE_MASTER|I2S_MODE_RX,I2S_SAMPLE_RATE,
                        ~~~~~~~~~~~~~~~^~~~~~~~~~~~
In file included from C:\Users\.ino:2:
C:\Users\I2S_functions.h:6:50: note:   initializing argument 2 of 'void i2s_install(i2s_port_t, i2s_mode_t, float, i2s_bits_per_sample_t, i2s_channel_fmt_t, i2s_comm_format_t, int, int, bool)'
 void i2s_install(i2s_port_t I2S_PORT, i2s_mode_t I2S_MODE, float I2S_SAMPLE_RATE,

exit status 1
invalid conversion from 'int' to 'i2s_mode_t' [-fpermissive]

Essentially i have 2 questions. While i looked in the github from the esp32 i found off that there is some typedef of the I2S config (https://github.com/espressif/arduino-esp32/blob/master/tools/sdk/esp32/include/hal/include/hal/i2s_types.h). I've never worked with this type of structs before so i am guessing how should i use it and specially how should i pass this type of variables to a function.
typedef enum {
    I2S_BITS_PER_SAMPLE_8BIT    = 8,            /*!< data bit-width: 8 */
    I2S_BITS_PER_SAMPLE_16BIT   = 16,           /*!< data bit-width: 16 */
    I2S_BITS_PER_SAMPLE_24BIT   = 24,           /*!< data bit-width: 24 */
    I2S_BITS_PER_SAMPLE_32BIT   = 32,           /*!< data bit-width: 32 */
} i2s_bits_per_sample_t;

/**
 * @brief I2S bit width per chan.
 *
 */
typedef enum {
    I2S_BITS_PER_CHAN_DEFAULT        = (0),      /*!< channel bit-width equals to data bit-width */
    I2S_BITS_PER_CHAN_8BIT           = (8),      /*!< channel bit-width: 8 */
    I2S_BITS_PER_CHAN_16BIT          = (16),     /*!< channel bit-width: 16 */
    I2S_BITS_PER_CHAN_24BIT          = (24),     /*!< channel bit-width: 24 */
    I2S_BITS_PER_CHAN_32BIT          = (32),     /*!< channel bit-width: 32 */
} i2s_bits_per_chan_t;

my questions are
1.- I would like to understand how this structs works. I want to clean my code the most that i could, and that mean passing a lot of functions out of the main file. So any resource is well welcome to improve my coding skill.
2.- Why the code fails passing this 2 variables "I2S_MODE_MASTER|I2S_MODE_RX" ?. Is there any special way of passing this variables when are 2 options at once?.
Thanks for your replies!

this is more a general C++ programming question, than it is an Arduino question

https://en.wikipedia.org/wiki/Enumerated_type

Answer to Question 1: The typedef code you posted is enum and not struct. Look up C++ Enumeration and you will find lots of good tutorials. Here is one video.
Answer to Question 2:  You need to typecast the argument for your function to accept it as i2s_mode_t.
i2s_install(I2S_PORT, (i2s_mode_t)(I2S_MODE_MASTER|I2S_MODE_RX), ... ... ...);

i2s_mode_t it is an example of a very bad API design. it should never be an enum.


text:
Copy Uno Analog Input Configuration To ESP32
I started a project using the arduino uno and as a challenge I'm attempting to make it work with the esp32 but I've run into a roadblock. I may not describe it in proper terms, but I noticed that the analog input signal on the esp32 functions differently from how analog input works on the uno. After some research I found that the esp32 has a default analog width of 12, instead of the default 10 on the uno. This got me wondering what other analog settings (reference voltage, pin attenuation, width, etc.) on the esp32 are different from the uno and how I might go about getting similar results on the esp32. I found this useful page detailing some functions to mess around with the adc channels but, other than analogSetWidth(), I haven't been able to figure out what they do. I tried messing around with the functions mentioned in the linked page, but I ultimately made things worse.
tl;dr What analog input settings (analog width, pin attenuation, etc.) on the esp32 are different from the uno?

You've found a datasheet equivalent (or API description) for the ESP32 ADC. Find one also for the ATmega328P (Uno/Nano MCU) to compare their ADC capabilities. These are different peripherals from different manufacturers. Some features may not be present on both.

@6v6gt Your advice led me to find https://ece-classes.usc.edu/ee459/library/documents/ADC.pdf and https://www.best-microcontroller-projects.com/arduino-adc.html which told me exactly what I needed to know! Thanks!

Per the advice of @6v6gt, I was able to find this resource and this resource that told me the following information about the ADC configuration for the Uno's MCU (aka ATmega328P):

The analog width defaults to 10 bits (** definitely the most important)
The reference voltage is determined by the AVCC (power source) by default
The ADC clock defaults to a divisor of 128 (assuming 13 ADC cycles per conversion)

Wasn't able to find anything useful about pin attenuation, though.


text:
Why does arduino use a PWM range of 544 to 2400?
I learned in school that typical servos use a simple PWM system to control a servo. To do this, we would generate a 1000ms pulse to put the servo at 0 degrees and 2000ms pulse to set it at 180 degrees. Simple basics, right?
I recently tried configuring my HS-311 with these values and I found the servo moving less than 90 degrees.
I switched to the Servo.h library and it worked fine. I peeked at Servo.h file and found the following:
#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached

544? 2400? Where are these numbers coming from?
I looked at an old datasheet for this servo and found
OPERATING TRAVEL: 40�/ONE SIDE PULSE TRAVELING 400usec
DIRECTION: CLOCK WISE/PULSE TRAVELING 1500 TO 1900usec

A bit hard to tell what does numbers mean but they are definitely not 1000 to 2000!
Then I took a look at the specs on servocity.com and I see:
Max PWM Signal Range    575-2460μsec

This matches up with the Servo.h source code!
What's going on here? Do manufacturers normally move outside of the 1000us-2000us range? These values that I see far exceed what I'd think are acceptable tolerances. Please help me figure out where these numbers came from!

IIRC the first models of such servos were available in the 70s, about 50 years ago. At least one manufacturer used low pulses in contrast to other brands. The pulse width range was not standardized, too. So these variations can be historically necessary, or by the inevitable different quality of products, or simply trying to go to the limits. But since I'm no expert, this is just a comment, not an actual answer... You might want to start a research on the matter. ;-)

You may want to change this to "Why does Servo..." or something to that effect. Most of the people reading the current title will probably think that it's about analogWrite().


text:
USB OTG and ESP32-S2
I have an ESP32-S2-DevKitM-1 which is supposed to able to act as USB HID device.
But whatever I try using either ESP-IDF or Arduino-IDE, I can't get any data from it.
I ran this esp-idf example.
I also ran the arduino example.
I connected GPIO20/19 to D+/D- of a USB cable.
When I plug in that cable, my host computer logs:
usb 1-6: new full-speed USB device number 93 using xhci_hcd
usb 1-6: device descriptor read/64, error -71
usb 1-6: device descriptor read/64, error -71
usb 1-6: new full-speed USB device number 94 using xhci_hcd
usb 1-6: device descriptor read/64, error -71
usb 1-6: device descriptor read/64, error -71
usb usb1-port6: attempt power cycle
usb 1-6: new full-speed USB device number 95 using xhci_hcd
usb 1-6: Device not responding to setup address.
usb 1-6: Device not responding to setup address.
usb 1-6: device not accepting address 95, error -71
usb 1-6: new full-speed USB device number 96 using xhci_hcd
usb 1-6: Device not responding to setup address.
usb 1-6: Device not responding to setup address.
usb 1-6: device not accepting address 96, error -71
usb usb1-port6: unable to enumerate USB device

The esp-idf example fails to send, because tud_mounted() is false, and the arduino-ide example fails on SendReport(): not ready.
How can I get the ESP32-S2 to talk USB with my host computer?

This problem went away when I replaced my DIY USB cable connection with an Adafruit USB-C breakout board.
I checked all the connections of my cable, but somehow it would not work, until I replaced it.


text:
Arduino unable to read 0x41 and 0x42 (reads others just fine (ICT bill acceptor)
Here is my issue:
My code successfully recognizes and accepts $1 (0x40) and $20 bills (0x43), but it fails to recognize, display, process, anything for the $5 bill (0x41), and $10 bills (0x42). Also, when I say "Arduino", I mean TTGO btw...
I have verified that the bill acceptor is indeed sending the correct value (0x41) for the $5, and $10 (0x42) bills using an external monitoring tool like Docklight, and I used an oscilloscope too! All signals from all bill types were near identical and valid. However, the Arduino code does not seem to receive those two values (and ONLY those two values) at all... Meanwhile, it will display every other little thing there is... I have my code setup where it displays all incoming bytes, be it B.A. (bill acceptor) idle signals, rejection signals, everything, but it goes 100% blank, MIA, for 0x41 and 0x42... WHY?!?! So frick'n random...
===================================================
Just so you all know, this is how the bill acceptor (B.A.) works:

Insert a bill into BA
BA sends the corresponding HEX value (ex. 0x40) of the bill to my Arduino (Using RS232 cables and an RS232 to TTL converter (the converters are confirmed to be 100% operational BTW))
Once the Arduino "sees" the HEX value for a bill of N value, it will then send 0x02 to the BA to accept the bill.
If 0x02 is NOT sent to the BA within 5 seconds, then it will reject the bill and spit it back out the front.
Code then adds that value to "total count"

OFC, my code is setup where the only way an accept (0x02) signal is sent is IF 0x4N is received... So, the fact that 0x41 and 0x42 disappear into thin air means 0x02 is never sent so those two values are always rejected... Very, very, simple stuff, so the fact that it consistently is unable to ONLY NOT read 0x41 and 0x42 while clearly displaying all other sent HEX values is causing me unlimited headaches and conniptions... Programming... YAY! -_-
So, anyone... please, do you know what's going on? The signal is 100% being generated, and my code, below, is setup to display all incoming bytes, but it acts like 0x41 and 0x42 do not exist at all! Nothing. Nada. Zilch. WTF? It literally handles everything I can throw at it... except 0x41 and 0x42!!! FUUUUUUUUUUUU!!! So mad...
HERE IS THE ICT RS232 PROTOCL FOR MY BILL ACCEPTOR - http://tdmegalit.ru/upload/iblock/401/ict_protocol.pdf
ALSO, I HAVE ALL DIP SWITCHES CORRECTLY SET, POWER SUPPLY IS PERFECT, ALL WIRES ARE TESTED AND PERFECT, RS232 TO TTL CONVERTERS ARE PERFECT. I GUESS IT IS SOFTWARE SERIAL, OR THE TTGO
So with all that said, below is my code. It is a part of a much great whole of a program, so to remove the possibilities of the rest of the code causing the error, I reduced it to what you see below, but the problem persist... bruh
Also, I have included the Serial Monitor LOG. The LOG below shows startup, and then a 1, 5, 10, and 20 dollar bill being inserted...
SERIAL MONITOR LOG:
PLZ NOTE, I ADDED SPACES TO SHOW WHATS GOING ON...
====================================================================

... Received: 0x80       //IDLE SIGNALS (BA POWERED ON BEFORE "SETUP" SENT)
... Received: 0x8F
... Received: 0x80
... Received: 0x8F
... Received: 0x80
... Received: 0x8F

SETUP - ...Sent: STX     //SETUP TO INITALIZE BA
SETUP - ...Sent: DLE
SETUP - ...Sent: ETX
=======================
                         //INSERTED $1 (0x40) SUCCESS!!!
... Received: 0x40
$1 accepted
... Sent: 0x02
... Received: 0x10
                         //INSERTED $5 and 5 seconds later 0x29>>0x29>>0x2F = Rejection
... Received: 0x29
Bill rejected
... Received: 0x29
Bill rejected
... Received: 0x2F
                         //INSERTED $10 and 5 seconds later 0x29>>0x29>>0x2F = Rejection
... Received: 0x29
Bill rejected
... Received: 0x29
Bill rejected
... Received: 0x2F
                         //INSERTED $20 (0x43) SUCCESS!!!
... Received: 0x43
$20 accepted
... Sent: 0x02
... Received: 0x10

BILL ACCEPTOR CODE:
#include <SoftwareSerial.h>

SoftwareSerial BA(32, 33);  // RX, TX

int billCounter = 0;

void setup() {
  Serial.begin(9600);
  BA.begin(9600);
  delay(3000); //WAIT BC TRESH

  BA.write(0x02); // Send the initialization command (STX)
  Serial.println("SETUP - ...Sent: STX");
  BA.write(0x10); // Send the command to enable the bill acceptor
  Serial.println("SETUP - ...Sent: DLE");
  BA.write(0x03); // Send the end of text character (ETX)
  Serial.println("SETUP - ...Sent: ETX");
  Serial.println("=======================");
}

void loop() {
  if (BA.available()) {
    byte receivedByte = BA.read();
    Serial.print("... Received: 0x");
    Serial.println(receivedByte, HEX);

    if (receivedByte == 0x29) {
      delay(200);
      Serial.println("Bill rejected");
      // Handle bill rejection here (e.g., display message or perform necessary actions)

    } else if (receivedByte == 0x40) {
      delay(200);
      Serial.println("$1 accepted");
      BA.write(0x02); // Send the HEX value 0x02 to accept the bill
      Serial.println("... Sent: 0x02");

      // Increment the counter by $1
      billCounter += 1;

    } else if (receivedByte == 0x41) {
      delay(200);
      Serial.println("$5 accepted");
      BA.write(0x02); // Send the HEX value 0x02 to accept the bill
      Serial.println("... Sent: 0x02");

      // Increment the counter by $5
      billCounter += 5;

    } else if (receivedByte == 0x42) {
      delay(200);
      Serial.println("$10 accepted");
      BA.write(0x02); // Send the HEX value 0x02 to accept the bill
      Serial.println("... Sent: 0x02");

      // Increment the counter by $10
      billCounter += 10;

    } else if (receivedByte == 0x43) {
      delay(200);
      Serial.println("$20 accepted");
      BA.write(0x02); // Send the HEX value 0x02 to accept the bill
      Serial.println("... Sent: 0x02");

      // Increment the counter by $20
      billCounter += 20;

    } else if (receivedByte == 0x44) {
      delay(200);
      Serial.println("$50 accepted");
      BA.write(0x02); // Send the HEX value 0x02 to accept the bill
      Serial.println("... Sent: 0x02");

      // Increment the counter by $50
      billCounter += 50;

    } else if (receivedByte == 0x45) {
      delay(200);
      Serial.println("$100 accepted");
      BA.write(0x02); // Send the HEX value 0x02 to accept the bill
      Serial.println("... Sent: 0x02");

      // Increment the counter by $100
      billCounter += 100;
    }
  }
}

looks like the bill validator is rejecting the 10 and the 5

@jsotola It is not though. As you can see, for 1 and 20, it shows 0x40 and 0x43 when the bill is inserted. Meanwhile, absolutely nothing appears for 5 and 10 and it is automatically rejected after 5 seconds... Again, I have confirmed that 5 and 10 dollar bills do indeed send a hex value but my code shows nothing for only 5 and 10 dollar bills fuuuuu

The default for Arduino Serial  is 8 data bits, no parity, one stop bit. The first page of your linked documents says:
Start bit 1, Data bit 8, Parity bit Even, Stop bit 1. The mismatched parity parameter could explain a partial failure of this. Look at (Software) Serial begin() method to change this.

@6v6gt, you should make it an answer.

The default for Arduino Serial is 8 data bits, no parity, one stop
bit. The first page of your linked documents says: Start bit 1, Data
bit 8, Parity bit Even, Stop bit 1. The mismatched parity parameter
could explain a partial failure of this communication. The
documentation for the Serial begin() method describes the various
configuration options.
However, see also this thread:
https://forum.arduino.cc/t/altsoftserial-how-to-change-parity-solved/668535
It appears that the various software serial libraries do not support
EVEN parity settings. Use a hardware serial port on your TTGO Arduino
instead. This may mean using SoftwareSerial for the debug printing
(maybe with a USB/UART adapter) and dedicating the hardware serial
port to your bank note reader.

Thank you 6v6gt! Using HardwareSerial was the answer and setting the parity bit to EVEN was the answer too :D Here is what I did to fix it if anyone ever needs to see this answer in the future...
Also note, here is the logic:
The default for hardware serial is SERIAL_8N1, but I needed to use SERIAL_8E1 for the even parity because:
SERIAL_8N1 means "8" bits, "N"o parity, and "1" stop bit (hence 8N1)
SERIAL_8E1 means "8" bits, "E"ven parity, and "1" stop bit (hence 8E1)
Here is the chart I used to get the protocol format I needed:
/* Baud-rates available: 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200, 256000, 512000, 962100
 *
 *  Protocols available:
 * SERIAL_5N1   5-bit No parity 1 stop bit
 * SERIAL_6N1   6-bit No parity 1 stop bit
 * SERIAL_7N1   7-bit No parity 1 stop bit
 * SERIAL_8N1 (the default) 8-bit No parity 1 stop bit
 * SERIAL_5N2   5-bit No parity 2 stop bits
 * SERIAL_6N2   6-bit No parity 2 stop bits
 * SERIAL_7N2   7-bit No parity 2 stop bits
 * SERIAL_8N2   8-bit No parity 2 stop bits
 * SERIAL_5E1   5-bit Even parity 1 stop bit
 * SERIAL_6E1   6-bit Even parity 1 stop bit
 * SERIAL_7E1   7-bit Even parity 1 stop bit
 * SERIAL_8E1   8-bit Even parity 1 stop bit
 * SERIAL_5E2   5-bit Even parity 2 stop bit
 * SERIAL_6E2   6-bit Even parity 2 stop bit
 * SERIAL_7E2   7-bit Even parity 2 stop bit
 * SERIAL_8E2   8-bit Even parity 2 stop bit
 * SERIAL_5O1   5-bit Odd  parity 1 stop bit
 * SERIAL_6O1   6-bit Odd  parity 1 stop bit
 * SERIAL_7O1   7-bit Odd  parity 1 stop bit
 * SERIAL_8O1   8-bit Odd  parity 1 stop bit
 * SERIAL_5O2   5-bit Odd  parity 2 stop bit
 * SERIAL_6O2   6-bit Odd  parity 2 stop bit
 * SERIAL_7O2   7-bit Odd  parity 2 stop bit
 * SERIAL_

CODE SOLUTION:
#include <HardwareSerial.h>

HardwareSerial BA(1);  // Use Hardware Serial on TTGO

void setup() {
  Serial.begin(9600);
  BA.begin(9600, SERIAL_8E1, 32, 33);  // (Baud rate, Protocol, RX, TX)
  ...  //rest of my code

The default for Arduino Serial is 8 data bits, no parity, one stop bit. The first page of your linked documents says: Start bit 1, Data bit 8, Parity bit Even, Stop bit 1. The mismatched parity parameter could explain a partial failure of this communication. The documentation for the Serial begin() method describes the various configuration options.
However, see also this thread: https://forum.arduino.cc/t/altsoftserial-how-to-change-parity-solved/668535
It appears that the various software serial libraries do not support EVEN parity settings. Use a hardware serial port on your TTGO Arduino instead. This may mean using SoftwareSerial for the debug printing (maybe with a USB/UART adapter) and dedicating the hardware serial port to your bank note reader.


text:
Improving moving mouse loop to optimize speed
Code:
#include <Mouse.h>
#include <hiduniversal.h>
#include "hidmouserptparser.h"
#include <USBController.h>

USBController controller;
USB Usb;
HIDUniversal Hid(&Usb);
HIDMouseReportParser Mou(nullptr);
String x;
String y;
boolean isX;
int recv;

void setup() {
    Mouse.begin();
    Usb.Init();
    delay(200);

    if (!Hid.SetReportParser(0, &Mou))
        ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
}

void loop() {
    Usb.Task();
    recv = controller.read();
    if ((recv-48)==29){ // recv = M
        // , : -4
        // /n : -38
        x="";
        y="";
        isX = true;
        while (true){
            recv = controller.read();
            if (recv!=0 && recv!=2){ // filter out 0 and 2
                if ((recv-48)==-38){ // -38 is a line break
                    break;
                }
                else if ((recv-48)==-4){ // switch to y value after comma
                    isX = false;
                    continue;
                }

                if (isX){
                    x+=String(recv-48);
                }
                else{
                    y+=String(recv-48);
                }
            }
        }
        Mouse.move(x.toInt(),y.toInt());
    }
}

void onButtonDown(uint16_t buttonId) {
    Mouse.press(buttonId);
}

void onButtonUp(uint16_t buttonId) {
    Mouse.release(buttonId);
}

void onMouseMove(int8_t xMovement, int8_t yMovement, int8_t scrollValue) {
    Mouse.move(xMovement, yMovement, scrollValue);
}

I'm using an Arduino leonardo with a usb host shield. My goal is to move my cursor to a specific location based on the data read in. Format of the data read in is "MX,Y" and a line break.
In the main loop,

I read the data and subtract 48 because that's the real number.
Then I check if the first character is M because that is where the beginning of my data starts.
Then I filter out 0 and 2 because those values are useless to me and randomly appear.
I loop to add the integer values as strings to x then switch to y after the comma appears.
Then I convert the string values to int and mouse.move.

The problem is the mouse movement is slow and jittery and I think it's because the toInt and String() methods are slowing it down. How could I improve my algorithm?

This:

while (true){
    recv = controller.read();
    // ...
}

is a blocking loop. This means that, while executing this part of the
code, the Arduino is stuck for an indeterminate amount of time, and can
do nothing else. Specifically, it cannot run Usb.Task(), which could
well be the cause of the jittery behavior you are experiencing.
I would recommend reading the incoming data in a non blocking fashion:
each time there is a byte to be read, read it and move on. Do not wait
for the subsequent bytes. Only when you find an end of line would you
handle the data you received. For example:
// Parse and execute a command received through USB.
executeCommand(String &command) {
    // Implementation left as an exercise to the reader.
}

// Whether we are presently receiving characters from a command.
bool receivingCommand = false;

// Received command, may be incomplete.
String command;

void loop() {
    Usb.Task();
    if (controller.available()) {
        char c = controller.read();
        if (!receivingCommand && c == 'M') {  // start of command
            receivingCommand = true;
        } else if (receivingCommand && c == '\n') {  // end of command
            executeCommand(command);
            command = "";
            receivingCommand = false;
        } else if (receivingCommand) {  // body of command
            command += c;  // buffer the received character
        }
    }
}

A better approach would be to avoid the String class, which is not
friendly to your Arduino's memory, and use a plain C string, as
explained in Reading Serial on the Arduino. This, however, is
likely unrelated to your jitter issue.

Thanks! How would I use a C string to this program. My input is originally a float and I need to add that to a character array. Don't I need to convert it to a String first?

@JakeJin: No, you do not need a String. You can convert a float to a character array using dtostrf().


text:
How to configure I2S with ESP32 and MAX98357A to reproduce wav files?
I have configured I2S to reproduce files with an ESP32 and a MAX98357A from and SD card. The problem is that it reproduces the files way too fast, like they are sped up * 100. Here is my (simplified) code:
#define I2S_DOUT 25
#define I2S_BCLK 27
#define I2S_LRC 26

void setup() {
// Start SD card and sqlite
  SPI.begin();
  if (!SD.begin()) {
    Serial.println("SD card not found");
    while (1) {};
  }
// Configure I2S
  i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = 44100,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S_MSB,
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count = 2,
      .dma_buf_len = 1024,
      .tx_desc_auto_clear = true,
  };

  i2s_pin_config_t pin_config = {
      .bck_io_num = I2S_BCLK,
      .ws_io_num = I2S_LRC,
      .data_out_num = I2S_DOUT,
      .data_in_num = -1,
  };

  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
  i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN);
  i2s_set_sample_rates(I2S_NUM_0, 44100);
}

void loop() {
// Play the audio file
  string filename = "/audios/" + text + ".wav";
  File file = SD.open(filename.c_str());
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  const size_t buffer_size = 512;
  uint8_t buffer[buffer_size];
  size_t bytes_read;
  size_t bytes_written;
  while (file.available() && (bytes_read = file.read(buffer, buffer_size)) > 0) {
    i2s_write(I2S_NUM_0, buffer, bytes_read, &bytes_written, portMAX_DELAY);
    if (bytes_read == 0) break;
  }
  file.close();
}

How do I configure it correctly?

So I figured it out (a somewhat long time ago) but forgot to post here hahaha.
Basically, the i2s_config_t was not properly configured. Here's a corrected version:
i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = 44100,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S_MSB,
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count = 8,
      .dma_buf_len = 1024,
      .use_apll = false,
      .tx_desc_auto_clear = true,
  };

If you compare, the .channel_format configuration changes from I2S_CHANNEL_FMT_RIGHT_LEFT to I2S_CHANNEL_FMT_ONLY_LEFT. This is important because when using RIGHT_LEFT and only using one amplifier, 2 sound outputs were sent but only one amp was receiving them, causing the sound to play at twice the speed. Now, the .dma_buf_count was increased to 8, and added the .use_apll config, because I saw it somewhere else, I don't really know what it does hahaha.
There are other things.
In the setup for the i2s communication, I didn't include
i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN);
i2s_set_sample_rates(I2S_NUM_0, 44100);

And created a new function, play_sound.
Here's the complete code:
// sound.cpp

#include <sound.h>

bool parseWavHeader(File &file, WavHeader &header) {
  if (file.read() != 'R' || file.read() != 'I' || file.read() != 'F' || file.read() != 'F') {
    Serial.println("Invalid WAV file");
    return false;
  }

  file.seek(22);
  header.num_channels = file.read() | (file.read() << 8);
  header.sample_rate = file.read() | (file.read() << 8) | (file.read() << 16) | (file.read() << 24);
  file.seek(34);
  header.bits_per_sample = file.read() | (file.read() << 8);
  file.seek(44);  // Skip to the audio data
  return true;
}

void setup_sound() {
  i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = 44100,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S_MSB,
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count = 8,
      .dma_buf_len = 1024,
      .use_apll = false,
      .tx_desc_auto_clear = true,
  };

  i2s_pin_config_t pin_config = {
      .bck_io_num = I2S_BCLK,
      .ws_io_num = I2S_LRC,
      .data_out_num = I2S_DOUT,
      .data_in_num = -1,
  };

  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
}

void play_sound(std::string text, fs::FS &SD) {
  std::string filename = "/audios/" + text + ".wav";
  File file = SD.open(filename.c_str());
  if (!file) {
    Serial.println("Failed to open file for reading");
    while (1) delay(1);
  }

  WavHeader header;
  if (!parseWavHeader(file, header)) {
    Serial.println("Invalid WAV file");
    return;
  }

  i2s_set_sample_rates(I2S_NUM_0, header.sample_rate);

  const size_t buffer_size = 512;
  uint8_t buffer[buffer_size];
  size_t bytes_read;
  size_t bytes_written;
  while (file.available() && (bytes_read = file.read(buffer, buffer_size)) > 0) {
    i2s_write(I2S_NUM_0, buffer, bytes_read, &bytes_written, portMAX_DELAY);
    if (bytes_read == 0) break;
  }

  file.close();
}

// sound.h

#ifndef SOUND_H
#define SOUND_H

#include <SD.h>
#include <driver/i2s.h>

#define I2S_DOUT 25
#define I2S_BCLK 33
#define I2S_LRC 26

struct WavHeader {
  uint32_t sample_rate;
  uint16_t bits_per_sample;
  uint16_t num_channels;
};

bool parseWavHeader(File &file, WavHeader &header);
void setup_sound();
void play_sound(std::string text, fs::FS &SD);

#endif  // SOUND_H

Hope it helps you not go through the struggle I went through!

good job.
the another solution is to change the .sample_rate = 16000, can play well. for the file saved at same sample_rate.


text:
OEM Arduino UNO not seen by COM port
Arduino UNO R3
My error code:
avrdude: ser_open(): can't set com-state for "\.\COM3"
An error occurred while uploading the sketch
This has been mentioned several times before here in the Stack.  I have been through several of them and followed the steps to delete/reinstall the CH340G Serial driver, change cables, and changed the USB port selection on the computer, all without success.  The computer will 'see' the UNO.
I use Windows 11.  I also learned that the card is a counterfeit from LAFVINTECH.COM.
At the moment, I have no answers.  I've tried everything I know of except taking it to the gun range.

Did you try turning the computer off then on again?

Have you seen this Q+A? https://arduino.stackexchange.com/questions/55301/avrdude-ser-open-cant-set-com-state

Did you assign USB on the Windows computer?  Then Arduino IDE should be able to find the hardware when uploading the Sketch. This works for me.

Here are the answers to the above comments.

Did you try turning the computer off then on again? –
VE7JRO
YES
Have you seen this Q+A? arduino.stackexchange.com/questions/55301/… –
VE7JRO
YES.
Did you assign USB on the Windows computer? Then Arduino IDE should be able to find the hardware when uploading the Sketch. This works for me. –
John
The Computer automatically assigns a COM port to the connection.  There are three USB ports on the front of the tower.  They are COM 3, COM 4, and COM5.  The computer has the correct Driver and then responds with a visible tie between card and PC.

The Computer automatically assigns a COM port to the connection.   ....  Normally in Arduino IDE you can pull down and change this,

I have more information that may be helpful - I connected an ATMEGA328P_U (call this one "A") to TWO different PCs and it worked fine.  I then connected an ATMEGA328P_U_TH (Call this one "B") to both PCs and it did not 'see' the card in the proper way.    "A" com port responded by adding 'Arduuino Uno' to the COM port number.  "B" did not.


text:
Using library functions in timer ISR ESP32
I'm trying to use a library function in my ISR function that uses the internal timer to trigger every 1 ms. The chip that I'm using is an ESP32-C3-MINI. Here is my current code:
main.cpp
#include <Arduino.h>
hw_timer_t *_timer = NULL;
myClass a();

void IRAM_ATTR isr()
{
    a.incrementCount();
}

void setup()
{
    coin_timer = timerBegin(0, 80, true);
    timerAttachInterrupt(_timer, &isr, true);
    timerAlarmWrite(_timer, 1000, true);
    timerAlarmEnable(_timer);
}

myClass.h
#include <Arduino.h>

class myClass
{
private:
    unsigned long count;

public:
    myClass();
    ~myClass();

    void incrementCount();
}

myClass.cpp
#include <Arduino.h>
#include "myClass.h"

myClass::myClass(){

}

void myClass::incrementCount(){
    count++;
}

This is just an example of the code that I wrote. In reality, the incrementCount function is a little more complicated and involves multiple variables and arrays within the library. This current code compiles and works without an issue. However, I would like to know if this method is bad practice or can cause problems in certain situations. Secondly, I notice if I declare count variable as volatile, the MCU just crashes and enters a reboot cycle.


text:
ARDUINO DC Motor Control over IR Sensor INPUT
I'm working on a school project where I'm building a small convyeor belt using an ARDUINO, DC motor and IR sensor for moving object detection so my color sensor can read color value.
I'm using single mosfet IRFZ44N to control DC motor. I can control DC motor using mosfet normally as turning it ON/OFF using digitalWrite using an arduino.
So, I want to stop convyeyor belt for 500ms when IR sensor detects HIGH and let color sensor read color of object and then let object move ahead normally on belt.
I have written below code but the IR sensor detect object but motor never stops running.
#define IR_COLOR 34

const int MOTORpin = 32;
const long onDuration = 1000;// OFF time for LED
const long offDuration = 1000;// ON time for LED
int MOTORState =HIGH;// initial state of LED

boolean MOTOROnFlag          = true;

long rememberTime=0;

void setup() {
  pinMode(IR_COLOR, INPUT);
  pinMode(MOTORpin,OUTPUT);// define MOTORpin as output
  digitalWrite(MOTORpin,MOTORState);// set initial state
}

void loop() {

  int state = digitalRead(IR_COLOR);

 if( state == false )
 {
    if( (millis()- rememberTime) >= onDuration){
    MOTORState = LOW;
    rememberTime=millis();
    }
 }
 else if(state == true)
 {
    if( (millis()- rememberTime) >= offDuration){
    MOTORState =HIGH;// change the state of LED
    rememberTime=millis();// remember Current millis() time
    }
 }

 digitalWrite(MOTORpin,MOTORState);// turn the LED ON or OFF

}// loop ends

you have no IR sensor code

@jsotola IR_COLOR is IR Sensor.

what is IR_RED then?

@jsotola It was made for future work but the initial task is not completed of stoping motor pin for 500ms and starting motor again. Motor stops as IR detects object but it remains off as object is still ahead of IR sensor.

so what will you name the color sensor? ... it seems like you are using confusing names

insert a layer of separation between the sensor and the motor ... use a run flag ... set it at beginning ... sensor clears the flag and starts a timer ... timer expiration sets the flag .... further down in the code, if flag is set, then run motor

@jsotola I'm using total 5 IR sensor and 1 color sensor. as IR_COLOR is the first IR sensor which is close to color sensor so I named it as IR_COLOR. So, that's not a big issue for me. I will name color sensor as something COLOR_Sen.

@jsotola Please, can you provide demo code related to flag for arduino? You may edit mine code too if you wish!

you are already using a flag variable in your code ... it is named state

YES! It's little confusing to me! can you please insert your logic of clearing flag by sensor in my code?

pick a value for set and a value for clear ... true/false ... HIGH/LOW ... 1/-1 ... 10/20 ... "abc"/"xyz" ... etc. etc. ... right now your code uses HIGH and LOW ... true/false is the most convenient because the if statements operate on true/false ... if ( state ) {} and  if ( !state ){}

use pen and paper... write description of the desired behavior in words ... something like if sensor is LOW then clear the flag ... a clear description translates to code almost directly

I have edited my code a bit and here's it! I don't understant arduino flags so I wanted you to edit my basic code with flags!  Here's my edited code link:    https://drive.google.com/file/d/1ulzu5nnARIugKC4R7LD0-OWzkvYRSgdi/view?usp=sharing

there is no such thing as arduino flags ... this is C or C++ programming ... you are already using a flag variable in your code ... the flag name is state ... the value of the flag variable controls the motor if (state == LOW) digitalWrite(Motor, LOW);  ... I don't know if that turns the motor on or off ... I will not download anything from Google drive

@jsotola Indeed! But the problem lies with the timing! As, Object reaches ahead of IR sensor, the ESP32 turns off motor as mentioned in code but I want it to stay off for a few ms like 500ms and after 500ms it ESP32 should start the motor again even though IR sensor is detecting object! How can I translate this in code for arduino?

@jsotola I have edited the code in main post of mine! You may check that for reference!

You have the general idea.
Your code looks a bit cluttered. Comments are not part of the program, keep them away from the code.
The if statements reduce to if (true), that means that == true part is redundant.
All you need is if(state). The if block will execute when state is true.
Conversely if (!state) tests for state being false
When there are only two possible values, then else if(state == true) can be simply else.
Identical code that is in both parts of the if-else block should be moved to outside of the block, rememberTime=millis(); should be moved to after the closing brace } of the if-else block.
Here is some code that does what you want.
This code has not been tested on a hardware device.
https://wokwi.com/projects/364353854313747457
const int     sensor_blocked  = LOW;              // define sensor values
const int     sensor_clear    = HIGH;

const int     motor_on        = HIGH;
const int     motor_off       = LOW;

const int     master_enable   =  2;
const int     motor_pin       =  3;
const int     sensor_pin      = 12;

int           sensor_state;
int           sensor_previous = sensor_clear;
int           motor_state     = motor_on;

unsigned long millis_previous = 0;
unsigned long millis_now;

const long    interval        = 500;

void setup() {

  pinMode(master_enable, INPUT_PULLUP);
  pinMode(sensor_pin,    INPUT_PULLUP);
  pinMode(motor_pin,     OUTPUT);

}

void loop() {

  sensor_state = digitalRead( sensor_pin );

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

  if ( sensor_state != sensor_previous ) {             // only run this code when sensor state changes
    sensor_previous = sensor_state;                    // remember new sensor state

    if ( sensor_state == sensor_blocked ) {            // sensor became blocked
      motor_state = motor_off;                         // turn off motor
      millis_previous = millis();                      // start of "motor off" interval
    }
    delay(20);                                         // debounce sensor
  }

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

  if ( motor_state == motor_off ) {                    // timer check is relevant only when motor is off
    millis_now = millis();
    if ( millis_now - millis_previous >= interval ) {  // check if timer expired
      motor_state = motor_on;                          // enable motor
    }
  }

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

  if ( digitalRead( master_enable ) != LOW ) motor_state = motor_off;     // master switch

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

  digitalWrite(motor_pin, motor_state);                // translate motor state into action

}


text:
Avoid 1-LSB noise on ADC readings
I have a potentiometer connected to an ADC input of an Arduino Leonardo.
The ADC resolution is 10-bit (0..1024), while I need just 7-bit (0..127).
I use a simple filter to reduce the noise and then a map to cut the unused bits:
#define ADC_CH                18
#define ADC_FILTER            0.90

uint16_t value;

uint16_t adc = analogRead(ADC_CH);
value = (uint16_t) ((float) ADC_FILTER * adc + (1. - ADC_FILTER) * value);

I show value on an LCD. It's very stable, but it may happen that if the adc readings are in the nearby of two values, there is nothing that could prevent a change in the final value, even if the noise is of just few LSBs.
Is there a simple way to implement an hysteresis for each low-res value?
In this way the change between N and N+1 happens on a different ADC reading than between N and N-1, improving the noise rejection without increasing the filter delay (that would only increase the change interval).

When you reduce the resolution from 10 bits to 7 bits, every possible
output corresponds to an interval of inputs. If you add some hysteresis,
then those intervals should overlap. Below is a representation of the
input intervals corresponding to outputs 0, 1,… 6, for an
hysteresis width of 4:
input: 0    5   10   15   20   25   30   35   40   45   50   55   60
       └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴
       ├─────0────┤
           ├───────1──────┤
                   ├───────2──────┤
                           ├───────3──────┤
                                   ├───────4──────┤
                                           ├───────5──────┤
                                                   ├───────6──────┤

To implement this in code, you have to remember the last output, and
change it only if the input lies outside the interval assigned to this
output. Here is an example implementation:
const int hysteresis = 4;  // tune to taste

/* Remove 3 bits of resolution while adding some hysteresis. */
int resample(int adc)
{
    static int value;  // last output
    if (adc < (value<<3) - hysteresis) {
        value = (adc + hysteresis) >> 3;
    } else if (adc >= ((value+1)<<3) + hysteresis) {
        value = (adc - hysteresis) >> 3;
    }
    return value;
}

Note that a static local variable keeps its value between successive
calls to the function.

I'm not supposed to do this but anyway: excellent answer! Nice graphic, well explained. :)

Your code works perfectly and it fits exactly the example in my question. Anyway, is there a more general approach? For example, what if I want to map the ADC input to [min, max] (always < 1024) ?

@Mark: Then you would replace the shifts (which are basically optimized multiplications and divisions) by arbitrary map()s. You may then want to do some tests in order to see how the rounding errors introduced by the map interfere with the hysteresis.


text:
Why Did I Have To Program Duemilanove Bootloader?
As a volunteer for Public Invention, I have developed an Atmega328 based design in which I thought I was largely duplicating the Arduino UNO.
Unlike the UNO, I did choose a CH340 USB to UART chip as that was a part on some UNO clones I have purchased.
Our project, the General Alarm Device, is at:
https://github.com/PubInv/general-alarm-device
In the summer of 2022 We built up 15 Verion 1 assemblies.
When we went to put boot loader into them we found we could put the Duemilanove bootloader but not the UNO.  We do not know why.
Even with the Duemilanove bootloader we from time to time have problems uploading code. Some times the IDE reports a problem but the code uploaded.  And perhaps some times we had to try to load more than once.
Here is an issue written up after one user had some difficulty with firmware upload:
https://github.com/PubInv/general-alarm-device/issues/127
Related questions,
Is their a way to check which boot loader is in a board?
Could our root problem have been due to which boot loader was on the UNO we were using as the ICP?

the difference is the upload baud rate. Duemilanove bootloader uses much slower baud rate. you have some problem with the USB to TTL Serial circuit

Hello Juraj,  Can you point me to documentation for these baud rates. For what should I google?

see the boards.txt file for the AVR platform. (or read in the IDE console the  parameters of the upload command)

Related questions, Is their a way to check which boot loader is in a board?

I wrote some code to detect chip signatures a while ago which also reports on known bootloaders: http://www.gammon.com.au/forum/?id=11633
It really is too long to post here. The code however is at https://github.com/nickgammon/arduino_sketches in particular in the Atmega_Board_Detector folder.
It's the same processor chip, you shouldn't have problems uploading, provided you use the appropriate clock speed and baud rate.
See my answers here:

Have I bricked my Arduino Uno? Problems with uploading to board

What happens when code is uploaded using the bootloader?

Where do I learn what is appropriate?

Well, the bootloaders have hard-coded into them the speed at which they expect the serial data to arrive. In the case of Optiboot it is 115200 baud, some other bootloaders may use 9600, 57600 or other speeds.
Now this baud rate is also dependent on the clock rate of the processor, because the baud rate is derived from the system clock.
So for example, on a Uno, Optiboot "expects" (in the sense that a computer can expect anything) that it will be running on a board at 16 MHz, and that the communication will be at 115200 baud.
So, if you are running at 8 MHz (half that speed) then the baud rate will naturally be 57600. However you can compensate for that by editing the file boards.txt in your Arduino installation and changing the baud rate, eg.
uno.name=Arduino Uno

uno.vid.0=0x2341
uno.pid.0=0x0043
uno.vid.1=0x2341
uno.pid.1=0x0001
uno.vid.2=0x2A03
uno.pid.2=0x0043
uno.vid.3=0x2341
uno.pid.3=0x0243

uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.maximum_data_size=2048
uno.upload.speed=115200

uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0xFD
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex

uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.board=AVR_UNO
uno.build.core=arduino
uno.build.variant=standard

Change the line "uno.upload.speed" to read 57600 in this case. That way the program (avrdude) which uploads to the board will upload slower, and since you are running at a slower speed, all will be well.

So, to make it all work:

Find which bootloader you have (by comparing signatures) or simply upload a new bootloader of a known type. I have a page about uploading bootloaders which might help you there.

Look up (eg. in that file) what the baud rate this particular bootloader uses (eg. 115200 for Optiboot).

Set your processor to run at that clock speed with a crystal or resonator. (see the line "uno.build.f_cpu" which is 16000000 in this case).

If you choose to run the processor at a different speed (eg. using the internal clock, at 8 MHz) then either use a bootloader designed for 8 MHz, or change the upload speed baud rate line in the file as mentioned above. I suggest copy/pasting an existing entry, changing for example "uno" at the start of each line to "myboard" or something like that, and the "name" line as well, so it will appear in the drop-down menu of available boards).

Hello Nick,  Thanks for the link to the code I hope to try it soon.   Regarding "provided you use the appropriate clock speed and baud rate."  Where do I learn what is approprate. That is what I am asking about here. I am not afraid to read docuementation but have no idea the key words for which to search.

@ForrestErickson See amended answer.


text:
Serial does not receive all chars
I'm trying to follow Serial Input Basics to build a program which receives commands over serial like "<led:12,34,21>" but i'm stuck on receiving the characters from serial...
I have copied the code from the example for receiveWithStartAndEndMarkers but it does not show that i received all the characters over serial
const int kMaxCommandSize=30;
char receivedChars[kMaxCommandSize + 1];
char command[kMaxCommandSize + 1];
boolean newData = false;

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

void loop() {
  recvWithStartEndMarkers();
  if(newData){
    ProcessCommand();
    newData = false;
  }
}

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

 // if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= kMaxCommandSize) {
                    ndx = kMaxCommandSize - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
        } else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void ProcessCommand() {
  Serial.println("Received:");
  Serial.println(receivedChars);
}

But when i send <123> i am consistently seeding
Received:
1
Received:
1
Received:
1

or when i send <asdf1234> i see
Received:
a
Received:
a
Received:
a

EDIT: it looks like sometimes the full transmission works... But not often i just sent <123> four times and got
Received:
123
Received:
12
Received:
1
Received:
123

Your provided sketch is not complete and does not compile, how and where is kMaxCommandSize defined? -- OT: I love this safe comparisons for booleans, you should make sure that it really works: (newData == false) == true. ;-) Hint: if it does not read nice, consider to rename the variable, for example to hasNewData.

I can't reproduce that. On my Uno, with the added line const int kMaxCommandSize = 32; it works perfectly.

Which Arduino are you testing it on?

@thebusybee sorry, kMaxCommandSize can be replaced by 30

@NickGammon I tried on a Mega (where the issue originally occurred), and a Uno. On the Uno it doesnt even reply! Its like the messages go no where.... Maybe both of them are bad...

You may try a simpler program that just echoes whatever it receives: void loop(){if(Serial.available())Serial.write(Serial.read());}. If it's still unreliable, look at the TX and RX pins with an oscilloscope.


text:
cant flash my nodemcu esp8266
So i wanted to flash my Nodemcu esp8266 v3.4 with esp8266 deauther code: script-github
i did everything said. First i plugged in my nodemcu. Windows detected it and drivers for ch340 where already installed. I tried using the Nodemcu firmware programmer programm for flashing, but when starting flashing in the log there it was just stuck on "begin finding esp8266". then i tried using the arduino ide, again i did everything the github wiki said. but i got this:
Sketch uses 829464 bytes (79%) of program storage space. Maximum is 1044464 bytes.
Global variables use 32132 bytes (39%) of dynamic memory, leaving 49788 bytes for local variables. Maximum is 81920 bytes.
esptool.py v2.8
Serial port COM5
Traceback (most recent call last):
  File "C:\Users\jakob\AppData\Local\Arduino15\packages\deauther\hardware\esp8266\2.7.5/tools/upload.py", line 65, in <module>
    esptool.main(cmdline)
  File "C:/Users/jakob/AppData/Local/Arduino15/packages/deauther/hardware/esp8266/2.7.5/tools/esptool\esptool.py", line 2889, in main
    esp = chip_class(each_port, initial_baud, args.trace)
  File "C:/Users/jakob/AppData/Local/Arduino15/packages/deauther/hardware/esp8266/2.7.5/tools/esptool\esptool.py", line 237, in __init__
    self._port = serial.serial_for_url(port)
  File "C:/Users/jakob/AppData/Local/Arduino15/packages/deauther/hardware/esp8266/2.7.5/tools/pyserial\serial\__init__.py", line 88, in serial_for_url
    instance.open()
  File "C:/Users/jakob/AppData/Local/Arduino15/packages/deauther/hardware/esp8266/2.7.5/tools/pyserial\serial\serialwin32.py", line 78, in open
    self._reconfigure_port()
  File "C:/Users/jakob/AppData/Local/Arduino15/packages/deauther/hardware/esp8266/2.7.5/tools/pyserial\serial\serialwin32.py", line 222, in _reconfigure_port
    'Original message: {!r}'.format(ctypes.WinError()))
serial.serialutil.SerialException: Cannot configure port, something went wrong. Original message: PermissionError(13, 'Ein an das System angeschlossenes Ger�t funktioniert nicht.', None, 31)
Failed uploading: uploading error: exit status 1

always format printouts as code for readability


text:
What is the most simple sketch to confirm the DAC works for audio on a speaker with it's own amplifier for an ESP32?
I have a PC speaker with it's owner power supply (no amplifier needed). It just uses a standard AUX jack.
Most examples sketches use an amplifier like the MAX98357A. I have explored some libraries too, such as ESP8266Audio.
I just want to find a simple example that emits audio (not just noise). This is my setup:

I thought an audio program would use the internal DAC to create the CODEC? Or am I not understanding something?
const int  DAC_CH1 = 25; // or 26

void setup()
{
//    dacWrite(DAC_CH1, 255); // ~3v3
//  dacWrite(DAC_CH1, 192); // ~2.5
//  dacWrite(DAC_CH1, 128); // ~1.7
}

void loop(){}

Edit
I found the PlayMODFromPROGMEMToDAC example, which uses pin 25 DAC:
#include <Arduino.h>
#include "AudioFileSourcePROGMEM.h"
#include "AudioGeneratorMOD.h"
#include "AudioOutputI2S.h"
#if defined(ARDUINO_ARCH_RP2040)
    #define WIFI_OFF
    class __x { public: __x() {}; void mode() {}; };
    __x WiFi;
#elif defined(ESP32)
    #include <WiFi.h>
#else
    #include <ESP8266WiFi.h>
#endif

// enigma.mod sample from the mod archive: https://modarchive.org/index.php?request=view_by_moduleid&query=42146
#include "enigma.h"

AudioGeneratorMOD *mod;
AudioFileSourcePROGMEM *file;
AudioOutputI2S *out;

void setup()
{
  WiFi.mode(WIFI_OFF); //WiFi.forceSleepBegin();
  Serial.begin(115200);
  delay(1000);

  audioLogger = &Serial;
  file = new AudioFileSourcePROGMEM( enigma_mod, sizeof(enigma_mod) );

   /* HERE! */
   // ↓
   // ↓
   out = new AudioOutputI2S(0, 1); //Uncomment this line, comment the next one to use the internal DAC channel 1 (pin25) on ESP32
   // ↑
   // ↑
//  out = new AudioOutputI2S();
  mod = new AudioGeneratorMOD();
  mod->SetBufferSize(3*1024);
  mod->SetSampleRate(44100);
  mod->SetStereoSeparation(32);
  mod->begin(file, out);
}

void loop()
{
  if (mod->isRunning()) {
    if (!mod->loop()) mod->stop();
  } else {
    Serial.printf("MOD done\n");
    delay(1000);
  }
}

Although, still no sound (besides noise) can be heard.

no need for DAC ... toggle a digital pin

What do you mean by "audio not just noise"? Can't you simply toggle the pins? An alternative would be to use the sin() function to generate a "clean" note.

Ideally something like talkMIDI(0xC0, instrument, 0) as found here: https://www.sparkfun.com/tutorials/302


text:
Troubleshoot/Diagnose Arduino circuit
I've built the attached circuit with the following changes:

I used Arduino Nano
I used 10K pot
12V is connected to VIN pin (instead of RAW)
the Arduino was connected to the PC by USB for the use of serial communication.

I used 12V 4Pin fan (C25704-002)
Here is the code, I used:
    const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to

int sensorValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)

void setup() {
   // Configure Timer 1 for PWM @ 25 kHz.
    TCCR1A = 0;           // undo the configuration done by...
    TCCR1B = 0;           // ...the Arduino core library
    TCNT1  = 0;           // reset timer
    TCCR1A = _BV(COM1A1)  // non-inverted PWM on ch. A
           | _BV(COM1B1)  // same on ch; B
           | _BV(WGM11);  // mode 10: ph. correct PWM, TOP = ICR1
    TCCR1B = _BV(WGM13)   // ditto
           | _BV(CS10);   // prescaler = 1
    ICR1   = 320;         // TOP = 320

    // Set the PWM pins as output.
    pinMode( 10, OUTPUT);

}

// PWM output @ 25 kHz, only on pins 9 and 10.
// Output value should be between 0 and 320, inclusive.
void analogWrite25k(int value)
{

    OCR1A = value;

}

void loop() {
    // read the analog in value:
    sensorValue = analogRead(analogInPin);

    // map it to the range of the analog out:
    outputValue = map(sensorValue, 0, 1023, 0, 320);

    analogWrite25k(outputValue);

I have the following questions:

The circuit was working for couple of minutes but then I smelled the famous electronic components barbecue smell, so I disconnected the GND power line and when I did I felt that the GND line was hot, I think I fried the Arduino, Do you have an idea what can fry the Arduino?
The Potentiometer (10K) was not sensitive, It worked only on some range of the knob, What resistance should I use?

Thanks.

you connected 12 V to A0


text:
How to make the built-in LED blink with a frequency of 5 Hz using interrupts
The task is: after five clicks on OK, the built-in LED starts flashing with a frequency of 5Hz using an interrupt. After the eighth click on OK, the flashing (and glowing) should stop.Why is flashing not working
bool ledState = false;
volatile bool ledOn = true;

void setup(){
TCCR2A = 0;
  TCCR2B = 0;
  TIMSK2 = 0;
  TCNT2 = 0;
  OCR2A = 77;
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
  TIMSK2 |= (1 << OCIE2A);
 pinMode(13, OUTPUT);
}

void loop(){
 if(button5.buttonPressedCount >= 5 && button5.buttonPressedCount < 8){
    ledState = true;
  }

  if(button5.buttonPressedCount > 7){
    ledState = false;
  }
}

ISR(TIMER2_COMPA_vect){
  if(ledState){
  digitalWrite(13, ledOn);
  ledOn = !ledOn;
  }
}

Why OCR2A = 77;?

The value for obtaining a frequency of 5 Hz with a divider of 1024

Could you please explain, within the question, how you go from “f = 5 Hz” to OCR2A = 77;?

timer will run at a frequency of 16 MHz / 1024 = 15.625 kHz, so desired interrupt frequency = (77 + 1) * 15.625 kHz / 1024 = 5 Hz

This calculation is wrong.

then what should the values be?

15.625kHz / 5 Hz = 3125. So I would set OCR2A to 3125. A value of 77 would be about 203Hz

I set to 3125 if this correct signal: link

Could you use Timer 1 instead of Timer 2?

yes I can, then what values should be set?

On the Uno (ATmega328P microcontroller), timers 0 and 2 are 8-bit only:
they cannot count beyond 255. Timer 1, on the other hand, is 16-bits.
This is the most convenient timer for generating low frequencies.
Speaking of frequencies... One LED period involves two toggles (turn on,
then turn off). Thus, if you want the LED to blink at 5 Hz, the toggle
action should happen at 10 Hz. Given that the CPU is clocked at 16 MHz,
this means you have to toggle the LED every 1,600,000 CPU cycles.
If you set the prescaler to 1,024, you then you have to count
1,600,000/1,024 = 1,562.5 timer cycles. You cannot count a non-integer
number of cycles, but you probably do not care about such accuracy. If
you do care, set the prescaler to 256 and count 1,600,000/256 =
6,250 timer cycles by setting the compare match register to 6,249.
One last issue: keep in mind that, in normal counting mode, the timer
counts up to its maximum value (65,535, or 255 on an 8-bit timer) and
then restarts at zero. If you want it to count only up the value set in
the compare match register, you should choose the appropriate waveform
generation mode: the fast PWM mode that lets you control the TOP value
with OCR1A.

then it should look like this? TCCR1A = 0; TCCR1B = 0; TIMSK1 = 0; TCNT1 = 0; OCR1A = 6249; // Set compare match value for prescaler 256 TCCR1B |= (1 << CS12); // Set prescaler to 256 TIMSK1 |= (1 << OCIE1A); // Enable interrupt on compare match A

@GoodYork: Read the datasheet and see how to set the appropriate waveform generation mode.

like this: TCCR1A = (1 << WGM11) | (1 << COM1A0);   TCCR1B = (1 << WGM12) | (1 << WGM13) | (1 << CS12);   TIMSK1 = (1 << OCIE1A);   OCR1A = 6250;


text:
Program work when used Delay() but same program doesn't work with millis()
I'm running a dc motor using esp32 and mosfet by taking readings of IR.
Program works fine when used delay() but same program doesn't work when uploaded using millis().
//This uses fixed delay()

// Pin definitions
const int irSensorPin = 34;  // IR sensor connected to GPIO 2
const int motorPin = 32;     // DC motor connected to GPIO 4

// Variables
bool isObjectDetected = false;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Set pin modes
  pinMode(irSensorPin, INPUT);
  pinMode(motorPin, OUTPUT);
}

void loop() {
  // Check if object is detected
  if (digitalRead(irSensorPin) == LOW) {
    if (!isObjectDetected) {
      // Object detected for the first time
      isObjectDetected = true;
      Serial.println("Object detected. Stopping motor.");
      digitalWrite(motorPin, LOW);  // Stop the motor
      delay(500);                   // Wait for 500ms
      Serial.println("Resuming motor.");
      digitalWrite(motorPin, HIGH); // Start the motor
    }
  } else {
    if (isObjectDetected) {
      // Object is no longer detected
      isObjectDetected = false;
    }
  }
}

//This uses millis()

// Pin definitions
const int irSensorPin = 34;  // IR sensor connected to GPIO 34
const int motorPin = 32;     // DC motor connected to GPIO 32

// Variables
bool isObjectDetected = false;
unsigned long motorStopTime = 0;
const unsigned long motorDelayTime = 500;  // Delay time in milliseconds

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Set pin modes
  pinMode(irSensorPin, INPUT);
  pinMode(motorPin, OUTPUT);

  // Initialize motor state
  digitalWrite(motorPin, HIGH);  // Start the motor
}

void loop() {
  // Check if object is detected
  if (digitalRead(irSensorPin) == HIGH) {
    if (!isObjectDetected) {
      // Object detected for the first time
      isObjectDetected = true;
      Serial.println("Object detected. Stopping motor.");
      digitalWrite(motorPin, LOW);  // Stop the motor
      motorStopTime = millis();     // Record the stop time
    }
  } else {
    if (isObjectDetected) {
      // Object is no longer detected
      isObjectDetected = false;
      unsigned long currentTime = millis();
      if (currentTime - motorStopTime >= motorDelayTime) {
        Serial.println("Resuming motor.");
        digitalWrite(motorPin, HIGH); // Start the motor
      }
    }
  }
}

“doesn't work” is not a useful description of the problem. What is the expected behavior? What is the actual behavior?

@EdgarBonet Sorry for my bad clarification. I have made a program where IR sensor detects object and the dc motor has to turn off for 1 sec or 500ms. In first of my program it works fine. motor starts normally, ir detects object and tell motor to wait for 1 sec and then motor starts again after 1 second even if ir sensor is detecting object ahead. In my second program, I'm using millis() with 500ms delay but that program doesn't start the motor normally.

I posted a code example to a similar question at https://arduino.stackexchange.com/questions/93115/arduino-dc-motor-control-over-ir-sensor-input ... it includes a link to a simulation

@jsotola switch?

What print statements are you seeing? Could be that the input in "chattering" since you are not debouncing it at all, and so motorStopTime is continuing to get reset to the current time.

switch? ... I have no idea what that means

I am not sure I quite understand what the requirements are for this
program. However, they do not do the same thing. I tried to represent
their behavior as state diagrams, and here is what I got:
Version using delay():

Version using millis():

In the above diagrams, states with a gray background are those where the
motor is off. As can be seen here, the first version never keeps the
motor off for more than 0.5 s, where the second one can keep the
motor indefinitely off if the sensor remains HIGH.
I suggest you start by drawing the state diagram corresponding to the
behavior you actually want. Then, use the technique outlined in this
tutorial on finite state machines to turn the diagram into code.
Note that finite state machines work well with millis()-based timing.


text:
I2C Motor Driver (TB6612FNG) and DC fan error
I running the following code with Seeeduino Cortex M0, DC fan  and Grove - I2C Motor Driver (TB6612FNG) but I get error ,any idea why?
Code:
#include "Grove_Motor_Driver_TB6612FNG.h"
#include <Wire.h>

MotorDriver motor;

void setup()
{
    // join I2C bus (I2Cdev library doesn't do this automatically)
    Wire.begin();
    Serial.begin(9600);
    motor.init();
}

void loop()
{
    // drive 2 dc motors at speed=255, clockwise
    Serial.println("run at speed=255");
    motor.dcMotorRun(MOTOR_CHA, 255);
    delay(1000);

}

Errors:
c:\Users\alirazi\Desktop\libraries\Grove_-_Motor_Driver_TB6612FNG\I2Cdev.cpp: In static member function 'static int8_t I2Cdev::readBytes(uint8_t, uint8_t, uint8_t, uint8_t*, uint16_t)':
c:\Users\alirazi\Desktop\libraries\Grove_-_Motor_Driver_TB6612FNG\I2Cdev.cpp:276:62: error: 'BUFFER_LENGTH' was not declared in this scope
             for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) {
                                                              ^~~~~~~~~~~~~
c:\Users\alirazi\Desktop\libraries\Grove_-_Motor_Driver_TB6612FNG\I2Cdev.cpp:276:62: note: suggested alternative: 'REG_DSU_LENGTH'
             for (uint8_t k = 0; k < length; k += min(length, BUFFER_LENGTH)) {
                                                              ^~~~~~~~~~~~~
                                                              REG_DSU_LENGTH
c:\Users\alirazi\Desktop\libraries\Grove_-_Motor_Driver_TB6612FNG\I2Cdev.cpp: In static member function 'static int8_t I2Cdev::readWords(uint8_t, uint8_t, uint8_t, uint16_t*, uint16_t)':
c:\Users\alirazi\Desktop\libraries\Grove_-_Motor_Driver_TB6612FNG\I2Cdev.cpp:416:70: error: 'BUFFER_LENGTH' was not declared in this scope
             for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) {
                                                                      ^~~~~~~~~~~~~
c:\Users\alirazi\Desktop\libraries\Grove_-_Motor_Driver_TB6612FNG\I2Cdev.cpp:416:70: note: suggested alternative: 'REG_DSU_LENGTH'
             for (uint8_t k = 0; k < length * 2; k += min(length * 2, BUFFER_LENGTH)) {
                                                                      ^~~~~~~~~~~~~
                                                                      REG_DSU_LENGTH

exit status 1

Compilation error: exit status 1

it tells you why on the second line of the error message

This is the example from the Grove - I2C Motor Driver (TB6612FNG) library, any idea how to solve it?
adding #define BUFFER_LENGTH 132 dows not work


text:
RFID card read loop seems to stop
I successfully programmed an RFID card reader to switch lights on and off if any rfid card is presented.  I have tested this and it works, with the lights continually switching on and off if any rfid enabled card is is presented.
I tried to add a command that if two specific cards are read (identified by their UID numbers) then only those cards would reset the lights to "off" no matter what the state they were currently in - like a reset button.
The problem is that once one of those cards is presented, the light goes off but the system stops responding and presenting one of the other cards no longer turns the light on and off.
I am fairly new to programming Arduino, as well as with RFID technology, but it seems like the loop does not reset to the beginning properly, or my IF statement somehow leaves the system in a state where the beginning code can't be run.
My code is below.  Any thoughts would be appreciated.
`
#define r1 A0
int relay1 = LOW;

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

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

  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  Serial.println("Approximate your card to the reader...");
  Serial.println();
}

void loop()
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }

// Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content = "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();

  if ((content.substring(1) == "23 49 1F BE") || (content.substring(1) == "CB CB 2C E3")) //change here the UID of the card/cards that you want to give access
  {
   Serial.println("Staff access");
    Serial.println();
    relay1 = HIGH;
    digitalWrite(r1, relay1);
    delay(500);
  }
  else
  {

    Serial.println("Authorized access");
    Serial.println();
    relay1 = ~ relay1;
    digitalWrite(r1, relay1);
    delay(500);
  }
}

`

Are you looking at the serial output when this happens? do you see the "Staff Access" message? and then is there any other indication of what its doing? I would add print statements in the two places you return, this way you will be able to monitor the state of the loop and/or see if it stops running and where the last place it printed from.

if the first card i present is a generic card, the serial monitor returns "authorized access" with each tap and keeps turning the light on and off.  If I then present staff card, the serial monitor returns "staff access" but the lights do nothing, and thereafter, if i tap the generic card again, the serial monitor returns "authorize access again, but the lights don't respond anymore.

This operation on an int needs some explanation: relay1 = ~ relay1;. Is there another way you could achieve your goal here?

Ya, relay1 should be a bool, and then use relay1=!relay1; to switch states.

relay1 = ~relay1 worked fine when i was just using one criteria for the cards (meaning everyone was authorized).  it was only when I added the criteria of "Staff access" that it stopped working.   Is there a particular reason why !relay1 would work better than ~relay1  ?

The C++ tilde  (~) operator is a bitwise NOT operator.  That is, it changes every 0 to a 1 and every 1 to a 0. It is almost never appropriate for use with signed numbers such as int where the high order bit is a sign bit. It is normally used for manipulating individual bits in a variable, not for logical operations.

Thank you, and advice taken, but do you think this the issue causing the loop appear not to work?  Like I said, it worked before, alternating the state from low to high, when any card would activate it.  Why would the code no longer trigger the lighting event now that there are two sets of access cards to evaluate?  I feel like there might be something wrong with the if statement, or how it ends.

The problem is the inappropriate use of the tilde (~) , which is a bitwise NOT operator, against the int variable relay1.
It appears to work correctly when relay1 starts with LOW which has the value 0. That is, relay1 has the internal value 0b0000000000000000.  If now the statement relay1 = ~relay1 is executed, relay1 has the internal value 0b1111111111111111. This is treated as a HIGH in the expression digitalWrite(r1, relay1); So it appears to work correctly.
If again the statement relay1 = ~relay1 is executed, relay1 has the internal value 0b0000000000000000 This is treated as a LOW in the expression digitalWrite(r1, relay1);
So that would also appear to work continuously, turning the relay on and off.
The problem comes when you explicitly set relay1 to HIGH here: relay1 = HIGH;. HIGH has the value 1, that is relay1 now has the intenal value 0b0000000000000001 and again that works, however, the next execution of the statement relay1 = ~relay1 gives relay1 the internal value
0b1111111111111110 which is also treated as HIGH. So, from now on, the statement relay1 = ~relay1 will always result in relay1 having a value which is interpreted as HIGH. So the relay appears to be stuck.
The solution, which already appears in a comment, is to change the statement int relay1 = LOW; to bool relay1 = LOW; and change this statement relay1 = ~ relay1; to relay1 = ! relay1;

Thank you SO much for explaining.  I didn't understand that there would be an internal value other than zero and one associated with LOW and HIGH, so couldn't really see how the solution of changing the relay statement would help.  That does sound like it will fix the problem and now I have another concept to look into and understand more :)

@Christine, the protocol is to tick the answer is correct.  :-)


text:
Cannot change fuses on ATmega32U4
I have a custom board based on Arduino Leonardo (ATmega32u4).
As usual I used the Arduino IDE to burn the bootloader with my Atmel ICE ISP programmer.
This time it failed complaining about some errors writing the fuse bits.
So I tried to manually set them with avrdude but it turns out it can't.
I first dumped out the current values:
avrdude: Device signature = 0x1e9587 (probably m32u4)
avrdude: safemode: lfuse reads as 5E
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as F3

avrdude> d lock
>>> d lock
0000  ff

Then I tried to change, say, lfuse to 0xFF:
avrdude "-C/home/mark/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf" -v -patmega32u4 -catmelice_isp -Pusb -Ulfuse:w:0xff:m

here the output:
avrdude: reading input file "0xff"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.09s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xff:
avrdude: load data lfuse data from input file 0xff:
avrdude: input file 0xff contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x5e != 0xff
avrdude: verification error; content mismatch

avrdude: safemode: lfuse reads as 5E
avrdude: safemode: hfuse reads as D8
avrdude: safemode: efuse reads as F3
avrdude: safemode: lfuse changed! Was ff, and is now 5e
Would you like this fuse to be changed back? [y/n] y

But it failed:
avrdude: safemode: Wrote lfuse to ff, read as 5e. 9 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 8 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 7 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 6 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 5 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 4 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 3 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 2 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 1 attempts left
avrdude: safemode: Wrote lfuse to ff, read as 5e. 0 attempts left
avrdude: and COULD NOT be changed
avrdude: safemode: Fuses not recovered, sorry

I can program the MCU with a firmware (using the ISP programmer) and it works, so it's not damaged. What can I do in order to fix this writing issue on the fuse bits?