text:
DS18B20 doesn't work reliably
like discribed in the title my temperature sensor goes to -127 after a few minutes of run time, it works again after a restart, I have already replaced the sensor and I'm using the same code for the temperature which I had used before which has been running flawlessly for almost 6 months now, I really have no clue what I did wrong hopefully someone got an idea.
Thank you!

There's not much information there to figure out what happened. Did changing the sensor fix the problem or did it continue with the new sensor? Providing a schematic of your sensor connection to the Arduino(?) would help. So would seeing a minimum sketch that still reproduces the problem. Both of those edited into your question, please.

Thank you for your reply but I just used a diferent library now.

decimal -127 is binary 11111111 ... reading all 1 bits is usually a wiring issue

Reading '0xFF' could be caused by poor grounding or insufficient power supply, incorrect pull-up resistor value or simply bad/fake chip. If the code you posted below as an "answer" is the code that you are  running, you are also causing the sensor self heat-up by constantly looping it. DS18B20 supposed to be read at once every second to avoid self heating.

There's a problem with using OneWire and Wire/I2C in one Sketch at once.
I believe this is because OneWire takes too long not sure, but this is probably why the temperature reading went to -127 after a while to fix thi.
I used an NTC 10K at 20°C. Below you can see code to make the NTC work and how to wire it!
Hope this helps!
Code:
#include <math.h>
const int thermistor_output = A1;

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

void loop() {
  int thermistor_adc_val;
  float output_voltage, thermistor_resistance, therm_res_ln, temperature;
  thermistor_adc_val = analogRead(thermistor_output);
  output_voltage = ( (thermistor_adc_val * 5.0) / 1023.0 );
  thermistor_resistance = ((5 * (10.0 / output_voltage)) - 10);
  thermistor_resistance = thermistor_resistance * 1000 ;
  therm_res_ln = log(thermistor_resistance);
  temperature = (1 / (0.001129148 + (0.000234125 * therm_res_ln) + (0.0000000876741 * therm_res_ln * therm_res_ln * therm_res_ln)));
  temperature = temperature - 273.15;
  Serial.print("Temperature in degree Celsius = ");
  Serial.print(temperature);
  Serial.print("\n");
  delay(1000);
}

Wiring:

Hi @Dennis, the point of this and the many other stack exchange web sites are to accumulate clear, concise and well-worded Questions and Answer to help others w/similar problems.  There is absolutely nothing wrong w/answering your own question. Consider editing your Title, Question & Answer to make it clear what was not working and how you fixed it.  Copy any important information from the comments and integrate them into the Question and Answer. Thanks.

Is this the solution to your own question, or is it meant as an addition. -- If the latter, you urgently need to take the [tour] to learn how this site works, it is not a forum. Then edit your question and add this content to it, then delete this non-answer.

-127 is the default code for an open wire.


text:
GPS speedometer with NEO 6M - latency issue
I have built a speedometer, based on this
youtube video: https://www.youtube.com/watch?v=gKuJxjxNP-k&t=34s
The speedometer is for a car, so it needs to be in real-time and accurate, with the actual speed that the car reads. The speedometer is built with a NEO-6m GPS module with an antenna. It is hooked up to an Arduino Nano and an OLED 0.96".
This is the code and wiring diagram. The code is the same as the video and uses TinyGps library. But simplified to just show me the current speed(kmh). I have removed every other line of code, to reduce latency.

#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);

#include <SoftwareSerial.h>
#define rxPin 2
#define txPin 3 //unused
SoftwareSerial neogps(rxPin,txPin);

#include <TinyGPS++.h> //1.0.3
TinyGPSPlus gps;
//---------------------------------------------------------------------------
int x_max    = 128;       //OLED display width, in pixels
int y_max    = 62;        //OLED display width, in pixels
int x_center = x_max/2;
int y_center = y_max/2+10;
int speed;
int adjspeed;// Adjusted speed for oversetimation by car
int num_sat;

//satellite logo
#define sat_logo_width 20
#define sat_logo_height 20

const unsigned char sat_logo[] = {
  0x00, 0x01, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x60, 0x30, 0x00,
  0x60, 0x78, 0x00, 0xc0, 0xfc, 0x00, 0x00, 0xfe, 0x01, 0x00, 0xff, 0x01,
  0x80, 0xff, 0x00, 0xc0, 0x7f, 0x06, 0xc0, 0x3f, 0x06, 0x80, 0x1f, 0x0c,
  0x80, 0x4f, 0x06, 0x19, 0xc6, 0x03, 0x1b, 0x80, 0x01, 0x73, 0x00, 0x00,
  0x66, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x70, 0x00, 0x00
};
//---------------------------------------------------------------------------

//Program variables
double lat;
double lng;

void gauge() {

  //TOP LEFT: draw satellite logo and number of satellites
  u8g.drawXBM(0, 0, sat_logo_width, sat_logo_height, sat_logo);
  u8g.setPrintPos(18, 5);
  u8g.print(num_sat, 5);

  //---------------------------------------------------------------------------
  // Show Speed and align its position
  u8g.setFont(u8g_font_profont22);
  u8g.setPrintPos(54,60);

  if (adjspeed>99) {
    u8g.setPrintPos(47,60);
  }

  u8g.print(adjspeed);
  //---------------------------------------------------------------------------
}

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

  neogps.begin(9600);

  u8g.setFont(u8g_font_chikita);
  u8g.setColorIndex(1);
}

void loop(void){

  Read_GPS();

  //Display Data on Oled
  {
    u8g.firstPage();
    do {
      gauge();
    }
    while( u8g.nextPage() );
  }

}

void Read_GPS(){

  boolean newData = false;

for (unsigned long start = millis(); millis() - start < 100;)
  {
    while (neogps.available())
    {
      if (gps.encode(neogps.read()))
      {
        newData = true;
        break;
      }
    }
  }

  //If newData is true
  if(newData == true){
    newData = false;
    Get_GPS();
  }
  else {
    //no data
  }
}

void Get_GPS(){
  num_sat = gps.satellites.value();

  if (gps.location.isValid() == 1) {
    speed = gps.speed.kmph();
    adjspeed = 1.03*speed; // the speed is adjusted(increaed) to match the speed that the actuall car outputs. (Because there is a law stating that cars need to overestimate the actual speed by a little bit
    Serial.print("Speed: ");
    Serial.println(adjspeed);

  }
}

The speedometer is accurate and shows the right speed, but there is a latency of around 1-2 seconds. For example, if the car starts accelerating from 0, the OLED shows the speed 1-2 seconds later, the same with when the car brakes. I need the latency to be, at least, less than a second.
I'm a bit of a beginner and not sure how to reduce this latency. I was hoping for someone here to explain to me how I can reduce this latency

what's the purpose of the for statement in Read_GPS()?

reduce your program to minimum code that reads raw GPS data and dumps it to serial port

Which NMEA messages do you expect? You seem to be trying to process all messages, but then abort on the first one you get.

By default, the Neo 6M (if it's a genuine U-blox) outputs 1 position update per second but it can be set to a maximum of 5 position updates per second (5 Hz) which will reduce the latency. If you decide to change the update frequency, you should also increase its baud rate. You can use U-Blox's u-center software to change these settings.

source: Stack Exchange

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

sort: votes


text:
SD Card Mount Failed with Waveshare ESP32 using Arduino IDE
I'm currently working on a project using an ESP32 (the Waveshare ESP32 Driver Board), and I am trying to read data from an SD card, but consistently getting a "SD Card Mount Failed" error. I am using the Adafruit SD card reader breakout board and the Arduino IDE.
Here's how I've wired the SD card reader to the ESP32
SD card     ESP32
-------     -----
3.3V        3.3V
GND         GND
CLK         pin 18 (SCK)
DO          pin 19 (MISO)
DI          pin 23 (MOSI)
CS          pin 5 (SS)

And here's the relevant code I'm using to setup and test the SD card:
#define SCK  18
#define MISO  19
#define MOSI  23
#define CS  5

int setup_sd_card() {

  SPIClass spi = SPIClass(VSPI);
  spi.begin(SCK, MISO, MOSI, CS);

  if (!SD.begin(CS,spi,80000000)) {
    Serial.println("ERROR: SD Card Mount Failed");
    return -1;
  }
  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE){
    Serial.println("ERROR: No SD card attached");
    return -1;
  }

  // Code to print out SD card details...

  return 1;
}

I've triple-checked my wiring but the code always fails at if (!SD.begin(CS,spi,80000000)). I've tried 3 different SD cards of different sizes, all formatted to FAT32 (64GB, 256GB, 1024GB)
Could the issue be related to the ESP32 not being a stock one because it has some hardware for driving an e-paper screen? Here is the schematic: https://www.waveshare.com/w/upload/8/80/E-Paper_ESP32_Driver_Board_Schematic.pdf

Can anyone suggest what might be the issue or what else I could try to debug this problem? Any help would be greatly appreciated.

The Waveshare esp32 appears to use the following SPI pins for the screen. P13:  spi clk; P14:  spi mosi; P15:  cs (not  shared). For clk, miso and mosi you should use the same pins. Try printing out the existing values of clk, miso and mosi without (re-) defining them. Only the cs pin is unique to the peripheral. The remaining SPI pins are a shared bus.

I moved the SPIClass declaration to a global variable and changed the frequency down to 4 from 80 but I'm getting the same result. Thanks for the suggestion.

I also printed out the existing values of MOSI/MISO/SCK/SS after deleting my redefinition of them and they are:
MOSI: 23
MISO: 19
SCK: 18
SS: 5
; I can try using the same SPI pins the screen uses and see if that works. I'll update this when I know.

There are at least two problems with your code.
First I think you have a typo in the frequency. Default frequency is 4 MHz, but your parameter in begin is 80 MHz, which I doubt will work.
You initialize the spi object on the stack in the function and then supply it to the SD instance. The spi object on stack will be removed when the function ends and the SD object will crash. It has to be an allocation on heap as SPIClass* spi = new SPIClass(VSPI); or a global variable SPIClass spi(VSPI);.
And since you use the default pins of VSPI you can use just spi.begin() without the pin numbers.

The issue turned out to be a faulty SD card.
I had tried other SD cards but must have used incorrect wiring for them.
EDIT: Here is the updated code:
#define CS        5
#define SCK       18
#define MOSI      23
#define MISO      19

SPIClass spi(VSPI);

int setup_sd_card() {
  spi.begin(SCK, MISO, MOSI, CS);

  if (!SD.begin(CS,spi,4000000)) {
    Serial.println("ERROR: SD Card Mount Failed");
    delay(1000);
    return -1;
  }
  Serial.println("Finished initializing SD card. Getting card type...");

  uint8_t cardType = SD.cardType();

  if(cardType == CARD_NONE){
    Serial.println("ERROR: No SD card attached");
    delay(1000);
    return -1;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC){
    Serial.println("MMC");
  } else if(cardType == CARD_SD){
    Serial.println("SDSC");
  } else if(cardType == CARD_SDHC){
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }
  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));

  Serial.println("SUCCESS! (SD CARD)");

  return 1;
}

does it work with the code as it is in the Question?

