Procesos paralelos de Arduino. Arduino: Conexión en paralelo y en serie de dispositivos esclavos al bus SPI. Controlar un LED y un zumbador piezoeléctrico mediante el operador Delay()

En términos generales, Arduino no admite la paralelización de tareas verdaderas ni los subprocesos múltiples. Pero es posible con cada repetición del ciclo círculo() indique al microcontrolador que verifique si es hora de ejecutar alguna tarea adicional en segundo plano. En este caso, al usuario le parecerá que se están realizando varias tareas simultáneamente.

Por ejemplo, hagamos parpadear un LED a una frecuencia dada y emitamos simultáneamente sonidos ascendentes y descendentes como una sirena desde un emisor piezoeléctrico. Ya hemos conectado más de una vez tanto el LED como el emisor piezoeléctrico al Arduino. Montemos el circuito, como se muestra en la figura.

Si está conectando un LED a un pin digital que no sea "13", no se olvide de una resistencia limitadora de corriente de 220 ohmios.

2 Control de LED y zumbador piezoeléctrico usando el operador delay()

Escribamos este boceto y subámoslo a Arduino.

Const int soundPin = 3; /* declaramos una variable con el número del pin al que está conectado el elemento piezoeléctrico */ const int ledPin = 13; // declara una variable con el número de pin del LED configuración vacía()( pinMode(pin de sonido, SALIDA); // declara el pin 3 como salida. pinMode(ledPin, SALIDA); // declara el pin 13 como salida. } bucle vacío() (// Control de sonido: tono(soundPin, 700); // hacer un sonido a una frecuencia de 700 Hz delay(200); tono (pin de sonido, 500); // con un retraso de 500 Hz (200); tono (pin de sonido, 300); // con un retraso de 300 Hz (200); tono (pin de sonido, 200); // con un retraso de 200 Hz (200); // control LED: digitalWrite(ledPin, HIGH); // retardo de disparo(200); digitalWrite(ledPin, BAJO); // extingue el retraso (200); }

Después de encenderlo, se puede ver que el boceto no se ejecuta exactamente como lo necesitamos: hasta que la sirena esté completamente resuelta, el LED no parpadeará y nos gustaría que el LED parpadeara durante el sonido de una sirena. ¿Cuál es el problema aquí?

El hecho es que este problema no se puede resolver de la manera habitual. Las tareas son realizadas por el microcontrolador de forma estrictamente secuencial. Operador demora() retrasa la ejecución del programa por un período de tiempo específico, y hasta que expire este tiempo, los siguientes comandos del programa no se ejecutarán. Debido a esto, no podemos establecer una duración de ejecución diferente para cada tarea en el ciclo. círculo() programas Por lo tanto, necesita simular de alguna manera la multitarea.

3 Procesos Paralelos sin el operador "delay()"

Los desarrolladores de Arduino proponen la opción en la que Arduino realizará tareas en pseudo-paralelo. La esencia del método es que con cada repetición del ciclo círculo() comprobamos si es hora de hacer parpadear el LED (realizar una tarea en segundo plano) o no. Y si es así, invertimos el estado del LED. Este es un tipo de operador de derivación. demora().

Const int soundPin = 3; // variable con el número de pin del elemento piezoeléctrico const int ledPin = 13; // variable con número de pin LED const long ledInterval = 200; // Intervalo de parpadeo del LED, mseg. int ledState = BAJO; // estado inicial del LED sin firmar largo anteriorMillis = 0; // almacena el tiempo del encendido anterior del LED configuración vacía()( pinMode(pin de sonido, SALIDA); // establece el pin 3 como salida. pinMode(ledPin, SALIDA); // establece el pin 13 como salida. } bucle vacío() (// Control de sonido: tono(soundPin, 700); retraso (200); tono (pin de sonido, 500); retraso (200); tono (pin de sonido, 300); retraso (200); tono (pin de sonido, 200); retraso (200); // Parpadeo del LED: // tiempo desde que se encendió Arduino, ms: unsigned long currentMillis = millis(); // Si es hora de parpadear, if (currentMillis - previousMillis >= ledInterval) ( previousMillis = currentMillis; // entonces almacena la hora actual if (ledState == LOW) ( // e invierte el estado del LED ledState = HIGH; ) else (ledState = BAJO;) digitalWrite(ledPin, ledState); // alternar el estado del LED) }

