Esp32&Servos

Ejemplos probados con dos librerias para el uso de servomotres con la placa Esp32.

Las siguientes librerias funcionan perfectamente en estos ejemplos.

  • ESP32Servo.h (https://www.arduino.cc/reference/en/libraries/esp32servo/)
  • ServoESP32 (https://github.com/RoboticsBrno/ServoESP32.git) (Servo.h)

Ejemplo con potenciometro conectado en A0=gpio36

#include <Servo.h>

 Servo servo_15;  // create servo object to control a servo



void setup() {
  servo_15.attach(15);  // attaches the servo on pin 11
servo_15.write(180); 
analogSetPinAttenuation (36,ADC_11db); 
}

void loop() {
  int pos=analogRead(A0);
 pos=map(pos,0,4095,0,180);

  
    servo_15.write(pos);              
    delay(10);                       
  
}
#include <ESP32Servo.h>
 
Servo myservo;  // create servo object to control a servo
// 16 servo objects can be created on the ESP32
 
int pos = 0;    // variable to store the servo position

int servoPin = 15;
 
void setup() {

  // Allow allocation of all timers
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);
  myservo.setPeriodHertz(50);    // standard 50 hz servo
  myservo.attach(servoPin, 500, 2400); // attaches the servo on pin 15 to the servo object
  // using default min/max of 1000us and 2000us
  // different servos may require different min/max settings
  // for an accurate 0 to 180 sweep
 analogSetPinAttenuation (36,ADC_0db); 
   myservo.write(0);

}
 
void loop() {
int val = analogRead(36);            // read the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 4095, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // set the servo position according to the scaled value
                          // wait for the servo to get there
}

En ambos casos hemos utilizado la función analogSetPinAttenuation (.), para entender como funciona y que efectos produce.Según mi experiencia, pongo esta tabla de resultados:

Conexionado Pot, GND y 3v3, y Resolucion por defecto 12 bits( valor 4095) de forma que veremos que ocurre cuando el mando lo giramos hacia 3v3:

AtenuaciónVoltaje para 4095(180º)
ADC_0db1V
ADC_2_5db1.4V
ADC_6db1.92V
ADC_11db3.28V

En función de la atenuación elegida podemos comprobar que si ponemos 0db , al girar el potenciometro poco antes de la mitad de su recorrido habra llegado el servo a 180º, y si ponemos 11 db, el recorrido del potenciometro coincidira con los valores 0-180, o sea que en su mitad de recorrido obtendriamos un posicionamiento de 90º.

Ejemplo con Joystick:

Aqui hay que tener en cuenta que como el Joystick varia en tres valores que serían 0V-1,6V-3,3V, siendo el valor 1,6V la posición central, obligatoriamente hemos de establecer,por seguridad la atenuación en 11db (en 6db tambien funcionaría) que abarca la lectura maxima de 4095 para 3,3V. Si por ejemplo pusieramos 0db, la lectura maxima estaria en 1V y como la posición central esta a 1,6V, el servo quedaria fijo en la posición definida como 180º. El resto de la explicacion es similar a otros casos ya expuestos. No hubiera hecho falta mapear.

#include <ESP32Servo.h>
 
Servo servo_15;  // create servo object to control a servo
// 16 servo objects can be created on the ESP32

 int pos=0;
void setup() {
  servo_15.attach(15);  // attaches the servo on pin 15
servo_15.write(0);
analogSetPinAttenuation (32,ADC_11db);// very important this value
}

void loop() {
  
int val=analogRead(32);
val = map(val, 0, 4095, 0, 180);
  if(val>=160){
     pos= (pos + 1);
    servo_15.write(pos);
    delay(5);
  }
  
    if (pos > 180) {
      pos = 180;
  }
  if(val<=10){
     pos= (pos - 1);
    servo_15.write(pos);
    delay(5);
  }
  
    if (pos < 0) {
      pos = 0;
    }
}

EJEMPLO USO INTERRUPCION PROGRAMADA PARA MOVER UN SERVO CADA 10 SEGUNDOS

El servo tardará 10 segundos en barrer el sector 0-180 y180-0, por eso ponemos un intervalo de 20 segundos. Si abrimos el monitor serie comprobaremos como se imprime los valores de millis() hasta que se interrumpe durante 10 segundos mientras barre el servo su sector.

#include <Servo.h>

 Servo servo_15;  // create servo object to control a servo


int pos;
volatile int interruptCounter;
int totalInterruptCounter;
 hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
 
void IRAM_ATTR onTimer() {
  portENTER_CRITICAL_ISR(&timerMux);
  interruptCounter++;
   
  portEXIT_CRITICAL_ISR(&timerMux); 
 
}
 

 
void setup() {
  Serial.begin(115200);
  
   servo_15.attach(15);
 pos=0;
servo_15.write(pos);
 timer = timerBegin(0, 80, true);
  timerAttachInterrupt(timer, &onTimer, true);
  timerAlarmWrite(timer, 20000000, true);
  timerAlarmEnable(timer);
 
}
 
void loop() {
long t1=millis();
  Serial.println(t1/1000);
  delay(1000);
 if (interruptCounter >0) {
 portENTER_CRITICAL(&timerMux);
    interruptCounter--;
    portEXIT_CRITICAL(&timerMux);
    
 
    totalInterruptCounter++;
    
  for (pos = 0; pos <= 180; pos += 1) { 
    // in steps of 1 degree
    servo_15.write(pos);              
   delay(28);                       
  }
  for (pos = 180; pos >= 0; pos -= 1) { 
   servo_15.write(pos);              
  delay(28);                       
  }
 }     
 }

EJEMPLO del uso de dos temporizadores consecutivos de diferentes intervalos.

#include <Servo.h>

 Servo servo_15;  // create servo object to control a servo
Servo servo_04;

int pos15;
int pos04;
unsigned long t15 = 0;
unsigned long t04=0;
unsigned long pausa15 = 30000;//tiempo de ejecucion cada 20 segundos
 unsigned long pausa04 = 20000;//tiempo de ejecucion cada 10 segundos (primero en moverse)
 
void setup() {
   servo_15.attach(15);
   servo_04.attach(04);
 pos15=0;
 pos04=0;
servo_15.write(pos15);
 servo_04.write(pos04);
 
}
 
void loop() {
  
 
  unsigned long diff15 = millis() - t15;
  unsigned long diff04 = millis() - t04;
 if (diff15 >= pausa15) {
  t15=millis();
  for (pos15 = 0; pos15 <= 180; pos15 += 1) { 
    // in steps of 1 degree
    servo_15.write(pos15);              
   delay(28);                       
  }
  for (pos15 = 180; pos15 >= 0; pos15 -= 1) { 
   servo_15.write(pos15);              
  delay(28);                       
  }
 }
  if (diff04 >= pausa04) {
  t04=millis();
  
  for (pos04 = 0; pos04 <= 180; pos04 += 1) { 
    // in steps of 1 degree
    servo_04.write(pos04);              
   delay(28);                       
  }
  for (pos04 = 180; pos04 >= 0; pos04 -= 1) { 
   servo_04.write(pos04);              
  delay(28);                       
  }
  }
}

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Translate »