I just edited my answer to add the code that works. It's the same as above with the two suggestions given in the comments.

so it doesn't begin at 80 mega? what about 8 mega?

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


text:
`time()` doesn't reset to 0 when calling `ESP.restart();` on ESP32?
I'm using an ESP32 and it's fine, I have no issues at all.
I was just curious that after flashing a new firmware via OTA, like this:
#include <ESPAsyncWebSrv.h>
#include <Update.h>

void http_page_flash(AsyncWebServerRequest* request) {
    if (!check_auth(request)) {
        return request->requestAuthentication();
    }

    request->send_P(200, "text/html", flash_html, http_page_flash_processor);
}

void http_api_flash(AsyncWebServerRequest* request) {
    if (!check_auth(request)) {
        return request->requestAuthentication();
    }

    ESP.restart();
}

void http_api_flash_part(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final) {
    if (!check_auth(request)) {
        return request->requestAuthentication();
    }

    if (index == 0) {
        if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
            Update.printError(Serial);
            request->redirect("/flash?status=error&message=" + String(Update.errorString()));
        }
    }

    if (len) {
        if (Update.write(data, len) != len) {
            Update.printError(Serial);
            request->redirect("/flash?status=error&message=" + String(Update.errorString()));
        }
    }

    if (final) {
        if (Update.end(true)) { //true to set the size to the current progress
            request->redirect("/flash?status=success");
        }
        else {
            Update.printError(Serial);
            request->redirect("/flash?status=error&message=" + String(Update.errorString()));
        }
    }
}

time() result doesn't seem to re-set to 0.
When accessing newly submitted entries which are time-based, they are timestamped as if the board never reset to 0, but all my entries are reset to 0 (so the memory is being reset):
void device_data::push(int co2_ppm, float rh, float temp_c, int sensor_status, unsigned long sequence_number) {
    unsigned long now = (unsigned long)time(NULL);

    current_ventilation_state_co2 = determine_current_ventilation_state(current_ventilation_state_co2, co2_ppm, global_config_data.co2_ppm_low, global_config_data.co2_ppm_medium, global_config_data.co2_ppm_high);
    current_ventilation_state_rh = determine_current_ventilation_state(current_ventilation_state_rh, rh, global_config_data.rh_low, global_config_data.rh_medium, global_config_data.rh_high);

    latest_measurement.relative_time = now;
    latest_measurement.set_co2(co2_ppm);
    latest_measurement.set_rh(rh);
    latest_measurement.set_temp(temp_c);
    latest_measurement.sensor_status = sensor_status;
    latest_measurement.sequence_number = sequence_number;
    latest_measurement.state_at_this_time = get_highest_ventilation_state(current_ventilation_state_co2, current_ventilation_state_rh);

    very_short_data.pushOverwrite(latest_measurement);
    // ...
}

The data is completely reset as the ring buffer is back to being size=0, but now is not close to 0, it's just increased as if it completely survived the ESP.restart() call.
I'm just curious, is this by design? Is this a bug?
Is time() somehow saved to flash? Or to some special restart-persistent memory?
I use the flash to store my configuration, but I never store or restore the time in any of my configuration.
If it's some special static ram which is not flash storage, can I also access this for my own purposes?

esp32 has RTC peripheral


text:
Microcontroller freezes when triggering the gate of an N-channel MOSFET
Disclaimer: I have asked questions about this project before but this is yet another issue I'm facing.
What I really want to do: Build a battery powered device with 6 colored buttons. When you press one of the buttons the gadget should play a sound saying the name of the color.
It should not need an ON/OFF toggle to save battery capacity but rather have a very low idle current draw so that the battery will lasts for weeks (or even months) when it's not used.
Something like this

Hardware: ATtiny85 (low draw in general, very low draw in sleep), DfPlayer, 3.7v Battery (probably 18650)
The 6 buttons are attached to a single input pin. The microcontroller can distinguish them by reading the ADC value. The buttons have different resistors attached to them
How I wanted to do it: My initial plan was to press a button that wakes the microcontroller up. The mcu then wakes the dfplayer, plays a sound and goes back to sleep. If that would not be responsive enough add a delay to the sleep like: if no button was pressed within the last 30s go to sleep. That worked after some initial problems but it turned out that the DfPlayer "sleep mode" doesn't mean it goes to sleep as in it draws less current but much rather that it's just idling, not playing any sound.
How I want to do it now: Pretty much the same as above but instead of sending the DfPlayer to sleep just turn it on and off:
Press a button that wakes the microcontroller up. The mcu then turns the DfPlayer on by setting the gate of an n-channel mosfet (IRF3708) HIGH, waits a short period of time, plays a sound, turns the dfplayer off and goes back to sleep. If that's not responsive enough add a sleep delay like explained above.
What I'm already able to do:

make the DfPlayer play a specific sound over serial communication
distinguish between the 6 input buttons
wake the microcontroller up with any of these buttons
turn the DfPlayer on/off by using an n-channel mosfet

The problem that I have: The microcontroller freezes when I set the output pin attached to the mosfet gate to HIGH. Freeze means it just won't execute any code after the digitalWrite(PIN_MOS, HIGH); call. I tested it by turning an LED on a different pin on and off like so
digitalWrite(PIN_LED, HIGH);
digitalWrite(PIN_MOS, HIGH);
digitalWrite(PIN_LED, LOW);

The LED turns on but won't ever turn off. When I use the external reset of the attiny the mosfet will turn off and code will execute again just fine. Until I try to set the mosfet pin to HIGH again.
The DfPlayer will turn on though, I can play sounds on it by shorting 2 pins on it. It doesn't seem to be unstable either. It's just that the attiny hangs up.
I use a cheap lab psu but it should be good enough to be not the problem. I've also tried a fully charged 18650 battery and a CR2032 battery. The 18650 worked the same as the psu and the CR2032 just couldn't handle the draw and the DfPlayer wouldn't properly turn on.
I tried it different voltages between 3.3v and 5v. In theory everything should work and in reality it didn't change anything either.
Here is the breadboard layout I use.
I also added an electrolytic and ceramic cap between Vcc/GND on the DfPlayer but that didn't help either

Here is the code I use
    #include <Arduino.h>
    #include <avr/sleep.h>
    #include <DFMiniMp3.h>
    #include <avr/interrupt.h>
    #include <avr/power.h>
    #include "LemonSerial.h"
    #include "mp3notify.h"

    #define PIN_TX PB0
    #define PIN_RX PB1
    #define PIN_MOS PB2
    #define PIN_LED PB3
    #define PIN_A PB4

    LemonSerial secondarySerial(PIN_RX, PIN_TX);
    DfMp3 dfmp3(secondarySerial);

    void sleep();

    void initADC()
    {
      ADMUX =
          (1 << ADLAR) | // left shift result
          (0 << REFS1) | // Sets ref. voltage to VCC, bit 1
          (0 << REFS0) | // Sets ref. voltage to VCC, bit 0
          (0 << MUX3) |  // use ADC2 for input (PB4), MUX bit 3
          (0 << MUX2) |  // use ADC2 for input (PB4), MUX bit 2
          (1 << MUX1) |  // use ADC2 for input (PB4), MUX bit 1
          (0 << MUX0);   // use ADC2 for input (PB4), MUX bit 0

      ADCSRA =
          (1 << ADEN) |  // Enable ADC
          (1 << ADPS2) | // set prescaler to 128, bit 2
          (1 << ADPS1) | // set prescaler to 128, bit 1
          (1 << ADPS0);  // set prescaler to 128, bit 0
    }

    void setup()
    {
      initADC();

      pinMode(PB5, INPUT_PULLUP);
      pinMode(PIN_A, INPUT);
      pinMode(PIN_LED, OUTPUT);
      digitalWrite(PIN_LED, LOW);
      pinMode(PIN_MOS, OUTPUT);
      digitalWrite(PIN_MOS, LOW);
    }

    void play(uint16_t track)
    {
      if (digitalRead(PIN_MOS) == LOW)
      {
        digitalWrite(PIN_LED, HIGH);
        delay(500);
        digitalWrite(PIN_MOS, HIGH);
        digitalWrite(PIN_LED, LOW);

        delay(500); // wait for DfPlayer to turn on

        dfmp3.begin();
        dfmp3.reset();
        dfmp3.disableDac();
        dfmp3.setVolume(30);
        dfmp3.setPlaybackSource(DfMp3_PlaySource_Sd);
      }

      dfmp3.playGlobalTrack(track);
    }

    void loop()
    {
      ADCSRA |= (1 << ADSC); // start ADC measurement
      while (ADCSRA & (1 << ADSC))
      {
          // wait till conversion complete
      }

      uint8_t adcValue = ADCH;
      // actually calculate the parameter based off adcValue here. omitted for readability
      play(1);
    }

    // Interrupt Serviceroutine (Pin-Change-Interrupt)
    ISR(PCINT0_vect)
    {
      LemonSerial::handle_interrupt();
    }

    // ADC interrupt service routine
    ISR(ADC_vect)
    {
      ; // noop
    }

Got a link to the datasheet of the MOSFET you are using?

@VE7JRO it’s an IRF3708. I’ve attached a link to my post

You should also have a decoupling capacitor (ceramic say 100nF) directly across the power rails of the ATtiny85 and as physically close as possible to the chip. It is possible that the inrush current to the smoothing capacitor on the SD card player when the mosfet switches on is causing the problem. You may try a 100nf capacitor directly between the mosfet gate and ground and a 10k to 100k resistor between the arduino pin and the gate to slow this switch on. Also search for "attiny85 brown out fuse" . This may be dependent on options provided by the arduino core you are using.

while (ADCSRA & (1 << ADSC)) {   sleepIfIdle(started) ; }.  I think it is going to hang in this loop continuously sleeping because the variable started is not refreshed. Try making started global and update it also at the end of your sleep code. If this is the problem then create an answer yourself showing the coding changes.

Please reduce your sketch to the absolute minimum that stills shows the behavior. Then [edit] your question and add that code, please.

"I update started at the beginning of the loop. shouldn't that work?" No. The started at the beginning of the loop will not be executed when it gets stuck in that inner loop. After waking from sleep, the flow of control returns back up the call chain sleep() -> sleepIfIdle() into that inner loop without touching started. However, it sounds like it is not the problem. Which Arduino core are you using? Please add that to the problem description.

You've made a whole lot of changes to the code, see edits. Does it still exhibit the same behaviour? The comments above now seem to refer to code that has been removed.

You've said you are using the Attiny85 for lower power drain. The Atmega328P has a lot more ports and still only draws 100 nA in sleep mode "power down" and can still be woken from a switch closure. That would mean a lot less resistors you have to fit into that enclosure.

@NickGammon fair point I guess but the 85 is a lot smaller than the 328p. Length is worse than quantity. My ultimate goal is to make a pcb with smd components out of it anyway. The dfplayer might be an issue though since it's rather big

@6v6gt you were right. the resistor between PB4 and Gate + the ceramic capacitor between GND and Gate made it work eventually.
Your comments about the sleep function were right and I was able to fix that too.

That's great. I leave you to present your revised code and component layout as an answer to close this. It may helps some one else and you should also get a few Brownie points.

