title: communicating esp 32 with arduino uno

text:
# Question
Title: 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);
    }

```

# Answer
> 1 votes
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.*

---
Tags: arduino-uno, esp32, robotics
---


# Question
Title: Can arduino be used in industrial projects?
I'm developing an industrial project and my programming knowledge is limited to arduino.

I'm planning to use either Atmega328 or STM32F103C8T6 chip in my pcb and to program it using arduino IDE. My plan is just to use Arduino IDE to create sketches and programming the chip after burning arduino bootloader.

Is this concept viable for industrial environments? Are there any problems/challenges using this method?

# Answer
You don't talk about Arduino hardware. Your concern is the Arduino IDE.

Which is a lawyer's licensing topic. Might depend on the libraries you plan to use. And whether you want to hide the fact you're using (selling ?) open source software.
> 1 votes

# Answer
I don't think there are any major problems with your proposal. The chips themselves will have documented limitations (specifications) that you would need to be aware of. I think you would find that most manufacturers of washing machines, toasters, TVs etc. do not also manufacture processor chips, so they too would be relying on commercially-available chips such as the ones you mentioned.

This brings us to the IDE. It is basically a "wrapper" around a C++ compiler which is available for anyone to use in any project. The Arduino libraries themselves may have licensing you would need to be aware of, the same as if you used a library not associated with the Arduino.

See this page: Licensing for products based on Arduino:

> ## Note:
>
> * You can freely use Arduino hardware and software for your personal purposes, or within your company or organization, with no restrictions. The rules described in this document apply only when you distribute products based on Arduino to third parties or you make them public in any form.
> * If you comply with the open-source licenses of Arduino, you can distribute your software/hardware products for free or commercially. This document provides a summary of such rules for your convenience and does not waive the need to get professional legal advice.

---

I am not a lawyer, and if you are worried about the legal aspects I suggest you get legal advice. However I doubt that a small-scale project would warrant anyone getting their lawyers involved. For one thing, it would be hard to prove that the 0s and 1s on your chip were produced using the Arduino IDE, or any of its libraries.
> 1 votes

# Answer
The chips should work fine, however it depends on how things are assembled, what parts are used, ambient temperature, cooling and electronic protection. For reference here is what I use: Hobby: 0°C to 50°C Commercial: 0 ° to 70 °C. Industrial: −40 ° to 85 °C. Military: −55 ° to 125 °C. Automotive: -40°C to 175°C, location dependent. Without a complete set of specifications, schematic, and component information I cannot give you a yes or no answer.

At this point you should realize it will not be a slam dunk simple project.
> 0 votes

# Answer
Industrial environments can be hostile to electronics that aren't "hardened" against the potential hazards. There is no one answer to this without knowing the specific environment. Will it be controlling heavy electrical machinery (even if not switching the power). You'll need to know more about the intended environment to know whether and how you can harden your electronics to it.

But if nothing else, Arduino is terrific for prototyping things that, once the concept is proven, might then have to be re-built to a higher standard for production use.
> 0 votes

---
Tags: atmega328, bootloader, stm32
---


# Question
Title: Problem with reading MIFARE 13.5Mhz with MFRC522 lib
I'm trying to read the UID of MIFARE 13.5Mhz cards with MFRC522 lib and I have defined the following function for it.

```
void getUID() {
if (mfrc522.PICC_IsNewCardPresent() && mfrc522.PICC_ReadCardSerial()) {
  Serial.println("Scanned PICC's UID:");
  tag = "";
  for (byte i = 0; i < mfrc522.uid.size; i++)
   {
    tag.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    tag.concat(String(mfrc522.uid.uidByte[i], HEX));
   }
  tag.toUpperCase();
  Serial.println(tag);
  mfrc522.PICC_HaltA(); // Stop reading
}
}

```

this function works perfectly fine in void loop() but when I call it in the following web request my esp8266 crashes.

```
controlserver.on("/searchuid", HTTP_POST, [](AsyncWebServerRequest *request){

    transmit = request->arg("idcode");
    if (request->hasArg("configmodule")) {
    File file = SPIFFS.open("/inputString.txt", "r");
    if (!file) {
    Serial.println("Failed to open file");
    return;
    }
    getID();
    delay(500);
    Serial.println(tag);
    String content = file.readString();
    if (content.indexOf(tag) >= 0) {
    Serial.println("Found search string");
  } else {
    Serial.println("Did not find search string");
  }

    }
  });

```

and I cannot understand why, any help will be appreciated.

# Answer
Under "Important Things To Remember" in the ESPAsyncWebServer README:

> You can not use yield or delay or any function that uses them inside the callbacks

Your code calls `delay()` in the callback, and calls functions that you cannot know do not call `delay()` or `yield()`.

You need to rewrite your code to follow the instructions in the web server's documentation.
> 1 votes

---
Tags: esp8266, web-server
---


# Question
Title: Initialize ATMEGA32U4 with arduino bootloader with AVR Dragon?
I built my own atmega32u4 board. I wish to use it as "arduino" so I need to upload first the arduino bootloader.

Now, to do that I need another arduino but I don't have it currently.

However I have an AVR Dragon, which was the way to program these chips years back. So: how the heck can I burn the arduino bootloader to the mega32u4 with avr dragon?

Note: I can use AVR Dragon, and it can see the mega. Just I have NO clue on where this \** arduino stores it's bootloader hex file.

# Answer
> 1 votes
You don't need another Arduino if you have a programmer, but there is some problem with the AVR Dargon programmer and avrdude so the Arduino boards package and the MiniCore boards package don't have it configured.

With a supported programmer you can burn the bootloader with Arduino IDE. In Tools menu you select the board most similar to your custom board, then you select in Tools menu the programmer and then you select "Burn bootloader".

# Answer
> 0 votes
See https://github.com/arduino/ArduinoCore-avr/tree/master/bootloaders/caterina

The file you probably want would be `Leonardo-prod-firmware-2012-12-10.hex` in that folder.

Those files will be in your Arduino installation, in a folder called "bootloaders".

---
Tags: arduino-ide
---


# Question
Title: ArduinoJson library: how much space to allocate for serialized buffer?
I am using the fantastic `ArduinoJson` library for working with JSON data on my ESP8266. I have been facing issues with **random software wdt resets** and have been investigating memory leaks wherever I can. I want to trim down my use of `Strings` and `DynamicJsonDocument`s as much as possible. So I thought of using automatic variables: char buffers: `char[N]` and `StatitcJsonDocument`s instead.

I am using the ArduinoJson assitant service to help me figure out how many bytes I should reserve. The following is one response payload, I am expecting to receive:

```
// char input[MAX_INPUT_LENGTH];

