martes, 24 de febrero de 2026

REVIEW

 Aquí tienes un repaso detallado sobre el controlador PCA9685, ideal para prepararte para tu evaluación:

1. ¿Qué es la PCA9685?

Es un controlador de 16 canales que permite manejar múltiples servomotores o LEDs utilizando solo dos pines del microcontrolador (como Arduino o ESP32). Se comunica mediante el protocolo I2C, lo que ahorra muchos pines de salida y descarga al procesador principal de la tarea de generar señales en tiempo real.

2. ¿Cómo se usa para controlar servos?

  • Conexión I2C: Se conecta a los pines SDA y SCL del microcontrolador.

  • Alimentación Externa: Los servos consumen mucha corriente, por lo que la PCA9685 tiene una bornera (normalmente azul) para conectar una fuente externa (ej. 5V o 6V). No se deben alimentar los servos directamente desde el Arduino.

  • Librerías: Generalmente se utiliza la librería de Adafruit (Adafruit_PWMServoDriver), que permite enviar comandos simples para posicionar cada servo de forma independiente.

3. Puertos de la PCA9685

La placa está organizada de la siguiente manera:

  • Pines de Control (I2C): VCC, V+, SDA, SCL, GND y OE (Output Enable, para apagar todas las salidas).

  • Canales de Salida (0 al 15): Tiene 16 grupos de 3 pines. Cada grupo tiene:

    1. PWM (Amarillo/Blanco): La señal de control.

    2. V+ (Rojo): Alimentación positiva para el servo.

    3. GND (Negro/Marrón): Tierra.

  • Puente de Direcciones: Pequeños pads de soldadura para cambiar la dirección I2C y conectar hasta 62 placas en cascada.

4. ¿Qué es una señal PWM?

PWM (Pulse Width Modulation) o Modulación por Ancho de Pulso, es una técnica que consiste en variar el tiempo que una señal eléctrica está en estado "alto" (encendido) dentro de un ciclo constante.

  • En los servos, no importa el voltaje promedio, sino la duración exacta del pulso en milisegundos, ya que esto le indica al servo en qué ángulo posicionarse (por ejemplo, 1ms para 0°, 1.5ms para 90° y 2ms para 180°).

5. Pulso Mínimo y Máximo

En la programación de la PCA9685 (que tiene una resolución de 12 bits, es decir, valores de 0 a 4095):

  • PULSO_MIN: Es el valor numérico que corresponde al tiempo mínimo (usualmente 0°). Suele estar cerca de 150.

  • PULSO_MAX: Es el valor que corresponde al tiempo máximo (usualmente 180°). Suele estar cerca de 600.

6. Significado de const int PULSO_MAX = 600;

Según el estándar de programación para estos controladores:

  • Significado: Este número representa la longitud del pulso para la posición máxima del servomotor.

  • En el contexto del código: Indica el valor de "conteo" (ticks) en el que la señal PWM debe bajar a 0 para que el servo alcance su ángulo máximo (180°). Si el comentario dice algo como "Valor de pulso para 180 grados", ese es el significado exacto: definir el límite superior del recorrido del servo para evitar que intente girar más allá de su capacidad física y se dañe.

Resumen para tu examen:

  • PCA9685: 16 canales, I2C, 12 bits de resolución.

  • PWM: Control por duración de pulso.

  • 600: El valor máximo de la señal para llegar al tope de giro (180°).

viernes, 20 de febrero de 2026

OPEN LOOP SYSTEM

 /*

 * PROYECTO: Genios Solucionadores - Grado 8 GBCMC
 * OBJETIVO: Sistema de Control Automático de Luz (Lazo Cerrado)
 * EXPLICACIÓN: El ESP32 actúa como un "cerebro" que ajusta un LED
 * dependiendo de cuánta luz detecta su "ojo" (el sensor LDR).
 */

// --- PINES (¿Dónde conectamos las cosas?) ---
const int PIN_FOTORESISTENCIA = 34; // Pin donde el sensor envía su información
const int PIN_LED_PWM = 33;         // Pin donde enviamos energía al LED

// --- PARÁMETROS DE CONTROL (Las reglas del juego) ---
const int SETPOINT = 2000;          // La cantidad de luz ideal que queremos tener
const float reactionStrength = 0.3; // Qué tan rápido reacciona el sistema (como el acelerador)

// --- VARIABLES ---
float ledBrillo = 0; // Aquí guardamos el nivel de brillo actual (0 a 1023)