Una desventaja significativa de este método es que la sección de código antes del bloque de control LED debe ejecutarse más rápido que el intervalo de tiempo de parpadeo del LED "ledInterval". De lo contrario, el parpadeo ocurrirá con menos frecuencia de la necesaria y no obtendremos el efecto de la ejecución paralela de tareas. En particular, en nuestro esquema, la duración del cambio en el sonido de la sirena es 200+200+200+200 = 800 ms, y configuramos el intervalo de parpadeo del LED en 200 ms. Pero el LED parpadeará en un período de 800ms, que es 4 veces lo que configuramos.

En general, si el código usa el operador demora(), en este caso es difícil simular pseudoparalelismo, por lo que es conveniente evitarlo.

En este caso, sería necesario que la unidad de control de sonido de sirena también verificara si ha llegado el momento o no, y no usar demora(). Pero esto aumentaría la cantidad de código y empeoraría la legibilidad del programa.

4 Uso de la biblioteca ArduinoThread para crear hilos paralelos

Para resolver el problema, utilizaremos una biblioteca maravillosa. Hilo Arduino, que le permite crear fácilmente procesos pseudo-paralelos. Funciona de manera similar, pero le permite no escribir código para verificar el tiempo; debe completar la tarea en este ciclo o no. Esto reduce la cantidad de código y mejora la legibilidad del boceto. Echemos un vistazo a la biblioteca en acción.


En primer lugar, descargue el archivo de la biblioteca del sitio web oficial y descomprímalo en el directorio bibliotecas/ Entorno de desarrollo Arduino IDE. Luego cambie el nombre de la carpeta Arduino Threadmaster en Hilo Arduino.

El diagrama de cableado seguirá siendo el mismo. Solo cambiará el código del programa.

#incluir // conectando la biblioteca ArduinoThread const int soundPin = 3; // variable con el número de pin del elemento piezoeléctrico const int ledPin = 13; // variable con número de pin LED Thread ledThread = Thread(); // crea un hilo para controlar el LED Thread soundThread = Thread(); // crea un flujo de control para la sirena configuración vacía()( pinMode(pin de sonido, SALIDA); // declara el pin 3 como salida. pinMode(ledPin, SALIDA); // declara el pin 13 como salida. ledSubproceso.onRun(ledParpadeo); // asignar una tarea al subproceso ledThread.setInterval(1000); // establece el intervalo de respuesta, ms soundThread.onRun(sound); // asignar una tarea al subproceso soundThread.setInterval(20); // establecer el intervalo de respuesta, ms } bucle vacío() (// Comprobar si es hora de cambiar el LED: if (ledThread.shouldRun()) ledThread.run(); // inicia el hilo // Comprueba si es hora de cambiar el tono de la sirena: if (soundThread.shouldRun()) soundThread.run(); // iniciar hilo } // flujo LED: parpadeo led vacío () ( static bool ledStatus = falso; // Estado del LED Encendido/Apagado ledStatus = !ledStatus; // invertir el estado digitalWrite(ledPin, ledStatus); // enciende/apaga el LED } // Flujo de sirena: sonido vacío() ( tono interno estático = 100; // tono de sonido, tono Hz (soundPin, ton); // enciende la sirena a "ton" Hz if (ton )

En el programa, creamos dos hilos: Hilo led y hilo de sonido, cada uno realiza su propia operación: uno hace parpadear el LED, el segundo controla el sonido de la sirena. En cada iteración del bucle de cada hilo, comprobamos si ha llegado o no el momento de su ejecución. Si llega, se lanza para su ejecución mediante el método correr(). Lo principal es no usar el operador. demora(). Se dan explicaciones más detalladas en el código.


Cargue el código en la memoria de Arduino, ejecútelo. ¡Ahora todo funciona exactamente como debería!

Y daremos un ejemplo de uso de la función Arduino. adjuntar Interrupción ().

Una interrupción es una señal que informa al procesador sobre la ocurrencia de algún evento que requiere atención inmediata. El procesador debe responder a esta señal interrumpiendo la ejecución de las instrucciones actuales y transfiriendo el control al manejador de interrupciones (ISR, rutina de servicio de interrupción). Un controlador es una función regular que escribimos nosotros mismos y ponemos allí el código que debe responder al evento.