StaticJsonDocument<128> doc;

DeserializationError error = deserializeJson(doc, input, MAX_INPUT_LENGTH);

if (error) {
  Serial.print(F("deserializeJson() failed: "));
  Serial.println(error.f_str());
  return;
}

int statusCode = doc["statusCode"]; // 200
bool needUpdate = doc["needUpdate"]; // true
const char* message = doc["message"]; // "update required"

JsonObject data = doc["data"];
const char* data_deviceId = data["deviceId"]; // "DLD00005"
const char* data_user_fw_version = data["user_fw_version"]; // "0.0.0"
const char* data_new_fw_version = data["new_fw_version"]; // "0.0.5"

```

As you can see I am using a `char [N]` type as the input, which is in fact being copied using `strncpy()` from the `https.getString().c_str()` from the response of a previous `https.POST()` request. My issue is that **I do not know how much memory I should reserve for the `char[N]` array**, ie what should be the value of `N`? The reasons I ask is that I am getting a `deserialization() failed: IncompleteInput` error, which I'm pretty sure is because the `char[N]` buffer is not large enough. So my question is if the StaticJsonDocument object is `128` bytes, then how big should I make the `char[N]` buffer (is there any relation between the sizes)? Or should I just go with an arbitrarily large value like `char[512]` which I want to avoid to avoid stack overflows?

```
StaticJsonDocument<128> payload;
char payloadSerial[???];
...
int status = https.POST(payloadSerial);
strncpy(payloadSerial, https.getString().c_str(), sizeof(payloadSerial));
DeserializationError error = deserializeJson(payload, payloadSerial, sizeof(payloadSerial));
if (error) {
    Monitor.print(F("DeserializeJson() failed: "));
    Monitor.println(error.f_str());
}

```

# Answer
> 2 votes
You're asking about code that looks like this:

```
StaticJsonDocument<128> payload;
char payloadSerial[???];
...
int status = https.POST(payloadSerial);
strncpy(payloadSerial, https.getString().c_str(), sizeof(payloadSerial));
DeserializationError error = deserializeJson(payload, payloadSerial, sizeof(payloadSerial));

```

The documentation for `deserializeJson()` shows that it can accept a `String` directly:

```
DeserializationError deserializeJson(JsonDocument& doc, const String& input);

```

So there's no need to copy `https.getString().c_str()` into `payloadSerial`. You can just pass the `String` that `https.getString()` returns:

```
StaticJsonDocument<128> payload;

int status = https.POST(request_body);

DeserializationError error = deserializeJson(payload, https.getString());

```

You were using the same character array here for both the body of the request that you passed to `POST()` and for deserializing the JSON response. While this is okay, for clarity I changed the `POST` call to use something else as the character array is completely unnecessary for processing the response.

Even if `deserializeJson()` didn't accept a `String` type as an argument, you still wouldn't need to copy the response into a buffer. You could just pass `https.getString().c_str()`:

```
StaticJsonDocument<128> payload;

int status = https.POST(request_body);

DeserializationError error = deserializeJson(payload, https.getString().c_str());

```

You **really** should check the value of `status`. It indicates whether the POST succeeded or not. If it failed, you should report that and the reason for the failure, and not attempt to process the returned payload as there is no returned payload.

---
Tags: esp8266, arduino-mega
---


# Question
Title: Is there a microcontroller that can output hdmi?
Pretty simple question. Is there a microcontroller that can output hdmi? If not, what microcontrollers can output any type of video?

# Answer
It depends on what you are looking for. There are lots o chips made to control and process hdmi frames. However, as Jot said, the arduino is not suitable for this. The arduino can output basic VGA, but it does not have enough "horsepower" to play with HDMI. The best and cheapest solution is to use a Raspberry Pi.
> 1 votes

# Answer
RP2040 can output DVI which HDMI monitors can render.
> 0 votes

---
Tags: electronics
---


title: Using Soft UART - how include library

text:
# Question
Title: Using Soft UART - how include library
I want to use the soft serial communication example.

But when I compile it, it sais:

```
/home/xxx/Arduino/SoftwareSerialExample/aa/aa.ino:28:28: schwerwiegender Fehler: SoftwareSerial.h: Datei oder Verzeichnis nicht gefunden
Kompilierung beendet.
exit status 1
Fehler beim Kompilieren für das Board Arduino Uno.

```

What is going there? I have a directory also with AFSoftSerial.h at /Arduino/libraries/AFSoftSerial/AFSoftSerial

# Answer
Check to make sure you have the line:

```
#include <SoftwareSerial.h>