// Configuración de la "señal de energía" para el LED
const int freq = 5000;     // Qué tan rápido parpadea la señal (imperceptible al ojo)
const int resolution = 10; // Precisión del brillo (10 bits = 1024 niveles de brillo)

void setup() {
  Serial.begin(115200); // Iniciamos el monitor para "leerle la mente" al ESP32
 
  pinMode(PIN_FOTORESISTENCIA, INPUT); // Decimos que el sensor es una ENTRADA de datos

  // Conectamos el pin del LED a la función de control de brillo (PWM)
  ledcAttach(PIN_LED_PWM, freq, resolution);
}

void loop() {
  // 1. SENTIR: Leemos cuánta luz hay en la habitación (0 a 4095)
  int lectura = analogRead(PIN_FOTORESISTENCIA);

  // 2. PENSAR: Calculamos la diferencia entre lo que queremos y lo que hay
  // Si el resultado es positivo, falta luz. Si es negativo, sobra.
  int error =  SETPOINT-lectura;

  // 3. AJUSTAR: El brillo actual cambia un poco según el error
  // Multiplicamos por 0.3 para que el cambio sea suave y no de saltos locos
  ledBrillo = ledBrillo + (reactionStrength * error);

  // 4. SEGURIDAD: El LED solo entiende números entre 0 y 1023
  // Si el cálculo da 1100, lo obligamos a quedarse en 1023. Si da -5, a 0.
  if (ledBrillo > 1023) ledBrillo = 1023;
  if (ledBrillo < 0) ledBrillo = 0;

  // 5. ACTUAR: Le ordenamos al LED que brille con la potencia calculada
  ledcWrite(PIN_LED_PWM, (int)ledBrillo);

  // 6. MOSTRAR: Enviamos los datos a la computadora para revisar que todo esté bien
  Serial.print("Luz Ambiente: ");
  Serial.print(lectura);
  Serial.print(" | Brillo enviado al LED: ");
  Serial.println((int)ledBrillo);

  delay(100); // Esperamos un poquito antes de volver a medir (10 veces por segundo)
}

domingo, 15 de febrero de 2026

6 FISRT OLED CODE HELLO WORLD

 /*

 * WELCOME TO C++ PROGRAMMING - GRADE 6
 * This is your first program! We will print a name on the OLED screen.
 */

// 1. LIBRARIES ( The Tools )
// We include special "books" of code that teach the ESP32 how to use the screen.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// 2. SCREEN CONFIGURATION ( The Hardware )
// We tell the ESP32 the size of our screen (128 pixels wide, 64 pixels tall).
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64

// We create a "control object" for the screen. Think of this as the remote control.
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

// 3. YOUR VARIABLES ( The Data )
// **********************************************************
// STUDENT: CHANGE THE TEXT INSIDE THE QUOTES BELOW!
// **********************************************************
String name_here = "MARIE CURIE";

void setup() {
  // This part runs ONLY ONE TIME when you turn on the ESP32.
 
  // A. Start the connection to the screen
  // (0x3C is the address/ID of the screen)
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    // If the screen is not found, stop here.
    for(;;);
  }

  // B. Clean the screen (erase old drawings)
  display.clearDisplay();

  // C. Set up the text style
  display.setTextSize(2);      // Size of the text (1 is small, 2 is medium)
  display.setTextColor(WHITE); // Color of the text (OLEDs are usually only one color)
 
  // D. Choose where to start writing (Column 10, Row 20)
  display.setCursor(10, 20);

  // E. Print the variable we created above
  display.println(name_here);

  // F. IMPORTANT: Push the information to the screen!
  // Nothing appears until we use this command.
  display.display();
}

void loop() {
  // This part repeats forever.
  // Since we only want to show the name once, we leave this empty!
  // Relax, ESP32!
}

7 SERVO MOTOR CODE WEEK 3

 /*

   TITULO: cobot motores servo sg90
   GRADO: Septimo
   
   OBJETIVO:
   Aprender a controlar 3 motores servo usando un controlador externo (PCA9685).
   Vamos a decirle a cada motor a qué ángulo (grados) debe ir.
   
   CONEXIONES EN EL PCA9685:
   - Motor Base   -> Puerto 0
   - Motor Hombro -> Puerto 4
   - Motor Codo   -> Puerto 8
*/

#include <Wire.h>                  // Librería para comunicarse por los cables SDA/SCL
#include <Adafruit_PWMServoDriver.h> // Librería para manejar la tarjeta controladora

// --- 1. CONFIGURACIÓN ---