@Rohit Gupta - You can do syntax colouring with <!-- language: lang-c++ --> as a comment (not indented) just before the code. That saves you changing the indentation and having to add the backticks before and after it. Now it is over-indented.

@boop The difference in size is only a couple of mm for the SMD devices, but whatever works for you. Glad you got it working!

@6v6gt was the one who figured out what was missing.
I had to increase the 1Ω resistor between the output pin and gate to 1kΩ and add a 100nF ceramic capacitor between GND and gate. Eventually it worked just as expected.
This is the full code I ended up using. I tried to add enough comments to make it clear what happens.
#include <Arduino.h>
#include <avr/sleep.h>
#include <DFMiniMp3.h>
#include <avr/interrupt.h>
#include <avr/power.h>
// this is just "SoftwareSerial" without blocking interrupts
// thus you have to call handle_interrupt() from here
#include "LemonSerial.h"
#include "mp3notify.h"

#define PIN_TX PB0
#define PIN_RX PB1
#define PIN_MOS PB2
#define PIN_LED PB3
#define PIN_A PB4
// turning the player on and initializing it takes quite a while
// thus do not go back to sleep immediately after each button press
uint32_t timeoutMs = 30000;
uint64_t started = 0;

// dfplayer api
LemonSerial secondarySerial(PIN_RX, PIN_TX);
DfMp3 dfmp3(secondarySerial);

void sleep();

uint8_t readADC()
{
  ADCSRA |= (1 << ADSC); // start ADC measurement
  while (ADCSRA & (1 << ADSC))
    ; // wait till conversion complete

  uint8_t adcValue = ADCH;
}

void initADC()
{
  ADMUX =
      (1 << ADLAR) | // left shift result
      (0 << REFS1) | // Sets ref. voltage to VCC, bit 1
      (0 << REFS0) | // Sets ref. voltage to VCC, bit 0
      (0 << MUX3) |  // use ADC2 for input (PB4), MUX bit 3
      (0 << MUX2) |  // use ADC2 for input (PB4), MUX bit 2
      (1 << MUX1) |  // use ADC2 for input (PB4), MUX bit 1
      (0 << MUX0);   // use ADC2 for input (PB4), MUX bit 0

  ADCSRA =
      (1 << ADEN) |  // Enable ADC
      (1 << ADPS2) | // set prescaler to 128, bit 2
      (1 << ADPS1) | // set prescaler to 128, bit 1
      (1 << ADPS0);  // set prescaler to 128, bit 0
}

void setup()
{
  initADC();

  // set INPUT_PULLUP to reduce current draw
  pinMode(PB5, INPUT_PULLUP); // PB5 is not assigned to any constant
  pinMode(PIN_LED, INPUT_PULLUP);

  pinMode(PIN_A, INPUT); // ADC pin is physically pulled low
  pinMode(PIN_MOS, OUTPUT);
  digitalWrite(PIN_MOS, LOW);

  started = millis();
}

/// @brief plays a track on the dfplayer. turns the player on if neccessary
/// @param track track number to play
void playTrack(uint16_t track)
{
  started = millis();

  if (digitalRead(PIN_MOS) == LOW)
  {
    digitalWrite(PIN_MOS, HIGH);
    delay(50); // wait 50ms for DfPlayer to turn on

    // baud 4800 because the attiny runs at 16mhz (8mhz -> 9600)
    dfmp3.begin(4800);
    dfmp3.setVolume(30);
  }

  dfmp3.playGlobalTrack(track);
}

void loop()
{
  uint8_t adcValue = readADC();

  if (adcValue >= 227 && adcValue <= 237)
  {
    // 10k ohm (3.0V -> adc 232)
    playTrack(1);
  }
  else if (adcValue >= 212 && adcValue <= 223)
  {
    // 18k ohm (2.8V -> adc 217)
    playTrack(2);
  }
  else if (adcValue >= 196 && adcValue <= 206)
  {
    // 27k ohm (2.6V -> adc 201)
    playTrack(3);
  }
  else if (adcValue >= 181 && adcValue <= 191)
  {
    // 38k ohm (2.4V -> adc 186)
    playTrack(4);
  }
  else if (adcValue >= 165 && adcValue <= 175)
  {
    // 50k ohm (2.2V -> adc 170)
    playTrack(5);
  }
  else if (adcValue >= 150 && adcValue <= 160)
  {
    // 65k ohm (2.0V -> adc 155)
    playTrack(6);
  }
  // ending up here every loop where no button was pressed. so basically 99.99% of the time
  else
  {
    // started gets set to millis() everytime a track is played
    if (millis() - started > timeoutMs)
    {
      // sleep if some time has passed without input (see timeoutMs)
      sleep();
    }
  }
}

// sets the device into POWER DOWN mode.you can probably tune it to be more efficient
void sleep()
{
  digitalWrite(PIN_MOS, LOW);

  // pin change interrupt
  PCMSK |= bit(PIN_A);
  GIFR |= bit(PCIF);  // clear any outstanding interrupts
  GIMSK |= bit(PCIE); // enable pin change interrupts

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  power_all_disable(); // power off ADC, Timer 0 and 1, serial interface
  sleep_enable();
  sleep_cpu();
  sleep_disable();
  power_all_enable(); // power everything back on
}

// Interrupt Serviceroutine (Pin-Change-Interrupt)
ISR(PCINT0_vect)
{
  // the SoftwareSerial does not block any interrupt pins anymore and thats why we have to call it from here
  LemonSerial::handle_interrupt();
}

// ADC interrupt service routine
ISR(ADC_vect)
{
  ; // noop
}

This is a schematic from how everything is set up now. This is the first time I drew a real schematic so I hope it's clear whats going on

The RC network consisting of a 100nF capacitor and a 1k ohm in the gate circuit of the mosfet has a time constant of 100ns. It seems that this is enough to "soften" the switch on of the mini DF player. However, I believe that the extra capacitors you've added (100uF and 100nF) currently between the Vcc and (switched) GND of the player should actually be between Vcc of the player and the main GND otherwise these  also have an inrush current when the mosfet is switched on. Why, incidentally, do you consider especially the 100uF capacitor to be necessary ?

@6v6gt good point. It was just something I found while googling around. Maybe I misunderstood it though. It works without these caps but my understanding was that it helps stabilizing the player. Stabilizing as in: less unwanted noise/crackling

I don't necessarily disagree with the capacitor, more how you have wired it. Have you measured the current when the device is sleeping ? It is more usual to switch modules, in this case the DFplayer, on the high side, that is at their Vcc rather than their Gnd and using an P channel mosfet. The risk of some sort of parasitic powering is higher if the ground side is switched because it is more likely to find an alternative path to ground resulting in some residual current consumption by the module. If the current consumption is small of course you can choose to ignore it.


text:
Arduino MKRZero "This device cannot start" (Code 10), and Keyboard.h
I have bought my brand new Arduino MKRZero to emulate a keyboard. When I plug it in, I get the following on COM6, which is listed as "Arduino MKRZero".
"This device cannot start" (Code 10)

I also get a new COM port connection, COM3, listed as a generic USB Serial Device.

In my IDE (2.1.0) I am given the following:

COM 3 opens on the Serial Monitor, while COM 6 gives a port monitor error:

Attempts
I have tried a few things based on the following:
https://forum.arduino.cc/t/solved-arduino-uno-this-device-cannot-start-code-10-at-hardware-manager/298777
https://forum.arduino.cc/t/this-device-cannot-start-code-10-arduino-leonardo/897137
https://www.lifewire.com/how-to-fix-code-10-errors-2623181

Updating drivers
Rolling back drivers
Using a different USB connector
Restarting laptop

Context
The reason why I ask is because I am attempting to use the following code in an Arduino, which, per my understanding, should print the letter "F" every second with my keyboard.
#include <Keyboard.h>

void setup() {
  // open the serial port:
  Serial.begin(9600);
  // initialize control over the keyboard:
  Keyboard.begin();
}

void loop() {
    Keyboard.write('F');
    delay(1000);
}

However, no response is received.
Please let me know if more information is required, or if this is a code issue. I am on Win 10.0.19045, and attempted both the latest version and an alleged, more stable version of the MKRZero driver (Arduino SAMD Boards [32-bits ARM Cortex-M0+] version 1.8.13 and 1.8.9).

if you upload Blink or some other sketch without Keyboard library, everything is normal? one com port? which one?


text:
Unable to control motor with ESP32 using logic level shifter
I am using an ESP32 a TB6600 micro stepper, and a Nema 23 stepper motor, I am trying to control the motor with the esp32 but the TB6600 requires a 5v signal, I tried to fix this by using a logic level converter (specifically this) but when I attempt to control the motor I get a very slight hum out of the motor and no movement.
The motor controller and motor both work as I tested it with an Arduino Uno.
void setup() {
  pinMode(15, OUTPUT);
  pinMode(16, OUTPUT);
  pinMode(17, OUTPUT);
  digitalWrite(16, HIGH);
}

void loop() {

  digitalWrite(15,LOW);
  digitalWrite(15,HIGH);
  digitalWrite(17, HIGH);
   delay(200);
}

Picture of Circuit

Circuit Diagram

The inputs ENA, DIR and PUL appear to be leds of optocouplers based on this: https://www.dfrobot.com/product-1547.html . I guess that you don't need that logic level shifter which is anyway intended only for very low currents. It is strange, however, that 5v is specified. The wiring in the link I have supplied implies that LOW is on and HIGH is off. Ensure that any example code you are using matches your wiring.

How much current the TB6600 needs on its inputs? Bidirectional level shifters can't provide much current on the high side as they are basically shorting LOW through the mosfets (HIGH is pulled up by few kiloohms resistors to HV)

When you plug in your circuit, do you notice your motor getting hot? Also, why are you setting your pin 17 to high in your loop?

It doesn't look like the motor controller shares a ground with your ESP32.  Try connecting the grounds together and see if it helps.

I figured out the problem, the logic level switcher I was using is meant for I2C  sensors, and thus was only capable of converting open-drain signals and cannot perform push/pull level translation meaning it was not able to provide a data signal to the micro stepper. I replaced the shifter with a shifter capable of push/pull translation specifically This

I haven't used this kind of system, so I'm just guessing. But in the Manual it says:

When“EN”is in the valid state, the motor is in a free states (Off-line
mode). In this mode, you can adjust the motor shaft position manually. When“EN”is
in the invalid state, the motor will be in an automatic control mode.
(Source).

It is not entirely clear what they mean by "manually". But you set pin 17 to HIGH and the result would fit the description. Maybe set 17 to LOW?
On another note: there is no delay/time between digitalWrite(15,LOW); and digitalWrite(15,HIGH);. This will create a very short pulse, which might be too short for the level shifting electronics to translate. Some delay() or equivalent non-blocking code between the two writes could help.

In this context, "manual" means physically manipulating the shaft rather than doing it through the motor controller.   When steppers are disconnected, they can free spin.  When they are powered with a constant signal or shorted, they will hold position and resist external forces that would otherwise cause them to free spin.