```

... at the top of your Sketch.

Also, compare your code with that found on the Arduino Software Serial Library web page here.

Finally, make sure your Arduino Application and all your Arduino Libraries are up to date.
> 1 votes

# Answer
> I have a directory also with AFSoftSerial.h at /Arduino/libraries/AFSoftSerial/AFSoftSerial

The code is looking for the "SoftwareSerial" library and that is the library you need include and call, not "AFSoftSerial". Or, if you intend to use AFSoftSerial, then change your code to say that instead.
> 0 votes

# Answer
Download Arduino SoftwareSerial library, extract it and put it into your libraries folder. Libraries folder is in your project folder. If you haven't changed project folder in Preferences, it will be in C:\Users\your\_username\Documents\Arduino. Be careful that there are not two SoftwareSerial folders. Then try to upload your code again.
> -1 votes

---
Tags: library, uart
---


# Question
Title: Can't mount microSD card with Freenove ESP32 WROVER Module and Sparfun MicroSD module
I'm using Freenove's ESP32 WROVER Module with their GPIO expansion board as shown in the image below:

I'm trying to integrate Sparkfun's microSD module in the circuit. Here's my sketch. However, I'm unable to mount the card despite it works fine using an ESP32-CAM board with integrated SD card reader.

Any clues on what I'm doing wrong?

# Answer
> 0 votes
Your pinout to the SD is unclear from the picture, but I can see that you are using **pin 15**, which is the MTDO strapping pin- which will cause issues for sure.

You can learn more here about using alternative pins here:
https://randomnerdtutorials.com/esp32-spi-communication-arduino/

---
Tags: esp32
---


# Question
Title: A fatal error occurred: Failed to connect to ESP32: Wrong boot mode detected (0x13)! The chip needs to be in download mode. [upload] Error 2
I have seen so many people complain about this same error and they were given a multitude of answers to help with this error, but nothing so far has worked for me.

Everything was working fine until I upgraded to Win 11 and the latest version of VS Code. I also attempted uploading with the Arduino IDE and no success. I'm at the point of throwing the ESP32 boards into a box, and moving onto an alternative until someone comes up with a different solution.

This is my failed punch list gathered from the many postings about this error:

1. Followed these instructions: https://docs.espressif.com/projects/esptool/en/latest/troubleshooting.html without success.
2. Removed and Re-installed the CP210x & CH340 (ESP32-CAM Programming Board) Windows Drivers
3. Tried both VS Code & Arduino IDE with Ubuntu on two different computers.
4. For Ubuntu, I added "User" to dialout.
5. Pressed IO0 & RST to force the ESP32 into Boot Mode.
6. Verified USB cables were data cables.
7. Tested 6 ESP32 Dev Kit boards to make sure I didn't have a bad one.
8. Soldered a 10 uF capacitor across the EN pin and GND
9. Added: monitor\_dtr = 0 & monitor\_rts = 0 to platformio.ini
10. The two different Boards ESP32 DEV Kit & ESP32-CAM Boards, both appear in Device Manager.
11. Attempted to upload the code in Win 10, and had the same results.

I'm a beginner with this technology, so please keep this in mind when you answer my question. Thanks,in advance, to anyone who can help me.

# Answer
> 2 votes
I purchased a **NodeMCU** clone **ESP32** board and encountered this error.

> A fatal error occurred: Failed to connect to ESP32: Wrong boot mode detected (0x13)! The chip needs to be in download mode. \[upload\] Error 2

There were 2 separate problems, and I was stumped by their combined effect:

1. Normally such boards automatically go into program upload mode using the RTS/CTS pins on the USB serial. This self-resetting mechanism did not work on my board. I had to manually press the BOOT button on GPIO0 in order to upload code.
2. I guessed the above problem correctly, but there was an additional quirk: ESPTool sends a RESET command just before uploading the code. So you have to press the BOOT button *when you see the message 'Connecting..' on the Arduino IDE*. Normally we will hold the BOOT button and press reset in order to put the board in boot mode. This did not work with this board. Pressing the button at the time of power up/ connecting the USB cable etc. all failed. You have to press the BOOT button at the right time!

In addition to the Arduino IDE, I observed the same behavior with other tools like Tasmotizer. In all cases, the solution was the same.

---
Tags: esp32, error, upload
---


# Question
Title: 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

# Answer
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
> 0 votes

# Answer
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.
> 0 votes

---
Tags: esp32, voltage, stepper-motor
---


# Question
Title: How to turn off or stop Access Point network in ESP8266?
I've created a code for ESP8266 12E with Arduino IDE, in which it'll operate as "**Station Mode**" or "**Access Point Mode**" on Wifi, depending on the situation. Everything works fine except when device was configured as Access Point, even when I turn off device and then turn on again and force the Wifi initialization as "Station Mode", the Access Point network stays active.

Example: Let's suppose that I turned on the ESP8266 and initialized the Wifi as Access Point, and named the wifi network as "MY\_WIFI\_TEST". Let's assume now that I turned off the ESP8266 and forced it to turn on as "Station Mode". The ESP8266 typically connects to my network (the network of my gateway router 192.168.1.1), but keeps the network "MY\_WIFI\_TEST" active (the prior network as access point). You can not connect to this network, but it remains active.

How can I turn off or stop Access Point network?

My test code:

```
    #include <ESP8266WiFi.h>

    bool access_point_init(){
        // Access Point Mode

       Serial.begin(115200);
       IPAddress ip(192,168,1,254);
       IPAddress gateway(192,168,1,1);
       IPAddress subnet(255,255,255,0);
       char* ssid     = "myssidname";
       char* password = "12345678";

       WiFi.softAPConfig(ip, gateway, subnet);
       bool ret = WiFi.softAP(ssid, password);

       return ret;
    }

    void wifi_station_init(){

        // Station Mode
        Serial.begin(115200);
       Serial.printf("\n");

       WiFi.begin(net_ssid, net_pwd_ssid);

       IPAddress ip(192,168,1,10);
       IPAddress gateway(192,168,1,1);
       IPAddress subnet(255,255,255,0);

        WiFi.config(ip, gateway, subnet);

       k = 0;
       while ((WiFi.status() != WL_CONNECTED) && (k < 80)){
          delay(250);
          Serial.print('.');
          k++;
       }

       Serial.printf("\n");
       Serial.printf("IP address: ");
       Serial.println(WiFi.localIP());
    }

    void setup()
    {
        bool my_condition = false;
        //...
        // my_condition = myLoadFunction();
        //...

       if (my_condition) {
            access_point_init();
       } else {
          wifi_station_init();
       }
    }

```

# Answer
I've already solved, by using a function of the library Wifi, specific for the connections in "Access Point" mode:

```
WiFi.softAPdisconnect (true);