// Creamos el "objeto" que controla la tarjeta
Adafruit_PWMServoDriver tarjetaMotores = Adafruit_PWMServoDriver();

// Definimos los nombres de nuestros motores y dónde están conectados
// Es más fácil usar nombres que números sueltos
const int MOTOR_BASE = 0;   // Conectado en el huequito 0
const int MOTOR_HOMBRO = 4; // Conectado en el huequito 4
const int MOTOR_CODO = 8;   // Conectado en el huequito 8

// Valores técnicos para el Servo SG90 (No cambiar esto por ahora)
// Estos números ayudan a traducir "Grados" a "Electricidad"
const int PULSO_MIN = 150; // Equivale a 0 grados
const int PULSO_MAX = 600; // Equivale a 180 grados

void setup() {
  Serial.begin(115200); // Iniciamos el monitor serial para ver mensajes
  Serial.println(">>> INICIANDO SISTEMA COBOT <<<");

  tarjetaMotores.begin();  // Encendemos la tarjeta PCA9685
  tarjetaMotores.setPWMFreq(50); // Configuramos la velocidad de señal (50Hz es estándar para servos)
 
  delay(100);
}

void loop() {
  // --- ZONA DE PRUEBAS PARA EL ESTUDIANTE ---
  // Aquí puedes cambiar los números para mover tu robot
 
  Serial.println("--- PRUEBA 1: Todos al centro (90 grados) ---");
  moverMotor(MOTOR_BASE, 90);
  moverMotor(MOTOR_HOMBRO, 90);
  moverMotor(MOTOR_CODO, 90);
  delay(2000); // Esperamos 2 segundos para ver la posición

  Serial.println("--- PRUEBA 2: Posición de Saludo ---");
  moverMotor(MOTOR_BASE, 0);    // Base gira a la derecha
  moverMotor(MOTOR_HOMBRO, 45); // Hombro sube un poco
  moverMotor(MOTOR_CODO, 180);  // Codo totalmente estirado
  delay(2000);

  Serial.println("--- PRUEBA 3: Posición de descanso (0 grados) ---");
  moverMotor(MOTOR_BASE, 0);
  moverMotor(MOTOR_HOMBRO, 0);
  moverMotor(MOTOR_CODO, 0);
  delay(2000);
 
  // El loop se repite infinitamente, volviendo a la Prueba 1
}

// ---------------------------------------------------------
// FUNCION AUXILIAR (La "Traductora")
// Esta parte del código convierte los grados humanos (0-180)
// a pulsos eléctricos que entiende la tarjeta.
// ---------------------------------------------------------
void moverMotor(int numeroMotor, int grados) {
 
  // 1. Convertimos grados a pulsos
  int pulso = map(grados, 0, 180, PULSO_MIN, PULSO_MAX);
 
  // 2. Enviamos la orden a la tarjeta
  tarjetaMotores.setPWM(numeroMotor, 0, pulso);
 
  // 3. Imprimimos en pantalla para que el estudiante sepa qué pasa
  Serial.print("Moviendo Motor en puerto ");
  Serial.print(numeroMotor);
  Serial.print(" al angulo: ");
  Serial.println(grados);
}

viernes, 13 de febrero de 2026

jueves, 12 de febrero de 2026

PROGRAMANDO ROBOTINA 7 GRADE

 


HAZ CLIC EN EL ENLACE Y PROGRAMA A ROBOTINA




https://gemini.google.com/share/6a99b2a40d95

EXAMPLE CODE FUNTIONS 7 GRADE

// 1. Incluimos la librería.
// Nota: En ESP32, esta librería es genial porque maneja el PWM solita.
#include <ESP32Servo.h>

// 2. Le damos un nombre a nuestro motor
Servo miRobot;

// 3. Elegimos el pin (el "agujerito" 18)
int pinServo = 18;

void setup() {
  // CORRECCIÓN IMPORTANTE:
  // Los ESP32 necesitan saber la frecuencia del PWM.
  // La mayoría de los servos funcionan a 50Hz.
  ESP32PWM::allocateTimer(0); // Reservamos un temporizador del cerebro
 
  miRobot.setPeriodHertz(50);    // Le decimos que lata 50 veces por segundo
  miRobot.attach(pinServo, 500, 2400); // Conectamos y fijamos límites seguros
}

void loop() {
  // Usamos nuestra función con números de PWM (microsegundos)
 
  moverBrazo(1000); // Pulso corto (hacia un lado)
  delay(1000);      // Espera un segundo
 
  moverBrazo(1500); // Pulso medio (mira al centro)
  delay(1000);
 
  moverBrazo(2000); // Pulso largo (hacia el otro lado)
  delay(1000);
}