Después de dar servicio a la interrupción de ISR, la función finaliza su trabajo y el procesador felizmente regresa a las actividades interrumpidas; continúa ejecutando el código desde el lugar donde se detuvo. Todo esto sucede automáticamente, por lo que nuestra tarea es solo escribir un controlador de interrupción sin romper nada y sin obligar al procesador a distraerse con demasiada frecuencia. Necesitará una comprensión del circuito, los principios de funcionamiento de los dispositivos conectados y una idea de con qué frecuencia se puede llamar a una interrupción, cuáles son las características de su ocurrencia. Todo esto es la principal dificultad al trabajar con interrupciones.

Interrupciones de hardware y software

Las interrupciones en Arduino se pueden dividir en varios tipos:

  • interrupciones de hardware. Interrupción a nivel de arquitectura del microprocesador. El evento en sí puede ocurrir en un momento productivo desde un dispositivo externo, por ejemplo, presionando un botón en el teclado, moviendo el mouse de una computadora, etc.
  • Interrupciones de software. Se lanzan dentro del programa usando una instrucción especial. Se utiliza para llamar a un controlador de interrupciones.
  • Interrupciones internas (sincrónicas). Se produce una interrupción interna como resultado de un cambio o violación en la ejecución del programa (por ejemplo, al acceder a una dirección no válida, código de operación no válido, etc.).

¿Por qué necesitamos interrupciones de hardware?

Las interrupciones de hardware ocurren en respuesta a un evento externo y provienen de un dispositivo de hardware externo. Hay 4 tipos de interrupciones de hardware en Arduino. Todos ellos difieren en la señal en el pin de interrupción:

  • El contacto se tira al suelo. El controlador de interrupciones se ejecuta siempre que el pin de interrupción esté en BAJO.
  • Cambiar la señal en un contacto. En este caso, Arduino ejecuta un controlador de interrupción cuando se produce un cambio de señal en el pin de interrupción.
  • Cambiar la señal de BAJO a ALTO en un pin: al cambiar de bajo a alto, se ejecutará un controlador de interrupción.
  • Cambiar la señal de ALTA a BAJA en un pin: cuando la señal cambia de alta a baja, se ejecutará un controlador de interrupción.

Las interrupciones son útiles en los programas de Arduino, ya que ayudan a resolver problemas de temporización. Por ejemplo, cuando se trabaja con UART, las interrupciones le permiten no realizar un seguimiento de la llegada de cada personaje. El dispositivo de hardware externo emite una señal de interrupción, el procesador llama inmediatamente al controlador de interrupciones, que captura el carácter a tiempo. Esto ahorra tiempo de CPU, que sin interrupciones se gastaría en verificar el estado del UART; en cambio, el controlador de interrupciones realiza todas las acciones necesarias sin afectar el programa principal. No se requieren capacidades especiales del dispositivo de hardware.

Las principales razones para llamar a una interrupción son:

  • Determinar el cambio de estado de la salida;
  • Interrupción del temporizador;
  • Interrupciones de datos vía SPI, I2C, USART;
  • Conversión de analógico a digital;
  • Disponibilidad para usar EEPROM, memoria flash.

Cómo se implementan las interrupciones en Arduino

Cuando se recibe una señal de interrupción, la operación se suspende. Comienza la ejecución de la función que se declara ejecutar en caso de interrupción. Una función declarada no puede aceptar valores de entrada y devolver valores al finalizar. La interrupción no afecta al código en sí mismo en el bucle del programa principal. Para trabajar con interrupciones en Arduino, se utiliza una función estándar adjuntar Interrupción ().

La diferencia entre la implementación de interrupciones en diferentes placas Arduino

Dependiendo de la implementación de hardware de un modelo de microcontrolador en particular, hay varias interrupciones. La placa Arduino Uno tiene 2 interrupciones en el segundo y tercer pin, pero si se requieren más de dos salidas, la placa admite un modo especial de "cambio de pin". Este modo funciona cambiando la entrada para todos los pines. La diferencia en el modo de interrupción de cambio de entrada es que las interrupciones se pueden generar en cualquiera de los ocho pines. La tramitación en este caso será más complicada y más larga, ya que tendrás que llevar un control del último estado de cada uno de los contactos.

En otras placas, el número de interrupciones es mayor. Por ejemplo, la placa tiene 6 pines que pueden manejar interrupciones externas. Para todas las placas Arduino, cuando se trabaja con la función AttachInterrupt (interrupción, función, modo), el argumento Inerrupt 0 está asociado con el pin digital 2.