```

Reference: softapdisconnect
> 7 votes

# Answer
I fixed this by adding below command before starting the accesspoint.

`WiFi.mode(WIFI_AP);`
> 3 votes

# Answer
I was trying to turn off the softAP in the new Arduino Uno R4 Wifi so I could rename it and restart it. I put a changing sensor reading in AP name so I can see the value of it by just doing a network scan without actually connecting to it.

The wifi.h lib for UNO R4 doesn't implement SOFTAPDISCONNECT. In the example AP\_SIMPLEWEB server I found adding the following function shuts down the AP and allows restarting with a different name.

```
void endAccessPoint() {
  using namespace std;
  string res = "";
  modem.begin();
  modem.write(string(PROMPT(_DISCONNECTSOFTAP)),res,"%s%d\r\n" ,CMD_WRITE(_DISCONNECTSOFTAP),1);
}

```
> 1 votes

---
Tags: esp8266, wifi
---


# Question
Title: How to remove Arduino Due and Mega shields without bending pins?
What's your suggested technique for reliably removing Arduino Due and Mega shields while minimizing the chance of bending the strip header pins?

For example, there's a similar discussion here where the asker ended up building a jig to keep everything parallel, but the main PCB was screwed down into the jig (a disadvantage). There is a heap of PCB Pullers/Extractors on the web, but they all seem to relate to edge connected cards.

I'm hoping for multiple answers / techniques. Interested to hear how you do it, or for you to upvote an answer you like. Maybe everybody is just doing the best they can with finger wriggling and manual pin straightening?

# Answer
> 0 votes
I think I've found a nearly perfect tool in Knipex 45 10 170 reverse pliers. The only downside I can currently see is that they're conductive. The (unmodified) wooden clothes peg idea I found did not have enough grip or leverage.

# Answer
> 3 votes
You could modify a couple of wooden clothes pegs to act as reverse pliers.

<sub>(source: niceshops.com)</sub>

# Answer
> 2 votes
Here's the easiest solution. Spend $10 on Amazon and buy one of these "hose pliers". Put the tips on the double pin end. Gently squeeze. Simple!

https://www.amazon.com/dp/B07G5QSQFQ?ref\_=cm\_sw\_r\_apan\_dp\_Q2FM8GDW6EPGVSNA5XDZ\_1

# Answer
> 1 votes
It's an indirect answer to my original question, but having made a number of Due/Mega shields over the year or so since then, I've started making the side pins ~3mm longer than the double row end pins. This helps.

# Answer
> 0 votes
@Majenko's comment suggesting using a toothbrush handle as a lever reminded me of auto trim levers. I remembered I had some, and have done some quick testing. They give a little more strength I would say, but not much (if any) more control than using fingers.

---
Tags: arduino-mega, arduino-due, shields
---


title: DS18B20 Error in Proteus 8.13

text:
# Question
Title: DS18B20 Error in Proteus 8.13
I am using the below code to check temperatures from 36 DS18B20 sensors using Arduino Mega 2560. If any one of them go above 50 deg. celsius, then it sets the output pin to HIGH.

I am trying to run the code on Proteus 8.13, but during the same run, sometimes the virtual terminal prints -127 deg. celsius for all, sometimes right for some sensors and wrong for the other ones (usually the wrong value is also 85 deg. celsius). Is it something wrong with the simulator, or my code?

```
    #include <OneWire.h>
    #include <DallasTemperature.h>

    #define NUM_SENSORS 36
    #define START_PIN 14
    #define OUTPUT_PIN 2

    OneWire oneWire[NUM_SENSORS];
    DallasTemperature sensors[NUM_SENSORS];

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

      for (int i = 0; i < NUM_SENSORS; i++) {
        oneWire[i] = OneWire(START_PIN + i);
        sensors[i] = DallasTemperature(&oneWire[i]);
        sensors[i].begin();
      }

      pinMode(OUTPUT_PIN, OUTPUT);
      digitalWrite(OUTPUT_PIN, LOW);
    }

    void loop() {
      float celsius[NUM_SENSORS];

      for (int i = 0; i < NUM_SENSORS; i++) {
        sensors[i].requestTemperatures();
        celsius[i] = sensors[i].getTempCByIndex(0);
      }

      bool aboveThreshold = false;

      for (int i = 0; i < NUM_SENSORS; i++) {
        if (celsius[i] > 50.0) {
          aboveThreshold = true;
          break;
        }
      }

      digitalWrite(OUTPUT_PIN, aboveThreshold);

      printSensorData(celsius);

      delay(1000);
    }

    void printSensorData(float celsius[]) {
      for (int i = 0; i < NUM_SENSORS; i++) {
        Serial.print("Sensor ");
        Serial.print(i + 1);
        Serial.print(": ");
        Serial.print(celsius[i]);
        Serial.print(" C  ");
        Serial.print(sensors[i].toFahrenheit(celsius[i]));
        Serial.println(" F");
      }
    }

```

# Answer
The -127 indicates a fault on the hardware side, generally an open circuit. Also it sounds like your pull up resistor is not installed or way out of range.For the Mega. UNO and other 5V units 4.7K is a good size and 3.3K for the 3V3 systems. Note the resistor goes from VCC to the sensor output.
> 0 votes

---
Tags: arduino-mega, ds18b20
---


# Question
Title: Arduino Nano TX and RX LEDs Not Lighting Up During Upload
I'm encountering a problem with my Arduino Nano board. When I attempt to upload sketches to the board using the Arduino IDE, only the Power LED lights up, and the TX and RX LEDs remain inactive. I've tried several troubleshooting steps, including reinstalling drivers, using different USB cables, and trying different USB ports on my computer. Despite these efforts, I haven't been able to resolve the issue.

Board Details:

* Arduino Nano with ATmega microcontroller
* Power LED is lit when the board is connected
* "L" LED blinks rapidly during upload
* TX and RX LEDs are not lighting up during upload

Troubleshooting Steps Taken:

* Reinstalled Arduino IDE and drivers
* Tried multiple USB cables and ports
* Verified COM port selection in Arduino IDE
* Checked USB-Serial converter chip for damage

I'm reaching out to the community for help and guidance. Has anyone else encountered this issue? What further steps should I take to diagnose and resolve this problem? Any insights or suggestions would be greatly appreciated.

# Answer
> 1 votes
They many times will not light because of the bit pattern being sent and the short time the bit is active to light the LED. If it is uploading code without errors you are good to go. Quick test, If not try another Arduino and see if it uploads or not. If not it is your computer or a bad cable otherwise it is a bad Arduino.

---
Tags: arduino-uno, sensors, servo
---


title: How to clear heap memory in ESP32?

text:
# Question
Title: How to clear heap memory in ESP32?
I am using Free RTOS on ESP32 in my program. However at some point of time when I execute `xTaskCreate()` it returns -1 , the error being could\_not\_allocate\_required\_memory. In my program, each time I pring `getFreeHeap()` it is reduced by 2,000 approximately and is never cleared or reset. When it is not sufficient or below 2,000 xTaskCreate returns -1.

After reading a lot of forums I could not find a way to clear the memory to create a task. Can anyone guide me with this?

**code snippet**

```
void createTsk(){
  SerialDebug.print("available Heap size: ");
  SerialDebug.println(ESP.getFreeHeap());

  BaseType_t xBy = xTaskCreate(taskPriorityOne, "TaskOne", 20240, NULL, 1, &thOne);
  SerialDebug.println("Return Val : ");
  SerialDebug.println(xBy);
}