// --- NUESTRA FUNCIÓN (El comando mágico) ---
// "int pulso" es la cajita donde guardamos el número que elegimos arriba
void moverBrazo(int pulso) {
  // Corregimos el comando: usamos writeMicroseconds para hablar en PWM
  miRobot.writeMicroseconds(pulso);
}

_______________________________________________________________________


Guía de Montaje en Wokwi

Para empezar, entra en Wokwi.com y selecciona ESP32. Luego, sigue estos pasos:

1. Buscar las piezas

  • Haz clic en el botón "+" (Add new part) que es de color púrpura.

  • En el buscador escribe: Servo y haz clic sobre el motor que aparece. ¡Ya tienes tu robot!

2. Conectar los cables (¡El paso más importante!)

Los servos tienen 3 cables. Vamos a conectarlos como si fueran piezas de un rompecabezas:

Cable del ServoColor en el motor¿A dónde va en el ESP32?Significado para niños
GNDNegro o MarrónPin GNDEs el cable de "tierra".
VCCRojoPin 5V o VINEs por donde entra la "comida" (energía).
PWMNaranja o AmarilloPin D18Es por donde viajan las "órdenes".

Truco de Wokwi: Para conectar un cable, haz clic en el extremo de un cable del servo y luego haz clic en el pin correspondiente del ESP32. ¡Puedes cambiarle el color al cable haciendo clic derecho sobre él!


miércoles, 11 de febrero de 2026

Concepto: Funciones en C++

https://gemini.google.com/share/9e8d5113a2c7https://gemini.google.com/share/9e8d5113a2c7

SEVENTH GRADE/ FIRST FORMATIVE ACTIVITY WEEK 3

 FORMATIVE ACTIVITY

https://gemini.google.com/share/c0c8b8151b4d


Aciertos 

Nota 

Estado 

4 

10.0 

Superior. Entiende perfectamente la estructura, funciones y librerías. 

3 

8.0 

Alto. Aprueba. Tiene claros los conceptos generales aunque falló en uno. 

2 

5.0 

Bajo. Reprueba. Confunde conceptos clave (ej. Loop vs Setup). 

0-1 

2.5 

Inferior. No comprende la lógica básica del programa. 

SET POINT CODE

 #include <ESP32Servo.h>


// --- CONFIGURACIÓN DE PINES ---
const int PIN_TRIG   = 5;    
const int PIN_ECHO   = 18;  
const int PIN_SERVO  = 19;  
const int PIN_BUZZER = 4;    

Servo miServo;

// ==========================================================
// 🚩 SECCIÓN DE HACKEO
// ==========================================================
int setPointCm = 100;      // DISTANCIA DE ACTIVACIÓN (Umbral)
int velocidadServo = 30;   // VELOCIDAD: Cuánto avanza el servo en cada ciclo
int tiempoSonido = 50;    // DURACIÓN: Qué tan largo es cada "pitido"
// ==========================================================

// Variables de control interno (No tocar para el hackeo básico)
int posicionActual = 0;  
int direccion = 1;        // 1 para derecha, -1 para izquierda

void setup() {
  Serial.begin(115200);
 
  pinMode(PIN_TRIG, OUTPUT);
  pinMode(PIN_ECHO, INPUT);
  pinMode(PIN_BUZZER, OUTPUT);
 
  miServo.attach(PIN_SERVO);
  miServo.write(posicionActual);
 
  Serial.println(">>> SISTEMA DE MOVIMIENTO CONSTANTE LISTO <<<");
}