Interrupciones en el lenguaje Arduino

Ahora pasemos a la práctica y hablemos sobre cómo usar las interrupciones en sus proyectos.

Sintaxis de AttachInterrupt()

La función AttachInterrupt se utiliza para trabajar con interrupciones. Sirve para conectar una interrupción externa a un controlador.

Sintaxis de llamada: AttachInterrupt (interrupción, función, modo)

Argumentos de la función:

  • interrupción - el número de la interrupción que se llama (estándar 0 - para el segundo pin, para la placa Arduino Uno 1 - para el tercer pin),
  • función: el nombre de la función llamada cuando se interrumpe (importante: la función no debe aceptar ni devolver ningún valor),
  • El modo es la condición para disparar la interrupción.

Se pueden establecer las siguientes condiciones de activación:

  • BAJO - realizado en un nivel de señal bajo, cuando el contacto tiene un valor cero. La interrupción se puede repetir cíclicamente, por ejemplo, cuando se presiona un botón.
  • CAMBIO - en el frente, la interrupción ocurre cuando la señal cambia de alta a baja o viceversa. Se ejecuta una vez en cualquier cambio de señal.
  • RISING - Ejecuta una interrupción una vez cuando la señal cambia de BAJA a ALTA.
  • FALLING - Ejecuta una interrupción una vez cuando la señal cambia de HIGH a LOW.4

Notas importantes

Al trabajar con interrupciones, se deben tener en cuenta las siguientes limitaciones importantes:

  • La función del controlador no debería tardar demasiado en ejecutarse. La cosa es que Arduino no puede manejar múltiples interrupciones al mismo tiempo. Mientras se ejecuta su función de controlador, todas las demás interrupciones se ignorarán y es posible que se pierda eventos importantes. Si necesita hacer algo grande, simplemente pase el control de eventos en el bucle principal(). En el controlador, solo puede configurar el indicador de evento y, en el ciclo, puede verificar el indicador y procesarlo.
  • Hay que tener mucho cuidado con las variables. Un compilador inteligente de C++ puede "volver a optimizar" su programa eliminando las variables que no necesita. El compilador simplemente no verá que está configurando algunas variables en una parte y usándolas en otra. Para eliminar esta posibilidad en el caso de tipos de datos básicos, puede usar la palabra clave volatile, por ejemplo: volatile boolean state = 0. Pero este método no funcionará con estructuras de datos complejas. Así que hay que estar siempre alerta.
  • No se recomienda usar una gran cantidad de interrupciones (trate de no usar más de 6-8). Una gran cantidad de eventos diferentes requiere una complicación grave del código y, por lo tanto, conduce a errores. Además, debe comprender que no se puede hablar de precisión temporal de ejecución en sistemas con una gran cantidad de interrupciones: nunca comprenderá exactamente cuál es el intervalo entre las llamadas de los comandos que son importantes para usted.
  • Delay() no debe usarse en controladores. El mecanismo para determinar el intervalo de retraso usa temporizadores, y también funcionan en las interrupciones que su controlador bloqueará. Como resultado, todos esperarán a todos y el programa se colgará. Por la misma razón, no se pueden utilizar protocolos de comunicación basados ​​en interrupciones (como i2c).

ejemplos de AttachInterrupt

Vayamos a la práctica y consideremos el ejemplo más simple del uso de interrupciones. En el ejemplo, definimos una función de controlador que, cuando cambie la señal en el pin 2 del Arduino Uno, cambiará el estado del pin 13, al que tradicionalmente conectaremos el LED.

#define PIN_LED 13 estado de acción booleano volátil = BAJO; void setup() ( pinMode(PIN_LED, OUTPUT); // Establecer la interrupción // Se llamará a la función myEventListener cuando // la señal cambie en el pin 2 (la interrupción 0 está conectada al pin 2) // la señal cambia (no importa en qué dirección) attachInterrupt (0, myEventListener, CHANGE); ) void loop() ( // No hacemos nada en la función de bucle, ya que todo el código de manejo de eventos estará en la función myEventListener) void myEventListener() ( actionState != actionState; // // Hacer otras cosas como encender o apagar el LED digitalWrite(PIN_LED, actionState); )

Veamos algunos ejemplos de interrupciones más complejas y sus controladores: para el temporizador y los botones.

Interrupciones de botón anti-rebote

Cuando ocurre una interrupción, antes de que los contactos hagan contacto firme cuando se presiona el botón, oscilarán, generando varias operaciones. Hay dos formas de lidiar con la charla: hardware, es decir, soldando un condensador al botón y software.

Puede deshacerse de las conversaciones con la función: le permite detectar el tiempo transcurrido desde la primera operación del botón.

If(digitalRead(2)==HIGH) ( //cuando se presiona el botón //Si han transcurrido más de 100 milisegundos desde la última vez que se presionó if (millis() - previousMillis >= 100) ( //Recordar el tiempo de la primera operación previousMillis = millis(); if (led==oldled) ( // comprueba que el estado del botón no ha cambiado led=!led; )

Este código le permite eliminar el parloteo y no bloquea la ejecución del programa, como es el caso de la función de retraso, que no está permitida en las interrupciones.

Interrupciones de temporizador

Un temporizador es un contador que cuenta a una determinada frecuencia obtenida del procesador 16 MHz. Puede configurar el divisor de frecuencia para obtener el modo de conteo deseado. También puede configurar el contador para generar interrupciones cuando se alcanza un valor determinado.

Y la interrupción del temporizador le permite ejecutar la interrupción una vez por milisegundo. Arduino tiene 3 temporizadores: Timer0, Timer1 y Timer2. Timer0 se usa para generar interrupciones una vez por milisegundo, lo que actualiza el contador que se pasa a la función millis(). Este temporizador es de ocho bits y cuenta de 0 a 255. Se genera una interrupción cuando el valor es 255. De forma predeterminada, se utiliza un divisor de reloj por 65 para obtener una frecuencia cercana a 1 kHz.

Los registros de comparación se utilizan para comparar el estado del temporizador y los datos almacenados. En este ejemplo, el código generará una interrupción cuando el contador llegue a 0xAF.

TIMSK0 |= _BV(OCIE0A);

Es necesario definir un controlador de interrupción para el vector de interrupción del temporizador. El vector de interrupción es un puntero a la ubicación de la instrucción que se ejecutará cuando se llame a la interrupción. Varios vectores de interrupción se combinan en una tabla de vectores de interrupción. El temporizador en este caso tendrá el nombre TIMER0_COMPA_vect. En este controlador, se realizarán las mismas acciones que en bucle ().

SIGNAL(TIMER0_COMPA_vect) ( unsigned long currentMillis = millis(); sweeper1.Update(currentMillis); if(digitalRead(2) == HIGH) ( sweeper2.Update(currentMillis); led1.Update(currentMillis); ) led2.Update( currentMillis); led3.Update(currentMillis); ) // La función loop() permanecerá vacía. bucle vacío() ( )

resumiendo

La interrupción en Arduino es un tema bastante complicado, porque hay que pensar en toda la arquitectura del proyecto a la vez, imaginar cómo se ejecuta el código, qué eventos son posibles, qué sucede cuando se interrumpe el código principal. No pretendíamos revelar todas las características de trabajar con esta construcción del lenguaje, el objetivo principal era presentar los principales casos de uso. En próximos artículos seguiremos hablando de las interrupciones con más detalle.

Hola Andrei. Su enfoque para transferir el bagaje de conocimiento y experiencia que ha acumulado es muy interesante. Ayuda mucho a empezar. Bueno, yo, empezando a dominar arduino, tengo ganas de progresar. Además, con ayuda externa, puedo hacerlo más rápido. Entonces: al principio, mi tarea era hacer que un robot se moviera a lo largo de la línea. Lo hice, todo está bien. Pero además, brindándole opciones adicionales, no entendía por qué dejaba de responder correctamente a la línea. Encontré este artículo y entendí por qué.

Ahora tengo una pregunta para usted: en el esquema a continuación y listo, dados los problemas con la demora, ¿debo cambiar a milis donde esté presente esta función? Si es así, ¿entonces entiendo que habrá que rehacer casi todo el boceto? ¿Y no está del todo claro cómo usar milisegundos para medir distancias? Gracias.

//Robot con función de seguimiento de línea blanca

// ********************* Establecer cables de motor ********************* *

int MotorLeftSpeed ​​= 5; // Izquierda (A) VELOCIDAD Motor - ENA

int MotorIzquierdaAdelante = 4; // Motor izquierdo (A) ADELANTE - IN1

int MotorLeftBack = 3; // Izquierda (A) Motor ATRÁS - IN2

int MotorDerechaAdelante = 8; // Derecho (B) Motor ADELANTE - IN3

int MotorDerechaAtrás = 7; // Derecho (B) Motor ATRÁS - IN4

int MotorDerechaVelocidad = 9; // Derecho (B) motor VELOCIDAD - ENB

// ********************Instalar las salidas de los sensores ultrasónicos********************* **** *

inttrigPinL = 14; // configurando el número de salida del sensor ultrasónico activador izquierdo

int echoPinL = 15; // configurando el número de salida del sensor ultrasónico de eco izquierdo

inttrigPinC = 10; // configurando el número de salida del sensor ultrasónico trig central

int echoPinC = 11; // configurar el número de salida del sensor ultrasónico de eco central

inttrigPinR = 12; // configurando el número de salida del sensor ultrasónico activador derecho

int echoPinR = 13; // configurando el número de salida del sensor ultrasónico de eco derecho

// ********************* Configuración de las salidas de los sensores de línea *******************

const int LineSensorLeft = 19; // entrada del sensor de línea izquierda

const int LineSensorRight = 18; // entrada del sensor de línea derecho

intSL; // estado del sensor izquierdo

intSR; // estado del sensor derecho

// ********************* Configuración de la salida de alarmas de luz y sonido ****************

luz int = 2; // configurar el número de salida de la señal de luz

int Zumm = 6; // establece el número de salida del zumbador

int ledState = BAJO; // establecer el estado del LED en esta variable

largo anteriorMillis = 0; // almacenar la hora del último encendido del LED

intervalo largo = 300; // intervalo entre encender/apagar el LED (0.3 segundos)

// ******************** Medición de distancia variable por sensores***************

unsigned int impulseTimeL=0;

unsigned int impulseTimeC=0;

unsigned int impulseTimeR=0;

larga distL=0; // distancia medida por el sensor ultrasónico izquierdo

distancia largaC=0; // distancia medida por el sensor ultrasónico central

larga distR=0; // distancia medida por el sensor Uz derecho

// ******************************* CONFIGURACIÓN *********** ***** ***************

Serial.begin(9600); // iniciar puerto serie (velocidad 9600)

//*************** Ajustar contactos del motor********************

pinMode(MotorDerechaAtrás, SALIDA); // Derecho (B) Motor VOLVER

pinMode(MotorDerechoAdelante, SALIDA); // Derecho (B) Motor ADELANTE

pinMode(MotorLeftBack, SALIDA); // Motor Izquierdo (A) ATRÁS

pinMode(MotorIzquierdaAdelante, SALIDA); // Motor izquierdo (A) ADELANTE

retraso (duración);

//*************** Establecer los contactos del sensor de tiras*******************

pinMode(LineSensorLeft, ENTRADA); // definiendo el pin del sensor de linea izquierda

pinMode(LineSensorRight, ENTRADA); // definiendo el pin del sensor de linea derecha

// ***************Configuración de los modos de salida de los sensores ultrasónicos*************************

pinMode(trigPinL, SALIDA); // configurar el modo de funcionamiento de la salida del sensor ultrasónico activador izquierdo

pinMode(echoPinL, ENTRADA); // configurar el modo de funcionamiento de la salida del sensor ultrasónico de eco izquierdo

pinMode(trigPinC, SALIDA); // configurar el modo de funcionamiento de la salida del sensor ultrasónico trig central

pinMode(echoPinC, ENTRADA); // configurar el modo de funcionamiento de la salida del sensor ultrasónico de eco central

pinMode(trigPinR, SALIDA); // configurando el modo de operación de la salida del sensor ultrasónico trig derecho

pinMode(echoPinR, ENTRADA); // configurando el modo de salida de la salida del sensor ultrasónico de eco derecho

// *************** Establecer contactos para alarmas de luz y sonido*************************** *********

pinMode(Zumm, SALIDA); // configurando el modo de operación de la salida del zumbador

pinMode(Luz, SALIDA); // configurar el modo de funcionamiento de la salida de señalización luminosa

// ******************** Comandos básicos de movimiento ******************

void adelante (int a, int sa) // ADELANTE

analogWrite(MotorRightSpeed, sa);

analogWrite(MotorLeftSpeed, sa);

void right (int b, int sb) // GIRA A LA DERECHA (un lado)

digitalWrite(MotorDerechoAtrás, BAJO);

digitalWrite(MotorLeftBack, BAJO);

digitalWrite(MotorIzquierdoAdelante, ALTO);

analogWrite(MotorLeftSpeed, sb);

void left (int k, int sk) // GIRO A LA IZQUIERDA (un lado)

digitalWrite(MotorDerechoAtrás, BAJO);

digitalWrite(MotorDerechoAdelante, ALTO);

analogWrite(MotorRightSpeed, sk);

digitalWrite(MotorLeftBack, BAJO);

void detener(int f) // DETENER

digitalWrite(MotorDerechoAtrás, BAJO);

digitalWrite(MotorDerechoAdelante, BAJO);

digitalWrite(MotorLeftBack, BAJO);

digitalWrite(MotorIzquierdoAdelante, BAJO);

// ************************** Medida de distancia******************** *

void izmdistL () // medición de distancia por el sensor ultrasónico izquierdo

digitalWrite(trigPinL, ALTO);

digitalWrite(trigPinL, BAJO); // Pulso de 10mS a la salida de activación del sensor ultrasónico para la medición de distancia

impulsoTiempoL = pulsoEn(echoPinL, ALTO); // leer la distancia desde el sensor ultrasónico

distL=impulsoTiempoL/58; // Convertir a centímetros

void izmdistC () // medición de distancia por el sensor ultrasónico central

digitalWrite(trigPinC, ALTO);

digitalWrite(trigPinC, BAJO); // Pulso de 10mS a la salida de activación del sensor ultrasónico para la medición de distancia

impulsoTiempoC = pulsoEn(echoPinC, ALTO); // leer la distancia desde el sensor ultrasónico

distC=TiempoImpulsoC/58; // Convertir a centímetros

void izmdistR () // medición de distancia por el sensor ultrasónico central

digitalWrite(trigPinR, ALTO);

digitalWrite(trigPinR, BAJO); // Pulso de 10mS a la salida de activación del sensor ultrasónico para la medición de distancia

impulsoTiempoR = pulsoEn(echoPinR, ALTO); // leer la distancia desde el sensor ultrasónico

distR=impulsoTiempoR/58; // Convertir a centímetros

// ******************************* BUCLE *********** ***** ****************

// ********************* Modo de seguimiento de LÍNEA ********************* ***

// ********************señalización luminosa y sonora*******************

tono (Zumm, 900); // enciende el sonido a 900 Hz

tono (Zumm, 900); // enciende el sonido a 800 Hz

currentMillis largo sin firmar = millis();

if (millis actual - Millis anterior > intervalo) // comprobar si ha pasado el intervalo requerido, si es así

anteriorMillis = actualMillis; // almacenar la hora del último cambio

if (ledState == LOW) // si el LED está apagado, entonces lo encendemos, y viceversa

ledState = ALTO;

escritura digital (luz, estado de led); // establecer estados de salida para encender o apagar el LED

// ************************** Medida de distancia******************** **** **

Serial.println(distL);

Serial.println(distC);

Serial.println(distR);

if (distL>50 && distC>50 && distR>50) // si la distancia medida es más de 50 centímetros - ir

SL=lectura digital(LineSensorLeft); // lee la señal del sensor del carril izquierdo

SR=lectura digital(LíneaSensorDerecho); // lee la señal del sensor del carril derecho

// ************************ Siguiendo la línea negra ******************* ****

// ROBOT en el carril - vamos recto

if (SL == BAJO & SR == BAJO) // BLANCO - BLANCO - ir RECTO

adelante (10, 100); // ADELANTE (tiempo, velocidad)

// ROBOT comienza a cambiar de carril - rodamos

si no (SL == BAJO & SR == ALTO) // NEGRO - BLANCO - girar a la IZQUIERDA

izquierda (10, 100);// girar a la IZQUIERDA (tiempo, velocidad)

si no (SL == ALTO & SR == BAJO) // BLANCO - NEGRO - gire a la DERECHA

derecha (10, 100); // girar a la DERECHA (tiempo, velocidad)

// TERMINAR - ROBOT ve un carril con ambos sensores

si no (SL == ALTO & SR == ALTO) // NEGRO - NEGRO - STOP

detener(50); // DETENER

else // si la distancia medida es menor o igual al mínimo, detener