void taskPriorityOne(void *paramter)
{
   SerialDebug.println("Prio 1 task Initiated");
   threadTask(priorityOneQue, "task1", thOne);
}

void threadTask(QueueHandle_t priorityQue, String taskName, TaskHandle_t th)
{
  xQueueReceive(priorityQue, &taskdataholder, portMAX_DELAY);
  ongoingProcess = taskdataholder;
  furtherExecutionHttp(taskdataholder, fnm, taskName, th);
}

void furtherExecutionHttp(DataHolder *taskdataholder, String fnm, String
taskName, TaskHandle_t th)
{
   String response = httpRequest(taskdataholder->protocol, taskdataholder-
   >host, taskdataholder->port, taskdataholder->url, taskdataholder->body,
   fnm);

  delay(10);

  free(taskdataholder);
  SerialDebug.println("Releasing memory..\n");

  vTaskDelete(th);
}

```

# Answer
The heap memory in ESP32 cannot be cleared explicitly. The heap memory is used to store dynamically allocated objects, and when an object is no longer needed, it is automatically deallocated by the garbage collector.

You can free up some heap memory by deleting unused objects. In your code, you create a new object called **taskdataholder** in the **furtherExecutionHttp()** function. This object is allocated on the heap and will only be deallocated once the function returns. If you want to free up this memory, you can call the **free()** function before the function returns.
> 2 votes

# Answer
You probably don't want to "clear" the heap, assuming you mean either deallocating or zeroing all memory that you've allocated from the heap.

If you simply return all memory to the heap when you run out, your code may have pointers to that memory remaining when that memory gets allocated to another use, meaning some data will likely get over-written. Or, if you clear the heap (by zeroing it) you will be over-writing data already stored there, and possibly still be unable to allocate more memory if the allocator doesn't "know" that you meant to return it.

Instead, your code should free each memory allocation as soon as it is no longer useful, and make sure its pointer to that memory won't be used again. One way to protect re-use of dead pointers is 1) zero them when you deallocate the memory they point to; and 2) always test for a valid pointer (non-zero) before you try to use it.
> 0 votes

---
Tags: arduino-ide, esp32, memory-usage, memory, espressif
---


# Question
Title: How to reduce noise when using a load cell amplifier's 80 Hz mode?
I have four HX711s load cell amplifiers and each one reads one load cell. I was using the 10 Hz mode, however, this was making my application very slow, as I needed to take five readings and take the average.

When I put the 15 RATE in 1 there is a lot of noise, despite having sped up the reading of the weights; sometimes the variation is up to 3 digits at the end.

See the code for reading the modules where I already show the weights in kg:

```
n = 6;

for (int x=0; x<n; x++) {
  v1[x] = CELL1.read();
  v2[x] = CELL2.read();
  v3[x] = CELL3.read();
  v4[x] = CELL4.read();
}

v1m = 0;
v2m = 0;
v3m = 0;
v4m = 0;

for (int x=1; x<n; x++) { // sum of array
  v1m = v1m+v1[x];
  v2m = v2m+v2[x];
  v3m = v3m+v3[x];
  v4mv= v4m+v4[x];
}

// mean array
v1m = v1m/(n-1);
v2m = v2m/(n-1);
v3m = v3m/(n-1);
v4m = v4m/(n-1);

p1 = p;
p = ((v1m-v10)/(M[1]) + (v2m-v20)/(M[2]) + (v3m-v30)/(M[3]) + (v4m-v40)/(M[4]))/2.5; // show the weight in kg
p = p*o.7+p1*0.3; // convert to kg
// ... i print the p (weight in kg) now...

```

# Answer
I had a very similar problem with 4 load cells. I ran 10,000+ readings at 80Hz, copied the serial monitor into MS Word to find my string (text) value labels and replace them with nothing. This lets me keep the numbers. If you copy that into Excel and make a scatter plot graph you can see where your highs and lows are and their magnitudes. I was able to simply write an IF condition to reject those outliers. Interestingly the outliers are very large (positive or negative) and they weren't just random values. They were also occurring at a specific frequency that may have more to do with my application rather than being an element to your solution.
> 1 votes

---
Tags: arduino-uno, adc
---


# Question
Title: Error while trying to connect CH341 driver
I'm trying to connect an Arduino board to IDE on Ubuntu, and I have the following driver log:

```
[  543.412356] usb 1-2: USB disconnect, device number 3
[  549.593729] usb 1-2: new full-speed USB device number 7 using xhci_hcd
[  549.748438] usb 1-2: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.54
[  549.748449] usb 1-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  549.748454] usb 1-2: Product: USB2.0-Serial
[  549.750234] ch341 1-2:1.0: ch341-uart converter detected
[  549.750859] usb 1-2: ch341-uart converter now attached to ttyUSB0
[  550.347356] input: BRLTTY 6.4 Linux Screen Driver Keyboard as /devices/virtual/input/input20
[  550.462814] usb 1-2: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
[  550.463418] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[  550.463437] ch341 1-2:1.0: device disconnected

```

As a result no ports are found, any suggestion?

# Answer
Solved, thanks to this \[article\]\[1\]

```
sudo apt autoremove brltty

```

remove the conflict and now the board is visible \[1\]: https://0xsuk.github.io/posts/2022-07-19-how-to-install-ch340-on-ubuntu-22.04/
> 0 votes

---
Tags: linux, ubuntu, ch340
---


# Question
Title: Timer interrupt setup for one second is too slow (~ 4 seconds)
I am trying to use the timer interrupt on an Arduion Uno.

Here is a imple example code for displaying a progressive digit on a lcd display, which is updated with timer interupt every second:

```
#include <LCD_I2C.h>

LCD_I2C lcd(0x27);
volatile bool timerFlag = false; // Timer-Flag (timer-Interrupt)
int displayWidth = 16; // display width
int digit = 0; // current digit

void setup() {
  lcd.begin();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Initializing...");

  noInterrupts();
  TCCR1A = 0;
  TCCR1B = (1 << CS12) | (1 << CS10); // set Prescaler to 1024
  TCNT1 = 0;
  OCR1A = 15624; // should be 1 second with a prescaler of 102
  TIMSK1 |= (1 << OCIE1A); // Enable timer interrupt
  interrupts();
}

ISR(TIMER1_COMPA_vect) {
  timerFlag = true;
}

void loop() {
  static int position = 0;
  char displayString[17]; // +1 null termination

  if (timerFlag) {
    lcd.clear(); // clear display

    // update digit and progress
    digit = (digit + 1) % 10;
    position = (position + 1) % (displayWidth + 1);
    memset(displayString, ' ', displayWidth);
    displayString[displayWidth] = '\0'; add null termination
    displayString[position] = '0' + digit; // Character for the current digit

    // Show updated progress on the display
    lcd.setCursor(0, 1);
    lcd.print(displayString);

    timerFlag = false;
  }
}

```

The values for setting up he inteupt timer 1 for 1 second is arround everywhere. BUt the updates generated by this code is clearly much slower than 1 second, it's more about 4 seconds. So i did a comparison with a delay based version of the same example:

```
#include <LCD_I2C.h>

LCD_I2C lcd(0x27);
int displayWidth = 16; // display width

void setup() {
  lcd.begin();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Initializing...");
}

void loop() {
  for (int digit = 0; digit < 10; digit++) {
    char displayString[17]; // +1 null termination
    int position = digit % (displayWidth + 1);

    // Update progression
    memset(displayString, ' ', displayWidth);
    displayString[displayWidth] = '\0'; // add null termination
    displayString[position] = '0' + digit; // Character for the current digit

    // Show updated progress on the display
    lcd.clear(); // Clear display
    lcd.setCursor(0, 1);
    lcd.print(displayString);

    delay(1000);
  }
}

```

This one works as expected and updates every second.

So what is wrong with my interrupt settings?

# Answer
> 3 votes
There is a flag in `TCCR1A/B` called `WGM12` which sets the `wave generation mode (WGM)` to `Clear Timer on Compare Match (CTC)`. This causes the timer to count up to the value in OCR1A and then automatically reset to 0.

This flag was forgotten, so the interrupt simply ignores the setting `OCR1A = 15624;` and counts through to 65535, which corresponds to the observed factor of about 4. Therefore the setting line for TCCR1B must be changed to

```
TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);
// Set CTC mode and set Prescaler to 1024

```

Now the interrupt is triggered correctly every second.

# Answer
> 2 votes
It is ignoring this `OCR1A = 15624;` and simply rolling over at 65535 instead., hence the error factor of 4. You have to set the wave generation mode as CTC in registers TCCR1A/B.

---
Tags: arduino-uno, interrupt
---


title: Using SPI on Pi Pico, Arduino IDE

text:
# Question
Title: Using SPI on Pi Pico, Arduino IDE
Beginner with the Pi Pico here, but I studied electronics engineering and am reasonably hardware literate. I've used mbed online for a project prior to covid.

I want to use SPI to connect to a display using the ILI9488, (480 x 320 TFT panel), however, I cannot see how or where I would define SPI pins, and my understanding is that using SPI.h would default to Arduino pinouts - the uno etc being pin incompatible with the pi pico.

Do I need to trudge through the SPI.h file to try to work out how I set the pins manually? Or am I barking up the wrong tree?

I am using macOS, Arduino IDE 2.1.1 and have no issues connecting to the pico W. Please ask for any other clarification, I can provide a schematic of my design if it makes things easier. Love the pico but am finding it hard to use with C/C++.

Thanks, KL

# Answer
You can read the actual SPI pins with the following sketch

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

    void loop() {
      Serial.print("MOSI: ");
      Serial.println(MOSI);
      Serial.print("MISO: ");
      Serial.println(MISO);
      Serial.print(" SCK: ");
      Serial.println(SCK);
      Serial.print("  SS: ");
      Serial.println(SS);
      Serial.println();
      delay(5000);
    }

```

As Juraj wrote, they are defined in the board files.

I have no experience with your ILI9488 display and the corresponding library. Many libraries allow you to use software defined pins. I would not recommend that, especially for a display with 480 x 320 pixels. You really need the speed of the hardware SPI.
> 2 votes

---
Tags: spi, raspberrypi-pico
---


# Question
Title: How to use Interrupt in Arduino to receive the data from Serial Input
Currently i have a project that forced me to make a program that receives several data from Serial Input using Interrupt in Arduino. I use Arduino as the receiver and ESP32 as the sender through Hardware Serial. The program i have written for Arduino is as posted at Serial Input Basics with a few changes as written below :

```
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
char messageFromPC[numChars] = {0};
unsigned long sendDataPrevMillis = 0;
int controlCondition = 0;
int droneCondition = 0;
int gasValue = 0;
int pitchValue = 0;
int rollValue = 0;
int yawValue = 0;

boolean newData = false;

void setup() {
  attachInterrupt(digitalPinToInterrupt(1), handleInterrupt, RISING);
  Serial.begin(57600);
}

void loop() {

  Serial.print("Control Condition :");
  Serial.print(controlCondition);
  Serial.print(" Drone Condition :");
  Serial.print(droneCondition);
  Serial.print(" Roll:");
  if(rollValue < 1500)Serial.print("<<<");
  else if(rollValue > 1500)Serial.print(">>>");
  else Serial.print("-+-");
  Serial.print(rollValue);
  Serial.print("  Pitch:");
  if(pitchValue > 1500)Serial.print("^^^");
  else if(pitchValue < 1500)Serial.print("vvv");
  else Serial.print("-+-");
  Serial.print(pitchValue);

  Serial.print("  Gas:");
  if(gasValue < 1500)Serial.print("vvv");
  else if(gasValue > 1500)Serial.print("^^^");
  else Serial.print("-+-");
  Serial.print(gasValue);

  Serial.print("  Yaw:");
  if(yawValue < 1500)Serial.print("<<<");
  else if(yawValue > 1500)Serial.print(">>>");
  else Serial.print("-+-");
  Serial.println(yawValue);
}

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

    while (Serial.available() && newData == false) {
        rc = Serial.read();

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

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
    if (newData == true) {

    strcpy(tempChars, receivedChars);
    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars, ",");
    controlCondition = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    droneCondition = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    gasValue = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    pitchValue = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    rollValue = atoi(strtokIndx);

    strtokIndx = strtok(NULL, ",");
    yawValue = atoi(strtokIndx);

    newData = false;
    }
}

```

The data will be sent from ESP32 to change the values of `controlCondition`, `droneCondition`, `gasValue`, `pitchValue`, `rollValue`, and `yawValue`.

I have tried it and the Interrupt cannot be triggered. The Interrupt should be triggered whenever the `controlCondition`, `droneCondition`, `gasValue`, `pitchValue`, `rollValue`, or `yawValue` change its value. Any idea what should I do? or is there something wrong with my code?

Note that the code that i showed in the `void loop()` is just an example code. The real code is more complex with so many calculations involved. The variables that I mentioned are the important variables for the calculations.

# Answer
> 2 votes
Why do you want to use an interrupt anyway? The serial hardware already generates an interrupt, and inside that ISR the incoming byte is placed into a buffer.

I presume you have a main loop where you are doing other stuff, and you want to react when some interesting serial data arrives.

I have an example of processing serial data without blocking on my page about serial processing which I reproduce below:

```
/*
Example of processing incoming serial data without blocking.

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

Released for public use.
*/

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

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

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

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

  switch (inByte)
    {

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

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

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

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

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

    }  // end of switch

  } // end of processIncomingByte

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

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

  }  // end of loop

```

It looks to me like you are looking for an "end marker" which is when you want to react to what you have received earlier. Like in my example above, you could just pick up individual bytes in the main loop, and when the end marker arrives the whole line can be processed. I used a newline for and end marker, but you could change that to '\>'.

---

The problems with an interrupt like you are doing are:

* The interrupt will fire on the first bit (out of 10) and so there won't be any serial data yet, and your program will uselessly look for serial data which won't be there.
* You are calling Serial.read() which won't return anything because while you are in **your** ISR the main serial ISR won't be able to fire.
* Your ISR is doing too much.
* Serial line is normally HIGH, and transitions to LOW (the start bit) when the byte starts, so you should be looking for FALLING and not RISING.

---

I strongly suggest you rework to just check for serial available in the main loop, as I have done, and process it when the end delimiter arrives.

# Answer
> 0 votes
Don't do anything in your `loop()` function *except* calling other functions, each of which decides - for one part of your process - whether or not it is time to do that part. If so, do that part; if not, return immediately to the loop function.

Read my answer to a similar question that talks more about how to do this. This technique is called non-blocking programming. Your code should poll rapidly for whatever it might need to respond to, but should not wait for any of those things to occur. If you do that, you will likely not need the kind of response that would require interrupts.

Also, the print statements in your `loop()` will slow down (block) execution and may keep your PID from responding adequately. If you need them for debugging your calculations, you can wrap them in `#if DEBUG` ... `#endif` statements so one `#define DEBUG` can easily include them them when you need to (knowing that your device control will be affected) and remove them for operational tests. If you must keep some print statements live, make only as few as necessary live at one time, make sure to use the highest baud-rate possible, and keep them as brief as possible.

---
Tags: arduino-ide, interrupt, c
---


title: Control esp32 via keyboard keys

text:
# Question
Title: Control esp32 via keyboard keys
I'm making a project in which I have to control a mini car and get sensor information via bluetooth. I'd like to be able to control the mini car with the computers keyboard (w,a,s,d), but I was not able to find a library that could help with that, like the "keyboard" library does in python for example

Ex.

```
import keyboard

# when w is pressed, the car goes forward

If (keyboard.is_pressed("w"):

    Forward()

```

The "keyboard" library in arduino does not seem to work the same way. And I didn't find any other libraries nor tutorials about it online.

How to make it work?

# Answer
> 2 votes
In case someone is trying to do the same, I came up with a way to make it work. In ArduinoIDE, after the setup, the loop checks if the bluetooth serial is available and has received anything, if it receives the right variables for movement, it passes the instruction to the motors connected to the Arduino through an l298n module.

The code is as follows:

```
// variáveis para conexão bluetooth // variables for bluetooth connection
#include <SoftwareSerial.h>

SoftwareSerial SerialBT(8, 9);
char valorDoBluetooth;

//variáveis para o uso dos motores // variables for the use of motors
// motor 1
const byte in1 = 2;
const byte in2 = 4;
const byte enA = 3;
//motor 2
const byte in3 = 5;
const byte in4 = 7;
const byte enB = 6;

int velocidade = 100; // motor speed (up to 255)

int componentesOut[6] = { in1, in2, enA, in3, in4, enB }; // list created to setup the variables more easily

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

  // loop to set pins to Output
  for (int n = 0; n < 6; n++) {
    pinMode(componentesOut[n], OUTPUT);
  }
}

void loop() {
  // Read data from the Bluetooth module
  if (SerialBT.available()) {
    valorDoBluetooth = SerialBT.read(); // bluetooth Value

    if (valorDoBluetooth == 'F' || valorDoBluetooth == 'T' || valorDoBluetooth == 'D' || valorDoBluetooth == 'E' || valorDoBluetooth == 'P')  // if SerialBt recieved movement value
    {
      movimento(); // movement
    }
  }
}

void movimento() {
  if (valorDoBluetooth == 'F') {
    Serial.println("Frente");  // Forward
    frente();
  } else if (valorDoBluetooth == 'T') {
    Serial.println("Trás");  // Backwards
    tras();
  } else if (valorDoBluetooth == 'D') {
    Serial.println("Direita");  // Right
    direita();
  } else if (valorDoBluetooth == 'E') {
    Serial.println("Esquerda");  // Left
    esquerda();
  } else if (valorDoBluetooth == 'P') {
    Serial.println("Parar");  // Stop
    parar();
  }
  delay(1);
}

void frente() {
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  digitalWrite(enB, velocidade);
}
void tras() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  digitalWrite(enB, velocidade);
}
void direita() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  digitalWrite(enB, velocidade);
}
void esquerda() {
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  digitalWrite(enB, velocidade);
}
void parar() {
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);
  digitalWrite(enA, velocidade);
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
  digitalWrite(enB, velocidade);
}

```