void loop() {
  // 1. MEDICIÓN DE DISTANCIA
  digitalWrite(PIN_TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(PIN_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_TRIG, LOW);
  long duracion = pulseIn(PIN_ECHO, HIGH);
  int distancia = duracion * 0.034 / 2;

  // 2. LÓGICA DE ACTIVACIÓN CONSTANTE
  if (distancia > 0 && distancia < setPointCm) {
   
    Serial.print("OBJETO DETECTADO A: ");
    Serial.println(distancia);

    // --- MOVIMIENTO CONSTANTE ---
    // Actualizamos la posición sumando o restando según la dirección
    posicionActual += (direccion * velocidadServo);
   
    // Si llegamos a los límites (0 o 180), rebotamos
    if (posicionActual >= 180) {
      posicionActual = 180;
      direccion = -1; // Cambia a la izquierda
    }
    if (posicionActual <= 0) {
      posicionActual = 0;
      direccion = 1;  // Cambia a la derecha
    }

    miServo.write(posicionActual);

    // --- SONIDO PROGRESIVO ---
    // El sonido suena más rápido conforme te acercas
    digitalWrite(PIN_BUZZER, HIGH);
    delay(tiempoSonido);
    digitalWrite(PIN_BUZZER, LOW);
   
    // El silencio se acorta según la distancia (más velocidad de pitido)
    delay(distancia * 5);
  }
  else {
    // --- ESTADO DE REPOSO ---
    digitalWrite(PIN_BUZZER, LOW);
    // Opcional: El servo puede quedarse quieto o volver a 0
    // miServo.write(0);
    delay(50);
  }
}

lunes, 9 de febrero de 2026

SERVO PROGRAMMING CODE

 //Componente  Pin ESP32 Función Color Cable Servo


//Sensor HC-SR04 (Trig) GPIO 5  Disparador de señal -
//Sensor HC-SR04 (Echo) GPIO 18 Receptor de señal -
//Servo 1 (Base/Giro) GPIO 13 Movimiento Derecha/Izquierda  Amarillo/Naranja
//Servo 2 (Articulación)  GPIO 12 Movimiento Vertical (Saludo)  Amarillo/Naranja
//Servo 3 (Pinza) GPIO 14 Abrir/Cerrar Pinza  Amarillo/Naranja//

#include <ESP32Servo.h>

// Definición de pines para el sensor
const int TRIG_PIN = 5;
const int ECHO_PIN = 18;

// Definición de pines para los 3 Servos
const int SERVO1_PIN = 13; // Base
const int SERVO2_PIN = 12; // Brazo (Saludo)
const int SERVO3_PIN = 14; // Pinza (Gripper)

// Crear objetos para los servos
Servo baseServo;
Servo armServo;
Servo gripperServo;

// Variables para el sensor
long duration;
int distance;
const int safetyDistance = 30; // Distancia de seguridad en cm

void setup() {
  Serial.begin(115200);
 
  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);
 
  // Configurar temporizadores para ESP32 (soporta hasta 16 canales PWM)
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
 
  baseServo.setPeriodHertz(50);
  armServo.setPeriodHertz(50);
  gripperServo.setPeriodHertz(50);
 
  // Adjuntar servos a los pines
  baseServo.attach(SERVO1_PIN, 500, 2400);
  armServo.attach(SERVO2_PIN, 500, 2400);
  gripperServo.attach(SERVO3_PIN, 500, 2400);

  Serial.println("Sistema Cobot Inicializado con Seguridad activa...");
}

// Función para medir la distancia actual
void checkDistance() {
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
 
  duration = pulseIn(ECHO_PIN, HIGH);
  distance = duration * 0.034 / 2;
}

// Función de movimiento seguro: Verifica el sensor antes de mover
bool safeMove(Servo &s, int angle, int waitTime) {
  checkDistance();
  if (distance > 0 && distance < safetyDistance) {
    Serial.println("ALERTA: Obstáculo detectado. Motores bloqueados.");
    return false; // Detiene la ejecución del paso actual
  }
  s.write(angle);
  delay(waitTime);
  return true;
}

void loop() {
  checkDistance();

  // Solo si el camino está despejado
  if (distance > safetyDistance || distance == 0) {
   
    // --- 1. MOVIMIENTO DE LA BASE (SERVO 1) ---
    if (!safeMove(baseServo, 180, 1000)) return; // 90° Derecha
    if (!safeMove(baseServo, 0, 1000))   return; // 90° Izquierda
    if (!safeMove(baseServo, 90, 5000))  return; // Centro y espera 5 segundos
   
    // --- 2. SALUDO VERTICAL (SERVO 2) ---
    if (!safeMove(armServo, 180, 600))   return; // Arriba
    if (!safeMove(armServo, 90, 600))    return; // Centro
    if (!safeMove(armServo, 0, 600))     return; // Abajo
    if (!safeMove(armServo, 90, 600))    return; // Centro
   
    // --- 3. ACCIÓN DE LA PINZA (SERVO 3) ---
    if (!safeMove(gripperServo, 180, 800)) return; // Abre Pinza
    if (!safeMove(gripperServo, 90, 800))  return; // Cierra Pinza (sujeta)
    if (!safeMove(gripperServo, 180, 800)) return; // Abre Pinza nuevamente
    if (!safeMove(gripperServo, 90, 500))  return; // Posición neutra
   
  } else {
    // Si hay alguien cerca, no hace nada y espera
    delay(200);
  }
}