text:
I have a cash counter with RS232 in the back of it, I want to read the data that supposed displayed on the projector
I have cash counter with RS232 in the back of it. I want to read the data that supposed displayed on the projector with RS232 to TTL convertor and arduino.
Here is all my setup

Now I

Connect the MAX3232 TX pin to the RX Arduino pin
and Connect the MAX3232 RX pin to the TX Arduino pin
and the Vcc to 5V
and MAX3232  GND to arduino  GND
and plug the MAX3232  to the cash counter and the arduino to the pc
and flash

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

void loop() {
  int data = Serial.read();
  if (data != -1) {
    Serial.println(data);
  }
}

And the output comes like this
50
56
48
67
49
52
48
8
10
106
13
51
56
56
76
147
48
51
12
13
83
106
51
1
13
64
10
1
49
254
254
254
254
252
254
255

How can I read the data from this device?

you have to determine what data is actually sent by the counter ... until you have that information available, the question is not about arduino

Use Serial.write() instead of Serial.println(). Printing interprets the data as a number (integer) into the ASCII representation, while writing sends the data unchanged. If the device sends ASCII encoded data you then will be able to read it in the serial monitor

Posting the make, model will help all of us. Also what does the instruction manual tell you?

From the labels in the pictures supplied by the OP and a some minutes with Google it appears to be a Proware Mix Value Counter STS 6000-T https://www.facebook.com/ProWare-117664076286992/videos/currency-counter-machine/760314631226329/. Some technical reference from the manufacturer would help but the interface may be proprietary and not published. It will be used at least for uploading profiles of new bank notes. Some similar machines allow you also to download the bank note details like serial numbers etc.

thank u i send message to them i hope the can help me with any info about this problem  @6v6gt

there is no information about the model till now i dont have any useful info to share :( @Gil


text:
How to make 2 lidar lite v3 work with 1 Arduino?
I'm using the code below, but I had no success.
I'm using this connection wire:
The photo of the Arduino doesn't show the SCL and SDA pins, but please consider that it has 2 SCL pins and 2 SDA pins in the places where I marked them in the image.
Both sensors are working, however they are mirroring each other's measurements.
That link is from the datasheet:
https://static.garmin.com/pumac/LIDAR_Lite_v3_Operation_Manual_and_Technical_Specifications.pdf

#include <Wire.h>
#include <LIDARLite.h>

#define LIDAR1_ADDRESS 0x62 // Endereço I2C do LIDAR Lite 1
#define LIDAR2_ADDRESS 0x63 // Endereço I2C do LIDAR Lite 2

LIDARLite lidar1; // Objeto para o LIDAR Lite 1
LIDARLite lidar2; // Objeto para o LIDAR Lite 2

void setup() {
  Wire.begin();        // Inicializa a biblioteca Wire (I2C)
  Serial.begin(115200);  // Inicializa a comunicação serial

  // Inicializa os objetos dos LIDARs
  lidar1.begin(LIDAR1_ADDRESS); // Inicialização do LIDAR Lite 1
  lidar2.begin(LIDAR2_ADDRESS); // Inicialização do LIDAR Lite 2
}

void loop() {
  int distance1 = lidar1.distance();
  int distance2 = lidar2.distance();

  // Exibe as medições dos LIDARs no Monitor Serial
  Serial.print("LIDAR 1: ");
  Serial.print(distance1);
  Serial.print(" cm | LIDAR 2: ");
  Serial.print(distance2);
  Serial.println(" cm");

  delay(500); // Intervalo entre as leituras
}

what does mirroring each other's measurements mean?

you connected one to I2C bus and the other to the SPI bus ... why don't you connect both sensors to the same bus?

had no success doesn't tell us much. What is actually happening? What is appearing in the serial monitor?

I agree with @jsotola - if these are I2C devices, why connect one to the SPI port? I2C devices can be connected in parallel.

@jsotola, I'm so sorry, I wasnt really clear. Let me try again, both sensors seem to be measuring , but when I place an obstacle in front of either of then, both show the same reading on the serial monitor.

@NickGammon both sensors seem to be measuring , but when I place an obstacle in front of either of then, both show the same reading on the serial monitor, and i need that both display individual readings.

@jsotola sorry, that arduino in the image is not the same as mine. My arduino has two scl a sda pins. Where you are seeing the ISCP pins actually has a scl and sda pins

I put these twoaddress but im not sure if they are rigth. how can i get theses address?

I put the wire example to get the address, but the serial monitor only show me the "device found at address 0x62 "

Is the address of both Lidar Modules configurable and did you configure them on the boards (hardware)? If not it is possible that both listen and react to both of the addresses simultanously and then I2C transports the superposition of the bits from both devices to the arduino which then gets the same (possibly wrong) values independent of which device it tries to connect to.

@PeterPaulKiefer no, I didn't any configuration on the hardware, I just wire like the image and put the code.

What type of lidar device do you use (I mean the board not only the chip/sensor)? Do you have a link to its documentation? How did you know which addresses are appropriate? Have you a link to the docs of the used Arduino Library (LIDARlite). If you read the docs you might find the answers yourself. If not, show us the links; I mean add them to your question and you increase the chance, that someone invests more time and may help you.

@GUSTAVOTELES You haven't answered my question. You say "both sensors seem to be measuring", on your diagram you show one connected to the SPI port. This won't work. If the diagram is completely wrong, fix it or remove it. You are using I2C addresses 0x62 and 0x63. If you haven't configured the hardware they will both be responding to 0x62, which would account for the same readings. There appears to be an option to change the address, according to the datasheet. The I2C address can be changed from its default value. Have you done that?

My arduino has two scl a sda pins. - Don't post a photo which shows something completely different from reality. That just confuses everyone. Either photograph your own setup with your phone and upload it, or just sketch a circuit diagram.

@NickGammon You are sure I just changed the diagram for the real that I'm using, actually I didn't understand how to configure the hardware.

@PeterPaulKiefer I just added the link of documentation, On page 5 of the datasheet has the instruction to change, but didn't understand properly how do that.

Maybe my page didn't refresh, I see it now.

Run the I2C scanner described here - if that only shows one device, then naturally it will only give one reading. If not, please amend your question to show what the results are.

@NickGammon I used aTCA9548A multiplexer and I solved the addressing problem.

@NickGammon I appreciate  a lot your support, thank you.

Please make your own answer to this question and describe how you solved it, so as to help future people with the same problem. Thank you!

If these are the Garmin Lidar Lite V3, here is a link to their data sheet. On page 5 of the datasheet you'll find instructions for configuring their I2C addresses. If you haven't already done that, it's quite likely that both devices are replying at once to the same query.
If you have done that already, please update your question with that and any other relevant data - such as the manufacturer, if I got that wrong, add any configuration changes you've made.


text:
Uploading code to ESP32 using Arduino OTA
im trying to upload my code to my esp32 through OTA iam able to discover the network port but my code is always failing to upload i donno the reason behind it
#include <WiFi.h>
#include <ArduinoOTA.h>

const char* ssid = "Redmi";
const char* password = "12345678s";
const char* OTA_password = "1234"; // set your own OTA password

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

  // Connect to Wi-Fi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  // Print IP address
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  // Start OTA update server with authentication
  ArduinoOTA.setHostname("my-esp32");
  ArduinoOTA.setPassword(OTA_password); // set OTA password
  ArduinoOTA.onStart([]() {
    // Disable other tasks that may interfere with OTA update
    Serial.println("OTA update started");
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nOTA update finished");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("OTA update progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("OTA update error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("OTA authentication failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("OTA begin failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("OTA connect failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("OTA receive failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("OTA end failed");
    }
  });
  ArduinoOTA.begin();
}

void loop() {
  ArduinoOTA.handle();
  // Your other code here
}

above is the code i uploaded to create OTA server
#include <WiFi.h>
#include <ArduinoOTA.h>

const char* ssid = "Redmi";
const char* password = "12345678s";

#define LEDPIN 4

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

  // Connect to Wi-Fi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print(".");
  }
  Serial.println("");

  // Start OTA update server
  ArduinoOTA.begin();
  Serial.println("OTA server started");

  // Initialize LED pin as output
  pinMode(LEDPIN, OUTPUT);
}

void loop() {
  ArduinoOTA.handle();

  // Blink LED every second
  digitalWrite(LEDPIN, HIGH);
  delay(1000);
  digitalWrite(LEDPIN, LOW);
  delay(1000);
}

and im trying to upload above blink program through OTA

and above is the error im getting it getting stucked and i have to restart the software everytime to test it. I appreciate if anybody care to explain and help me


text:
Read binary file on SD card
Why I can't read the last byte in the file when I use the Arduino ide code?
The code in cpp is work without any mistakes.
This is my code on Arduino ide:
  vector<unsigned char> text;
  unsigned char textseg;
  in_file.read(&textseg,1);
  while (in_file.available()){
      text.push_back(textseg);
      in_file.read(&textseg,1);
  }

And this is cpp code:
vector<unsigned char> text;
unsigned char textseg;
in_file.read(reinterpret_cast<char*>(&textseg), 1);
while (!in_file.eof())
{   text.push_back(textseg);
    in_file.read(reinterpret_cast<char*>(&textseg), 1);
}

I would guess, the difference is caused by a differrent declaration of in_file. But, as you do not show us the declaration, it is just a guess. It is also caused by the fact, that you read the last line but do not write it the the text vector because the wihle loop ist not enter, when the last character is read. I have no explanation, why this does not happen in the second case. Perhaps because the eof is only triggered when the read method reads from an empty stream and available knows that the stream is empty without reading from it again.

because you read it but you don't write it. you have a read before the while loop but no write after the while loop. available() returns the count of bytes available to read  eof() is true when you try to read more than the length of the file

Are you aware that feof() returns true only after you tried to read past the end of the file?

Your loop seems to be out-by-one. I would prefer:
  vector<unsigned char> text;
  unsigned char textseg;
  while (in_file.available()){
      in_file.read(&textseg,1);
      text.push_back(textseg);
  }

Why read a byte, as you did, before you know if it is available?
In the Standard C++ library, eof() is true if a read fails, however in the Arduino available() means a byte is available to be read. They are not directly swappable.