To be able to control it via the PC keyboards, I connected the PC to the device through bluetooth, then see which COM it is connected to in bluetooth configurations of control panel, and use this the COM number on a Python code that's able to communicate with the device.

The Python code is as follows:

```
import serial
import time
import keyboard

# Replace 'COMX' with the actual COM port assigned to the HC-05 module / Esp device on your PC. More info at https://pyserial.readthedocs.io/en/latest/shortintro.html
ser = serial.Serial('COM8', 9600, timeout=1)

flagMovido = True # flag that checks if the motors are finished moving before changing directions

def controle(event):
    global flagMovido

    if event.event_type == keyboard.KEY_DOWN: # if a key is pressed:
        if (event.name == "w" or event.name == "a" or event.name == "s" or event.name == "d") and flagMovido: # if movement keys are pressed and motors are finished moving to any other direction:
            flagMovido = False # motors started moving

            if event.name == "w" and not flagMovido:
                ser.write(b'F')

                print('frente') # Forward

            elif event.name == "a" and not flagMovido:
                ser.write(b'E')

                print('esquerda') # Left

            elif event.name == "s" and not flagMovido:
                ser.write(b'T')

                print('trás') # Backwards

            elif event.name == "d" and not flagMovido:
                ser.write(b'D')

                print('direita') # Right

    elif event.event_type == keyboard.KEY_UP: # if a key is released:
        if (event.name == "w" or event.name == "a" or event.name == "s" or event.name == "d") and not flagMovido: # if movement keys are released and motors are moving to some direction

            flagMovido = True # motors are finished moving

            ser.write(b'P')

            print('parado') # Stop

print('START')

def main():
    while True:
        data = ser.readline().decode().strip()

        keyboard.hook(controle)
        time.sleep(.001)

        if data:
            print(f"Recebido: {data}") # prints data if any received. Used to print the sensor values received.

if __name__ == "__main__":
    main()

```

obs:

* The code runs fine, but may present some problems if you press to many keys at a time, since it was made to handle one direction at a time. But the movement bools will help with that and prevents it from happening to certain extent. Though in specific cases is should be improved.
* I ended up using a HC05 module with Arduino, but the code also woks for Esp. But if connecting to an Esp, the `ser = serial.Serial('COM8', 9600, timeout=1)` line should be changed to the way it connects to the Esp. More info at the link provided.

---
Tags: arduino-uno, esp32, bluetooth, hc-05
---


# Question
Title: Make my Arduino (Mega or whatever is better for the task) to be able to read and write `Serial` data to a **rj45** port
I have a Chinese hybrid solar inverter that exposes an **rj45 input** which talks the serial protocol (Baud rate 2400, no parity, 8 bits, 1 stop bit). I need my Arduino (say, Mega or whatever, does not really matter) to talk to it. What would be the best option to connect an Arduino board to the rj45 input such that it would be available as `Serial` in the code?

Basically, I'd like the following piece to code to "just work":

```
    uint8_t query[] = {81, 80, 73, 71, 83, 183, 169, 13};
    Serial.write(query, sizeof(query)); // Write some bytes to a device, i.e. send a request.
    Serial.flush();

    while (!Serial.available()); // Wait for device to reply.
    String str = Serial.readString();
    // do someting with `str`...

```

In other words, I am looking for a hardware solution to connect my Arduino board to the rj45 input without introducing an unnecessary complication (if any).

# Answer
Look up the data sheet for the max232. It is an old chip that does what you need. ARDUINOs serial work at 0 to 5v and the old fashioned standard for serial data works at +-12v. Also, there will be a high low inversion.
> 1 votes

---
Tags: serial, convert
---


title: Lilypad sends corrupted data on Serial

text:
# Question
Title: Lilypad sends corrupted data on Serial
I have an Arduino Lilypad with this simple code where I try to write a simple message to the serial console. The baud rate is set to 9600 both in the code as well as in the serial console and I'm using the FTDI UART tool. However, the output I'm receiving is corrupted and I'm not sure what could be the cause. Any ideas or suggestions are welcome. Thanks!

```

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

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(3000);
  Serial.write("Hello World");
}

```

Arduino is connected to the FTDI tool as shown here

# Answer
> 1 votes
It looks like the wrong baud rate. That often results in garbage characters. You said in a comment that halving the baud rate on the Arduino end seemed to synchronize the baud rates, and you could see proper characters.

I'm a bit puzzled by that because you were evidently able to upload the sketch in the first place. Therefore the baud rate was correct during the uploading process.

Looking in the file `boards.txt` which you should find somewhere in your Arduino installation, there appear to be a number of Lilypad variants. Perhaps you inadvertently chose the wrong one in the "Board" menu in the IDE?

It looks like the correct baud rate was used for the uploading, but the code generated by the compiler (because of settings passed by the IDE) thought that the board was running at half the speed it actually was (so it set the baud rate clocks to run faster), so by reducing the baud rate in the Serial.begin they became in sync.

You could just live with the difference, or try experimenting with choosing different Lilypad board types.

If the baud rate is wrong, probably the delays will be wrong too, whether or not that matters is up to you.

---
Tags: serial
---