text:
communicating esp 32 with arduino uno
I made a spider robot using arduino and from esp. I made an audio output device which is linked to python program which writes a particular data (when we speak a command) to esp board and accordingly the voice would be activated. Now I want to link them together.
If the esp32 sends a particular data the function in arduino is executed.  Therefore I want to connect esp32 to arduino uno though Serial monitor and send data from esp 32 to arduino. I have only analog pins vacant as all digital pins are used for the servos. how can I achieve this?.
In the main arduino file there are 2 more flexitimer and flexitimer2.cpp files but there is no need of editing them and hence I am giving the code of main file.
    #include <Servo.h>    //to define and control servos
    #include "FlexiTimer2.h"//to set a timer to manage all servos
    /* Servos --------------------------------------------------------------------*/
    //define 12 servos for 4 legs
    char data = 0;
    Servo servo[4][3];
    //define servos' ports
    const int servo_pin[4][3] = { {2, 3, 4}, {5, 6, 7}, {8, 9, 10}, {11, 12, 13} };
    /* Size of the robot ---------------------------------------------------------*/
    const float length_a = 55;
    const float length_b = 77.5;
    const float length_c = 27.5;
    const float length_side = 71;
    const float z_absolute = -28;
    /* Constants for movement ----------------------------------------------------*/
    const float z_default = -50, z_up = -30, z_boot = z_absolute;
    const float x_default = 62, x_offset = 0;
    const float y_start = 0, y_step = 40;
    const float y_default = x_default;
    /* variables for movement ----------------------------------------------------*/
    volatile float site_now[4][3];    //real-time coordinates of the end of each leg
    volatile float site_expect[4][3]; //expected coordinates of the end of each leg
    float temp_speed[4][3];   //each axis' speed, needs to be recalculated before each movement
    float move_speed;     //movement speed
    float speed_multiple = 1; //movement speed multiple
    const float spot_turn_speed = 4;
    const float leg_move_speed = 8;
    const float body_move_speed = 3;
    const float stand_seat_speed = 1;
    volatile int rest_counter;      //+1/0.02s, for automatic rest
    //functions' parameter
    const float KEEP = 255;
    //define PI for calculation
    const float pi = 3.1415926;
    /* Constants for turn --------------------------------------------------------*/
    //temp length
    const float temp_a = sqrt(pow(2 * x_default + length_side, 2) + pow(y_step, 2));
    const float temp_b = 2 * (y_start + y_step) + length_side;
    const float temp_c = sqrt(pow(2 * x_default + length_side, 2) + pow(2 * y_start + y_step + length_side, 2));
    const float temp_alpha = acos((pow(temp_a, 2) + pow(temp_b, 2) - pow(temp_c, 2)) / 2 / temp_a / temp_b);
    //site for turn
    const float turn_x1 = (temp_a - length_side) / 2;
    const float turn_y1 = y_start + y_step / 2;
    const float turn_x0 = turn_x1 - temp_b * cos(temp_alpha);
    const float turn_y0 = temp_b * sin(temp_alpha) - turn_y1 - length_side;
    /* ---------------------------------------------------------------------------*/

      - setup function
       ---------------------------------------------------------------------------*/
    void setup()
    {
      //start serial for debug
      Serial.begin(9600);
      Serial.println("Robot starts initialization");

      //initialize default parameter
      pinMode(14, OUTPUT);
      set_site(0, x_default - x_offset, y_start + y_step, z_boot);
      set_site(1, x_default - x_offset, y_start + y_step, z_boot);
      set_site(2, x_default + x_offset, y_start, z_boot);
      set_site(3, x_default + x_offset, y_start, z_boot);
      for (int i = 0; i < 4; i++)
      {
        for (int j = 0; j < 3; j++)
        {
          site_now[i][j] = site_expect[i][j];
        }
      }
      //start servo service
      FlexiTimer2::set(20, servo_service);
      FlexiTimer2::start();
      Serial.println("Servo service started");
      //initialize servos
      servo_attach();
      Serial.println("Servos initialized");
      Serial.println("Robot initialization Complete");
    //   stand();
    //   delay(1000);
    //   hand_shake(2);
    //   Serial.println("hihihihihi");
    //   delay(1000);
    //   step_forward();
    //   step_forward();
    //   step_forward();
    //   step_forward();
    //   step_forward();
    //   step_forward();
    //   delay(1000);
    //   step_back();
    //   step_back();
    //   step_back();
    //   step_back();
    //   step_back();
    //   step_back();
    //   delay(1000);

    //   turn_left();
    //   turn_left();
    //   turn_left();
    //   turn_left();
    //   delay(1000);
    //   turn_right();
    //   turn_right();
    //   turn_right();
    //   turn_right();
    //   delay(1000);
    //   hand_wave(4);
    //   delay(1000);
    //   hand_shake(4);
    //   delay(1000);
    //   sit();
    //   delay(1000);
    }

    void servo_attach(void)
    {
      for (int i = 0; i < 4; i++)
      {
        for (int j = 0; j < 3; j++)
        {
          servo[i][j].attach(servo_pin[i][j]);
          delay(100);
        }
      }
    }

    void servo_detach(void)
    {
      for (int i = 0; i < 4; i++)
      {
        for (int j = 0; j < 3; j++)
        {
          servo[i][j].detach();
          delay(100);
        }
      }
    }

    /*
      - loop function
       ---------------------------------------------------------------------------*/
    void loop()
    {

      if(Serial.available() > 0)
       {
          data = Serial.read();
          Serial.print(data);
          Serial.print("\n");

          if(data == 'F')
            {
             Serial.println("Step forward");
             step_forward();
            }
          else if(data == 'B')
             {
              Serial.println("Step back");
              step_back();
            }
          else if(data == 'L')
             {
             Serial.println("Turn left");
             turn_left();

            }
          else if(data == 'R')
            {
              Serial.println("Turn right");
              turn_right();

            }
            else if(data == 'X')
            {
             Serial.println("Stand");
             stand();
            }
             else if(data == 'x')
            {
              Serial.println("Sit");
              sit();
            }
           else if(data == 'S' ||data == 'D' )

            {

            }

             else if(data == 'W')
            {
              digitalWrite(14, HIGH);
            }
              else if(data == 'w')
            {
             digitalWrite(14, LOW);
            }
            else if(data == 'V')
            {
              Serial.println("Hand wave");
              hand_wave(3);
            }
              else if(data == 'v')
            {
             Serial.println("Hand wave");
             hand_shake(3);
            }
             else if(data == 'U')
            {
              Serial.println("Body dance");
              body_dance(10);
            }
              else if(data == 'u')
            {
              Serial.println("Body dance");
              body_dance(10);
            }
            while(Serial.available()) {Serial.read();}
       }

    }

    /*
      - sit
      - blocking function
       ---------------------------------------------------------------------------*/
    /*
      - spot turn to right
      - blocking function
      - parameter step steps wanted to turn
       ---------------------------------------------------------------------------*/
    void turn_right()
    {
        move_speed = spot_turn_speed;

        if (site_now[2][1] == y_start)
        {
          //leg 2&0 move
          set_site(2, x_default + x_offset, y_start, z_up);
          wait_all_reach();

          set_site(0, turn_x0 - x_offset, turn_y0, z_default);
          set_site(1, turn_x1 - x_offset, turn_y1, z_default);
          set_site(2, turn_x0 + x_offset, turn_y0, z_up);
          set_site(3, turn_x1 + x_offset, turn_y1, z_default);
          wait_all_reach();

          set_site(2, turn_x0 + x_offset, turn_y0, z_default);
          wait_all_reach();

          set_site(0, turn_x0 + x_offset, turn_y0, z_default);
          set_site(1, turn_x1 + x_offset, turn_y1, z_default);
          set_site(2, turn_x0 - x_offset, turn_y0, z_default);
          set_site(3, turn_x1 - x_offset, turn_y1, z_default);
          wait_all_reach();

          set_site(0, turn_x0 + x_offset, turn_y0, z_up);
          wait_all_reach();

          set_site(0, x_default + x_offset, y_start, z_up);
          set_site(1, x_default + x_offset, y_start, z_default);
          set_site(2, x_default - x_offset, y_start + y_step, z_default);
          set_site(3, x_default - x_offset, y_start + y_step, z_default);
          wait_all_reach();

          set_site(0, x_default + x_offset, y_start, z_default);
          wait_all_reach();
        }
        else
        {
          //leg 1&3 move
          set_site(1, x_default + x_offset, y_start, z_up);
          wait_all_reach();

          set_site(0, turn_x1 + x_offset, turn_y1, z_default);
          set_site(1, turn_x0 + x_offset, turn_y0, z_up);
          set_site(2, turn_x1 - x_offset, turn_y1, z_default);
          set_site(3, turn_x0 - x_offset, turn_y0, z_default);
          wait_all_reach();

          set_site(1, turn_x0 + x_offset, turn_y0, z_default);
          wait_all_reach();

          set_site(0, turn_x1 - x_offset, turn_y1, z_default);
          set_site(1, turn_x0 - x_offset, turn_y0, z_default);
          set_site(2, turn_x1 + x_offset, turn_y1, z_default);
          set_site(3, turn_x0 + x_offset, turn_y0, z_default);
          wait_all_reach();

          set_site(3, turn_x0 + x_offset, turn_y0, z_up);
          wait_all_reach();

          set_site(0, x_default - x_offset, y_start + y_step, z_default);
          set_site(1, x_default - x_offset, y_start + y_step, z_default);
          set_site(2, x_default + x_offset, y_start, z_default);
          set_site(3, x_default + x_offset, y_start, z_up);
          wait_all_reach();

          set_site(3, x_default + x_offset, y_start, z_default);
          wait_all_reach();
        }
    }

    /*
      - go forward
      - blocking function
      - parameter step steps wanted to go
       ---------------------------------------------------------------------------*/
    void step_forward()
    {
        move_speed = leg_move_speed;

        if (site_now[2][1] == y_start)
        {
          //leg 2&1 move
          set_site(2, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(2, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(2, x_default + x_offset, y_start + 2 * y_step, z_default);
          wait_all_reach();

          move_speed = body_move_speed;

          set_site(0, x_default + x_offset, y_start, z_default);
          set_site(1, x_default + x_offset, y_start + 2 * y_step, z_default);
          set_site(2, x_default - x_offset, y_start + y_step, z_default);
          set_site(3, x_default - x_offset, y_start + y_step, z_default);
          wait_all_reach();

          move_speed = leg_move_speed;

          set_site(1, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(1, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(1, x_default + x_offset, y_start, z_default);
          wait_all_reach();
        }
        else
        {
          //leg 0&3 move
          set_site(0, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(0, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(0, x_default + x_offset, y_start + 2 * y_step, z_default);
          wait_all_reach();

          move_speed = body_move_speed;

          set_site(0, x_default - x_offset, y_start + y_step, z_default);
          set_site(1, x_default - x_offset, y_start + y_step, z_default);
          set_site(2, x_default + x_offset, y_start, z_default);
          set_site(3, x_default + x_offset, y_start + 2 * y_step, z_default);
          wait_all_reach();

          move_speed = leg_move_speed;

          set_site(3, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(3, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(3, x_default + x_offset, y_start, z_default);
          wait_all_reach();
        }
    }

    /*
      - go back
      - blocking function
      - parameter step steps wanted to go
       ---------------------------------------------------------------------------*/
    void step_back()
    {
        move_speed = leg_move_speed;
        if (site_now[3][1] == y_start)
        {
          //leg 3&0 move
          set_site(3, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(3, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(3, x_default + x_offset, y_start + 2 * y_step, z_default);
          wait_all_reach();

          move_speed = body_move_speed;

          set_site(0, x_default + x_offset, y_start + 2 * y_step, z_default);
          set_site(1, x_default + x_offset, y_start, z_default);
          set_site(2, x_default - x_offset, y_start + y_step, z_default);
          set_site(3, x_default - x_offset, y_start + y_step, z_default);
          wait_all_reach();

          move_speed = leg_move_speed;

          set_site(0, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(0, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(0, x_default + x_offset, y_start, z_default);
          wait_all_reach();
        }
        else
        {
          //leg 1&2 move
          set_site(1, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(1, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(1, x_default + x_offset, y_start + 2 * y_step, z_default);
          wait_all_reach();

          move_speed = body_move_speed;

          set_site(0, x_default - x_offset, y_start + y_step, z_default);
          set_site(1, x_default - x_offset, y_start + y_step, z_default);
          set_site(2, x_default + x_offset, y_start + 2 * y_step, z_default);
          set_site(3, x_default + x_offset, y_start, z_default);
          wait_all_reach();

          move_speed = leg_move_speed;

          set_site(2, x_default + x_offset, y_start + 2 * y_step, z_up);
          wait_all_reach();
          set_site(2, x_default + x_offset, y_start, z_up);
          wait_all_reach();
          set_site(2, x_default + x_offset, y_start, z_default);
          wait_all_reach();
        }
    }

    // add by RegisHsu

    void body_left(int i)
    {
      set_site(0, site_now[0][0] + i, KEEP, KEEP);
      set_site(1, site_now[1][0] + i, KEEP, KEEP);
      set_site(2, site_now[2][0] - i, KEEP, KEEP);
      set_site(3, site_now[3][0] - i, KEEP, KEEP);
      wait_all_reach();
    }

    void body_right(int i)
    {
      set_site(0, site_now[0][0] - i, KEEP, KEEP);
      set_site(1, site_now[1][0] - i, KEEP, KEEP);
      set_site(2, site_now[2][0] + i, KEEP, KEEP);
      set_site(3, site_now[3][0] + i, KEEP, KEEP);
      wait_all_reach();
    }

    void hand_wave(int i)
    {
      float x_tmp;
      float y_tmp;
      float z_tmp;
      move_speed = 1;
      if (site_now[3][1] == y_start)
      {
        body_right(15);
        x_tmp = site_now[2][0];
        y_tmp = site_now[2][1];
        z_tmp = site_now[2][2];
        move_speed = body_move_speed;
        for (int j = 0; j < i; j++)
        {
          set_site(2, turn_x1, turn_y1, 50);
          wait_all_reach();
          set_site(2, turn_x0, turn_y0, 50);
          wait_all_reach();
        }
        set_site(2, x_tmp, y_tmp, z_tmp);
        wait_all_reach();
        move_speed = 1;
        body_left(15);
      }
      else
      {
        body_left(15);
        x_tmp = site_now[0][0];
        y_tmp = site_now[0][1];
        z_tmp = site_now[0][2];
        move_speed = body_move_speed;
        for (int j = 0; j < i; j++)
        {
          set_site(0, turn_x1, turn_y1, 50);
          wait_all_reach();
          set_site(0, turn_x0, turn_y0, 50);
          wait_all_reach();
        }
        set_site(0, x_tmp, y_tmp, z_tmp);
        wait_all_reach();
        move_speed = 1;
        body_right(15);
      }
    }

    void hand_shake(int i)
    {
      float x_tmp;
      float y_tmp;
      float z_tmp;
      move_speed = 1;
      if (site_now[3][1] == y_start)
      {
        body_right(15);
        x_tmp = site_now[2][0];
        y_tmp = site_now[2][1];
        z_tmp = site_now[2][2];
        move_speed = body_move_speed;
        for (int j = 0; j < i; j++)
        {
          set_site(2, x_default - 30, y_start + 2 * y_step, 55);
          wait_all_reach();
          set_site(2, x_default - 30, y_start + 2 * y_step, 10);
          wait_all_reach();
        }
        set_site(2, x_tmp, y_tmp, z_tmp);
        wait_all_reach();
        move_speed = 1;
        body_left(15);
      }
      else
      {
        body_left(15);
        x_tmp = site_now[0][0];
        y_tmp = site_now[0][1];
        z_tmp = site_now[0][2];
        move_speed = body_move_speed;
        for (int j = 0; j < i; j++)
        {
          set_site(0, x_default - 30, y_start + 2 * y_step, 55);
          wait_all_reach();
          set_site(0, x_default - 30, y_start + 2 * y_step, 10);
          wait_all_reach();
        }
        set_site(0, x_tmp, y_tmp, z_tmp);
        wait_all_reach();
        move_speed = 1;
        body_right(15);
      }
    }

    void head_up(int i)
    {
      set_site(0, KEEP, KEEP, site_now[0][2] - i);
      set_site(1, KEEP, KEEP, site_now[1][2] + i);
      set_site(2, KEEP, KEEP, site_now[2][2] - i);
      set_site(3, KEEP, KEEP, site_now[3][2] + i);
      wait_all_reach();
    }

    void head_down(int i)
    {
      set_site(0, KEEP, KEEP, site_now[0][2] + i);
      set_site(1, KEEP, KEEP, site_now[1][2] - i);
      set_site(2, KEEP, KEEP, site_now[2][2] + i);
      set_site(3, KEEP, KEEP, site_now[3][2] - i);
      wait_all_reach();
    }

    void body_dance(int i)
    {
      float x_tmp;
      float y_tmp;
      float z_tmp;
      float body_dance_speed = 2;
      sit();
      move_speed = 1;
      set_site(0, x_default, y_default, KEEP);
      set_site(1, x_default, y_default, KEEP);
      set_site(2, x_default, y_default, KEEP);
      set_site(3, x_default, y_default, KEEP);
      wait_all_reach();
      //stand();
      set_site(0, x_default, y_default, z_default - 20);
      set_site(1, x_default, y_default, z_default - 20);
      set_site(2, x_default, y_default, z_default - 20);
      set_site(3, x_default, y_default, z_default - 20);
      wait_all_reach();
      move_speed = body_dance_speed;
      head_up(30);
      for (int j = 0; j < i; j++)
      {
        if (j > i / 4)
          move_speed = body_dance_speed * 2;
        if (j > i / 2)
          move_speed = body_dance_speed * 3;
        set_site(0, KEEP, y_default - 20, KEEP);
        set_site(1, KEEP, y_default + 20, KEEP);
        set_site(2, KEEP, y_default - 20, KEEP);
        set_site(3, KEEP, y_default + 20, KEEP);
        wait_all_reach();
        set_site(0, KEEP, y_default + 20, KEEP);
        set_site(1, KEEP, y_default - 20, KEEP);
        set_site(2, KEEP, y_default + 20, KEEP);
        set_site(3, KEEP, y_default - 20, KEEP);
        wait_all_reach();
      }
      move_speed = body_dance_speed;
      head_down(30);
    }

    /*
      - microservos service /timer interrupt function/50Hz
      - when set site expected,this function move the end point to it in a straight line
      - temp_speed[4][3] should be set before set expect site,it make sure the end point
       move in a straight line,and decide move speed.
       ---------------------------------------------------------------------------*/
    void servo_service(void)
    {
      sei();
      static float alpha, beta, gamma;

      for (int i = 0; i < 4; i++)
      {
        for (int j = 0; j < 3; j++)
        {
          if (abs(site_now[i][j] - site_expect[i][j]) >= abs(temp_speed[i][j]))
            site_now[i][j] += temp_speed[i][j];
          else
            site_now[i][j] = site_expect[i][j];
        }

        cartesian_to_polar(alpha, beta, gamma, site_now[i][0], site_now[i][1], site_now[i][2]);
        polar_to_servo(i, alpha, beta, gamma);
      }

      rest_counter++;
    }

    /*
      - set one of end points' expect site
      - this founction will set temp_speed[4][3] at same time
      - non - blocking function
       ---------------------------------------------------------------------------*/
    void set_site(int leg, float x, float y, float z)
    {
      float length_x = 0, length_y = 0, length_z = 0;

      if (x != KEEP)
        length_x = x - site_now[leg][0];
      if (y != KEEP)
        length_y = y - site_now[leg][1];
      if (z != KEEP)
        length_z = z - site_now[leg][2];

      float length = sqrt(pow(length_x, 2) + pow(length_y, 2) + pow(length_z, 2));

      temp_speed[leg][0] = length_x / length * move_speed * speed_multiple;
      temp_speed[leg][1] = length_y / length * move_speed * speed_multiple;
      temp_speed[leg][2] = length_z / length * move_speed * speed_multiple;

      if (x != KEEP)
        site_expect[leg][0] = x;
      if (y != KEEP)
        site_expect[leg][1] = y;
      if (z != KEEP)
        site_expect[leg][2] = z;
    }

    /*
      - wait one of end points move to expect site
      - blocking function
       ---------------------------------------------------------------------------*/
    void wait_reach(int leg)
    {
      while (1)
        if (site_now[leg][0] == site_expect[leg][0])
          if (site_now[leg][1] == site_expect[leg][1])
            if (site_now[leg][2] == site_expect[leg][2])
              break;
    }

    /*
      - wait all of end points move to expect site
      - blocking function
       ---------------------------------------------------------------------------*/
    void wait_all_reach(void)
    {
      for (int i = 0; i < 4; i++)
        wait_reach(i);
    }

    /*
      - trans site from cartesian to polar
      - mathematical model 2/2
       ---------------------------------------------------------------------------*/
    void cartesian_to_polar(volatile float &alpha, volatile float &beta, volatile float &gamma, volatile float x, volatile float y, volatile float z)
    {
      //calculate w-z degree
      float v, w;
      w = (x >= 0 ? 1 : -1) * (sqrt(pow(x, 2) + pow(y, 2)));
      v = w - length_c;
      alpha = atan2(z, v) + acos((pow(length_a, 2) - pow(length_b, 2) + pow(v, 2) + pow(z, 2)) / 2 / length_a / sqrt(pow(v, 2) + pow(z, 2)));
      beta = acos((pow(length_a, 2) + pow(length_b, 2) - pow(v, 2) - pow(z, 2)) / 2 / length_a / length_b);
      //calculate x-y-z degree
      gamma = (w >= 0) ? atan2(y, x) : atan2(-y, -x);
      //trans degree pi->180
      alpha = alpha / pi * 180;
      beta = beta / pi * 180;
      gamma = gamma / pi * 180;
    }

    /*
      - trans site from polar to microservos
      - mathematical model map to fact
      - the errors saved in eeprom will be add
       ---------------------------------------------------------------------------*/
    void polar_to_servo(int leg, float alpha, float beta, float gamma)
    {
      if (leg == 0)
      {
        alpha = 90 - alpha;
        beta = beta;
        gamma += 90;
      }
      else if (leg == 1)
      {
        alpha += 90;
        beta = 180 - beta;
        gamma = 90 - gamma;
      }
      else if (leg == 2)
      {
        alpha += 90;
        beta = 180 - beta;
        gamma = 90 - gamma;
      }
      else if (leg == 3)
      {
        alpha = 90 - alpha;
        beta = beta;
        gamma += 90;
      }

      servo[leg][0].write(alpha);
      servo[leg][1].write(beta);
      servo[leg][2].write(gamma);
    }

NOTE: I am deleting some functions like void sit(void) stand as the maximum limit of characters was reached.
This is my esp32 code
    #include "Arduino.h"
    #include "WiFi.h"
    #include "Audio.h"

    #define I2S_DOUT      25
    #define I2S_BCLK      27
    #define I2S_LRC       26

    Audio audio;

    char data = 0;
    void setup()
    {

      Serial.begin(115200);

      WiFi.disconnect();
      WiFi.mode(WIFI_STA);
      WiFi.begin( "Physics", "299792458");

      while (WiFi.status() != WL_CONNECTED)
        delay(1500);

      audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
      audio.setVolume(100);
      audio.connecttospeech("Hello From akshit singh,,welcome to tapovan international school's project day ,,i am a smart walking robot ,you can also call me astra bot ", "en");

    }

    void loop(){
    if(Serial.available() > 0)
       {
          data = Serial.read();
          Serial.print(data);
          if(data == 'A')
            {
             audio.connecttospeech("hello everyone ,welcome to tapovan international school's project day ", "en");
             Serial.println("done");
            }

          else if(data == 'B')
            {
             audio.connecttospeech("BYE Bye everyone", "hi");
             Serial.println("done 2");
            }
          else if(data == 'C')
            {
             audio.connecttospeech("i am a smart walking robot ,you can also call me astra bot ", "hi");
             Serial.println("done 2");
            }

          else if(data == 'F')
            {
             audio.connecttospeech("going forward ,sir", "hi");
             Serial.println("done 2");
            }

          else if(data == 'b')
            {
             audio.connecttospeech("going backward ,sir", "hi");
             Serial.println("done 2");

            }
          else if(data == 'L')
            {
             audio.connecttospeech("moving left, sir", "hi");
             Serial.println("done 2");

            }
          else if(data == 'R')
            {
             audio.connecttospeech("moving right ,sir", "hi");
             Serial.println("done 2");

            }

       }

    {
      audio.loop();
    }

      }

    void audio_info(const char *info) {
      Serial.print("audio_info: "); Serial.println(info);
    }

Well first of all you need to be aware that the UNO runs at 5V, and the ESP32 at 3V3, so you will need a level shifter in between the UNO and ESP32 unless you want to possibly damage your ESP32.
You can create a bidirectional level shifter with an N-Channel mosfet and 2 resistors,
or buy a breakout board, or use a chip like the GTL2010. Just note that not all bidirectional level shifters are the same, some require changing the direction with a pin(usually DIR), the GTL2010 is not one of those.
Bitbanged UART
Can be done on any pin.
Either a uni or bi directional level shifter will work just fine.
SPI
Since your servos aren't being run by PWM/Timer hardware you could use the analog pins for a couple of your servos, and use the SPI peripheral which uses pins 10, 11, 12, and 13.
Your ESP32 is sending the commands, so you'd want to set up the ESP32 as the master, and the UNO as the slave.
Just like the BBUART option, either a uni or bi directional level shifter will work.
I2C
This uses the SDA and SCL pins next to VREF, which are really just A4 and A5. And again, you'd set the ESP32 to be the master, and the UNO to be the slave.
Be aware that you will need a bidirectional level shifter, a unidirectional will not work.
Although I don't recommend, there is a chance you may be able to get away without using a level shifter by attaching your pull-up resistors to 3V3. Just note, for the atmega328P to register a high logic level, the input voltage needs to be 60% of VCC. So if its running at 5V, it will take 3V to read high, which does have a chance at working. But if its running at 5V5, it will require 3V3 to register high and probably wont function properly if at all.
Another reason to use a level shifter is apparently the Arduino I2C library uses the internal pull-up resistors, so you would have to modify the library to disable them, so your ESP32 pins aren't pulled to 5V.
BBUART is probably your best bet, it uses the least pins, and easiest to work with in code. All you need is a level shifter and you're good to go. But if you feel confident enough coding wise, you could try I2C without a level shifter, and if it doesn't work then purchase one.


text:
When I use AnalogueWrite the voltage doesn't vary properly
I have a project where I want to control a pump, I use an Arduino, connected to a driver L298N and I will connect the pin 5, 6, 7 of the arduino to the pin IN2, IN1, ENA of the driver respectively and the motor will be connected to the output
My materiel :

Arduino Uno R3
Multimeter
Arduino IDE 2.1.1

The issue :
When I use the function analogWrite the voltage vary only between two value (0v or 5.5v).
The pin used was the Digital pin n°7, noted in the code 7.
The code :
#define PUMP_DIR_1 5
#define PUMP_DIR_2 6
#define PUMP_PWM 7
#define INVERTED 0

void setup() {
  Serial.begin(9600);
  pinMode(PUMP_PWM, OUTPUT);
}

void set_pump_speed(int speed){
  Serial.print("Set speed ");
  Serial.print(speed);
  Serial.print("\r\n");
  analogWrite(PUMP_PWM, speed);
}

void loop() {
  set_pump_speed(255);
  delay(3000);
  set_pump_speed(0);
  delay(3000);
  set_pump_speed(125);
  delay(3000);
}

As output I obtained :

00:32:17.184 -> Set speed 0
00:32:20.175 -> Set speed 125
00:32:23.178 -> Set speed 255
00:32:26.182 -> Set speed 0
00:32:29.197 -> Set speed 125
00:32:32.201 -> Set speed 255

From the mutlimeter I obtained :

0v when speed = 0
0v when speed = 125
5.5v when speed = 255

The arduino is not wired to anything

Pin 7 isn't a PWM pin. Use, say, pin 6 and you will get correct results. The PWM pins are marked with a "~" on the board.

Thank your for your answer, I feel stupid, because it is not the first time I use PWM on Arduino and I never took this in consideration.

@Nept0 Don't worry! It must have worked last time by chance, now you know why. :)


text:
Arduino Nano uploading problems
I am having trouble uploading code to my Arduino Nano. It has been very trusty in the past, but I am getting this new error when uploading any code to it:
avrdude: ser_open(): can't set com-state for "\\.\COM15"
This happened a while ago on my Windows 11 Laptop, and I was unable to resolve it, and now it has just started on my Windows 10 desktop.
I tried disabling and re-enabling the CH340 in device manager, restarted my computer, and uninstalled the CH340. After uninstalling it, it has dissapeared and does not even show up in Device Manager at all.
If anybody could provide some help explaining how to make it show up in Device Manager again, and also make it uploadable, I would greatly appreciate it!
Thank you in advance

did you try to change the Processor option in Tools menu?

@Juraj Yes, I did. I beleive it may have something to do with recent Windows updates, but im not sure.

some other program may have possession of COM15

@jsotola I dont think so. It switches ports every now and then, and none of them work. i can upload to any other type Arduino. Doesn't matter the port.

then the Nano has failed in some way ... check for foreign objects inside the USB connector and on the surface of the board ... also try a different cable

@jsotola Likely not. I was using it just fine with the same cable and hardware. I rebooted my PC, did some updates, and now it no longer works.

next step is to plug it into another computer to see if it is recognized

I've seen something about auto updated ch340 driver causing issues and they've solved it by downgrading it.

Finally found something about that:  https://github.com/SHWotever/SimHub/wiki/Arduino---Counterfeit-Fake-CH340G-chips-driver-issues  apparently there are even ch340 fakes :D

@KIIV Thank you soooo much! I have been needing that for so long! After executing it, it operated just fine! I can upload to my Arduino Nano without any problems now. I don't think I can mark that as an answer, and I can't upvote it, but thank you!

I'll make it into an answer, I just wasn't sure if it's it

Apparently there was an update in ch340 drivers early in 2023 and it broke something for counterfeit ch340. Solution is using older version of the driver (and possibly disabling automatic updates for the drivers in the Windows).
Issue description and solution found on github:

Rollback to an older driver manually :
Unfortunately since the incompatible driver is delivered through
windows update it is harder to keep an older driver installed :
Recommended : Block windows drivers update so the newest driver won't get installed automatically:
https://www.makeuseof.com/windows-stop-automatic-driver-updates (note:
while this is required to be able to install and keep the older ch340g
driver but this will affect any of your future devices)
Reinstall an older driver here : 01/30/2019, 3.5.2019.1 CH341SER driver


text:
LCD I2C connection problems
I am hoping there is a simple fix to this problem.
I am playing around with a 16x2 lcd with a I2C connector attached. I wired it up to an elegoo uno R3.
I started with some code I've used before and ended up with one row of the LCD fully lit and the other dark.
After a ton of trouble shooting, I can not get the LCD to show anything but one lit and one dark row.

In this image:
Power: 5V, 1.5A

Pin
LCD
Uno

SCL
SCL
SCL

SCA
SDA
SDA

+
VCC
5V

gnd
gnd
gnd

I've also tried:

putting the SDA to A4 and the SCL to A5
Using different power supplies
Powering from the USB connector

And I've tried several of the libraries available
They are all variations of the following from the Adafruit_LiquidCrystal library:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
    // initialize the LCD
    lcd.begin();

    // Turn on the blacklight and print a message.
    lcd.backlight();
    lcd.print("Hello, world!");
}

void loop()
{
    // Do nothing here...
}

No matter what I do the display does not change.

There should be a potentiometer for the contrast. Turning it ccw will make the text visible

I've played with that. There is no position where text is visible. The top row is fully lit and the bottom row off. When I turn the pot, the lit crystals dim evenly to nothing.

Maybe try an I2C scanner to verify the I2C address which your code assumes is 0x27

That fixed it. The scanner found the i2c at 0x3f. Everything is working. Thank you!

@6v6gt, if you could create an Answer and Andrew if you could accept it, that would make this Q & A perfect for anyone else in the same predicament.

Some common problems with LCD displays which incorporate an I2C backpack include:

Not using the correct I2C address for the I2C backpack. Use an I2C scanner to discover the correct address.
Mixing voltages without proper level shifting, say using a 5v display with a 3.3v MCU
Failing to adjust the contrast potentiometer
Some I2C backpacks may use a non-standard pin allocation which may be corrected by specifying a pin mapping in the constructor to the display library. Fortunately, this is rare.
Using code samples intended for a different variant of the library supporting the display. Always use a basic test sketch which is packaged with the chosen library to verify the performance of the display.


text:
Arduino Servo MG90S not moving
I'm new with arduino (nano). I am having problems with Servo MG90S, I cant make it move. Im doing the easiest test, Servo cables connected:
Brown -> gnd
Red -> 5v
Orange -> pin 9
my arduino code is:
#include <Servo.h>
Servo servo;

const int servoPin = 9;

void setup()
{
  servo.attach(servoPin);
  Serial.begin(9600);
}

void loop()
{
  servo.write(40);
  delay(2000);
  servo.write(0);
  delay(2000);
}

As you see its a super simple example, but the result is the servo vibrating slightly.
Extra data: the servo start vibrating with the servo.attach(servoPin); it doesnt matters if I set the servo.write(40);

The parameter of Servo.write() is a value between 0 and 180, so -40 is not valid. Does is change something if you use 50 and 130 instead?

No, the same result. Even if I only set the attach without the servo.write the servo is vibrating with no stop. I don't know if that is a normal behavior

Arduino power source is one of the most common problems.  For example a 9 Volt battery may run an Arduino but is unlikely to have enough power to run a motor.  What are you using as a power source?

Also, if you change your code please edit the question to reflect the change.

As I'm in developing procces, im using the mini usb wire that goes to my desktop pc usb 3.0 port

Did you connect the servo to Arduino GND AND the USB port? That may be your problem. Nowhere does it say that. You just said "Brown -> gnd." That doesn't mean so.

Also, you may be connecting it to just the Arduino, and that could be the problem, too. As usually all Arduino have very little current.

Wait, so... what is the USB connected to? The servo? May you, please, provide more detail? I could give an answer, but I am not sure what the EXACT problem is.

I edited the post and added an image of how it tis connected, all is conected to protoboard and this to the arduino (in my cade arduino nano), the USB wire is the one who power de arduino board, and goes from my pc USB port

Okay... try this: use a separate 5V power supply for your servo. Connecting the red to the positive of the power supply, and black to the GND of the power supply. Let me, then, know if it's still twitching. That may be your problem.

Also, what model is the servo? Like, what is the name of it? It depends of why it is twitching. If it's a micro servo, it would SHOULD be fine. Just Google what you have and post what it is. The more details, the better.

Also, remember: Google is your best friend, in this case.

I compiled the code, it works. So, there seems to be an issue with the hardware. I am trying to decipher between the two: it's either your Arduino Nano or the servo itself. Or POSSIBLY both.

Oh, and I DID use the same exact wiring.

Oh, right. I didn't read. Sorry. The model of the servo is MG90S. I will read the datasheet on that.

Okay, so here is the deal: I have looked up the datasheet for the Arduino Nano and the MG90S. The problem is: you may have killed your Arduino Nano. As the datasheet for the Arduino Nano says, "Max DC Current per I/O Pin... 40 mA." (The Datasheet for Arduino Nano). I am not sure if that's 100% of the issue, so, then I looked up the MG90S and it says "Current (typical during movement)... 120-250mA" (Also, another datasheet). Basically, all that means is that you MAY have to buy another Arduino because you may have used a servo that requires to much (for lack of a better term) "power." Using some math we see that you went approximately: 210 milli-amps over. Sorry.

Okay, so my first answer is WRONG. The reason being is because the MG90S and the SG90 (which are very similar servos, except the gearing and some others) CAN run off that Arduino. As this article shows: How to control the MG90S with the Nano. However, it IS best to run that servo off a separate power supply (5V). The issue lies within your wiring. Somehow, there is some miscommunication between us, you, and the Arduino.

I have tested the output voltage
5v pin -> 4.6v
pin 9 with servo.write(0) -> 0.13v
pin 9 with servo.write(180) -> 0.56v
I don't know if these are acceptable values.

Do you know what I mean by "separate power supply?" I think you need some time to reflect. You seem to steadily NOT want to use another source for your servo. Why? I told you the answer, gave you an article, and even asked, kindly, for more details. What more do you want from me?

That article gives the EXACT instructions. *Edit - please edit your response with more detail, as I still can't seem to help you (which I really do).

Honestly, I think I am starting to second guess myself on my first answer. I will post it for your sake. I think you BURNT your Arduino. Outputting those results, they seem terrible. So, yeah, I think you BURNT your Arduino.

Sorry, I didn't realize there were two answers cause they appeared together and I only saw one. I think the other one is okey.
Thank you for taking your time to help.

Well, like I said, the first answer (that you accepted ) is flat out wrong. That was my assumption. But I am okay as long as you are okay, with the answer, of course. And sorry, if I came across as a jerk or frustrated. That was not the intention. Hope your project goes well, though! I just want you to learn about this Googling thing. Again, sorry.


text:
Intercepting Keyboard Data on a Micro Controller
Recently I have purchased male and female USB-C breakout boards. I intend to connect the male breakout to a keyboard and the female end to my computer using a USB-C cable and wire the breakouts together using a breadboard. I was wondering if it is possible to read the keystrokes being sent across the D- and D+ lines with a micro-controller.
Here is an image of how I currently have the breakout boards setup

Just a suggestion, you should probably edit your question and replace Micro Controller with Arduino so as not to be off topic.

Welcome to SE/Arduino! Please take the [tour] to learn how this site works, and read "[ask]". -- Would you mind to [edit] your question and extend on the reason, please? -- It is much simpler to capture key presses in the receiving operating system, or in the keyboard before being transmitted. USB is quite complex "on the wire," however, you might try what small logic analyzers are doing. These commonly have special hardware involved, a simple device like the microcontroller of an Arduino cannot do it.

You may want to take a look at this video. The author decodes the USB HID protocol by hand, with pen and paper.

It would be far far easier to interface an Arduino to an old PS2 keyboard.
USB is complex.  You would have to understand USB protocol, then understand the HID (Human Interface Device) protocol inside of the USB protocol.  As HID can interface a number of devices like mice and keyboards, you might have to then understand the keyboard portion of the HID protocol.
As a point of reference, commercial USB analyzers cost hundreds of dollars.  This USB analyzer cost about $500.
As an alternative, have you considered an all software USB monitor? These normally reside on the same computer as the USB Device is attached to. Wireshark should be able to do this.
Also, assuming that is a Pro Micro used on the keyboard, consider adding code to its Atmel processor to send out keyboard activity on an unused pin. This approach might proved much easier then monitoring the keyboard after its data has been incorporated into the USB protocol.

I don't want to discourage you.  I just what to point out the difficulties of creating a USB interface.  Especially one that is not a USB Device or USB Host (i.e. one that can monitor but will not enumerate or try to take control of the USB).

This is a really old thread that discusses a USB Sniffer. Even back then (likely only USB 3.0 existed at the time) it was thought to be a really difficult task.

OP doesn't want a general USB sniffer. only keyboard

Btw you can use Wireshark to catch USB communication directly on the system. His question looks more like XY problem. If he has everything on the photo, he could just program it directly into that on-keyboard MCU (looks like Pro Micro with usb-c?)

@Juraj, I think once you start using USB to communicate you are going to have to buy into the entire USB protocol.  But please follow up w/links to project that monitor only a USB/HID/Keyboard.  I would be fun to figure out how they did it!

Good points @KIIV.  I forgot about Wireshark.  And you are correct, That Pro Micro should be able to monitor and spit out the keyboard activity way easier than picking apart the USB signal.

so my though is that there are Arduino projects with keyboard as input and there are projects where the Arduino is the keyboard. so it should be enough to copy keys from input to output. but of course with the keyboard on the photo the keyboard is already an Arduino.

I see, I was hoping for a simple way to have a microcontroller (like another Pro-Micro for example) to read in key inputs sent over USB. Creating a USB interface seems like it is currently out of my scope.

You can try @Juraj 's idea.  But you can't have 2 keyboards.  Well, you might be able to ... but you don't want 2 keyboards.  You want 1 keyboard and something that will listen.  So you need to keep the new keyboard from getting enumerated by the USB host.  But you still need it to listen.  This is where I'm in unknown waters.  It's almost like you need the listener to act like the 1st keyboard except it can not talk back.  This isn't just out of your scope, it's out of most of our scopes!

Micro can't be an USB host. USB host shield would have to be used to read an USB keyboard. but again. here the keyboard is already an Arduino.


text:
Read one byte from file and convert to decimal
Ok, I'm fairly new to Arduino and I'm trying to read bytes from a file in an SD card and convert to integer values (0-255).
I have a file, with 1 byte on it (128 int value, created in Python, can provide the code if necessary) and the hex dump (binary mode) is:
xxd -b single_byte.dat
00000000: 10000000

So far so good, right? So I was expecting to read this byte from the file (SD card) and then convert back to 128 value. This is my Arduino code:
#include <SPI.h>
#include <SD.h>

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 4;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  delay(100);
  Serial.print("\nInitializing SD card...");

  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    while (1);
  }

  File file;
  byte one_byte;
  int dec_value;

  file = SD.open("single_byte.dat", FILE_READ);
  one_byte = file.read();
  file.close();

  dec_value = int(one_byte);

  Serial.println(dec_value, DEC);

}

void loop(void) {
}

I was expecting the output to be 128.
However I get:

What am I missing? (yes, I tried generating the .dat file with big-endian encoding, same result)

Which version of Python are you using? "Note: Since Python 3.6, all files are read and written by Python using utf-8 by default, even on Windows."  Maybe you are writing UTF16 and do not realize it.  What happens if you try to read the next byte, and the next?

I'm using Python 3.9 (on Debian 11)... I haven't tried reading more bytes but, the hex dump displays a single byte on the file so, I think file is ok?

Oh, I think I see what you did.  Try adding SD.begin.

I just tried adding the SD.begin(4) code, no luck, same result as before: message "initialization done" is displayed, but the output on my variable is the same. What else can I try? Maybe the int(one_byte) is not the way to go and something else (bit manipulation?) must be done?

@melev Can you update your code to show where you added the SD.begin(4)?

... @melev, I see where you get most of your code from the 2nd example on the arduino.cc page I linked to in the answer below.  Assuming all examples on that page work, consider using just the 1st example on that same page.  True, it does not give you as much diagnostic details, but it may be a better place to start given our assumption the example is able to open and read a file on an SDCard successfully.

@st2000 I got it working, turns out I'm an idiot, LOL. your comment "given our assumption the example is able to open file" got me thinking, so I added an if(file) and guess what... it wasn't!!! so I was just reading garbage I guess. I'm posting the full explanation as the answer, thanks A LOT for your time.

@Fahad I got it working, it was the freaking filename that was the problem, check my answer. Thanks!

FWIW, xxd clearly shows that the file doesn't contain a single byte, it contains 4 bytes. Probably a uint32le. But, the nice thing about little-endian is that if you read it as a single byte you'll get the right answer anyway as long as the value is <256.

Ok, I got it working now, here's what was happening:
Turns out the file wasn't being opened. Why? seems like there's a limitation on the filename length, I noticed this after adding the lines:
root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE)

And sure enough my file was not detected as single_byte.dat but it was something like: single_~.dat so I renamed the file to test.dat and tada! code now works like a charm.
I guess I overlooked this restriction on the documentation, so keep this in mind when you use an SD card.
Also, make sure to check if you are really opening your file because no exception will be thrown if you reference an uninitialized file pointer I guess.
Just make sure to have:
file = SD.open(filename, FILE_READ);
if(file){
    // Do things here.
}
else{
    Serial.println("You're out of luck: Can't open file");
}

Ok, there goes my Sunday. Thanks all for reading!!!

The root of this restriction is partly Microsoft and partly the library. On one hand Microsoft stuffed long file names on their old FAT filesystems trying to be backwards compatible. Each files has a 8+3 short name and following some directory entries for the long name. On the other hand the library apparently saves on size and left out the code to work with long names. -- However, the main lesson you learned is: Always check return values!

Ah, good catch! So you asked: "Why? seems like there's a limitation on the filename length, I noticed this after adding the lines:"  The "Why" is because the FAT file system format dates back from when Bill Gates grabbed something called DOS from some computer club.  That fixed all file names to 8.3 or an eight-characters-decimal-point-three-character format.  That still exists.  Some clever workarounds are used to hide it.  But it still exists.  So the actual file name gets "mangled" when you try to go beyond the 8.3 format. I think the clever trick is that they all get "mangled" uniquely.

Consider adding a call to SD.begin() as is done in the example found on this arduino.cc web page.
Here's the section of the example code where SD.begin() is used:
  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }