El Arduino tiene varios puertos que pueden ser digitales, analógicos y PWM. Estos pueden ser definidos como entrada o salida.
Arduino tiene catorce (14) puertos digitales, denominados de 0~13.
Si requieres tener mas pines digitales como salida puedes echar mano de los pines analógicos A0~A5, solo declararlos como salidas 14~19. Prueba poner un LED para comprobar.
Aunque en muchos ejemplos veas que se usan variables tipo int para declarar los pines a usar, eso es un desperdicio de recursos doble. En primer lugar porque una variable tipo int ocupa 2 bytes y cubre un rango mucho mas amplio que cualquier numero de pines disponibles en Arduino. Una variable tipo byte cubre el rando de 0-255 que es mas que suficiente y solo ocupa 1 byte. El otro tema es que se guardara en la escasa RAM. Si la declaras como constante se guardara en la flash.
Esta funcion debe ser usada dentro de Setup() y sirva para configurar los puertos digitales que serán usadas y el modo que puede ser INPUT (entrada) o OUTPUT (salida) o INPUT_PULLUP (entrada con forzado de HIGH).
pinMode(pin, mode);
Tanto el pin como el valor podrían ser almacenados en constantes.
const byte pin = 13; pinMode(7, INPUT); pinMode(pin, OUTPUT); pinMode(3, INPUT_PULLUP);
Por defecto los puertos digitales están definidos como entradas y no es necesario declararlos. Bajo el punto de vista eléctrico es una resistencia de 20K que esta activa o no. Los puertos configurados como salida son de baja impedancia y pueden suministrar 5V y hasta 40 mA.
Es muy importante no olvidar poner una resistencia de entre 470~1000 ohms como limitadora.
Lee el valor del puerto digital dando un resultado. Los valores pueden ser HIGH o LOW.
digitalRead(pin);
El pin se puede especificar ya sea como una variable o constante (0~13 + 14~19).
byte led = 9; digitalRead(5); digitalRead(led);
Envía al puerto digital definido previamente como OUTPUT el valor HIGH o LOW (poniendo en 1 o 0 la salida). El pin se puede especificar ya sea como una variable o como una constante (0~13 + 14~19).
digitalWrite(pin, valor);
Tanto el pin (0~13 + 14~19) como el valor (LOW / HIGH) se puede especificar ya sea como una variable o constante.
digitalWrite(0, HIGH); digitalWrite(5, LOW);
Arduino tiene 6 puertos analógicos marcados como A0~A5, que solo pueden ser de entradas y no salidas. Y que pasa si necesita una salida analógica ? Lo que ocurre es que seis (6) de los puertos digitales pueden ser usados para simulado salidas analógicas llamadas PWM.
Lee el valor de pines analógicos marcados en Arduino como A0~A5, con una resolución de 10 bits. Esta instrucción sólo funciona en los pines (A0~A5). El rango de valores devuelto puede estar entre 0~1023.
analogRead(pin);
Los pines analógicos de entrada, al igual de que digitales de entrada no necesitan ser definidos.
analogRead(0); analogRead(5);
El pin se puede especificar ya sea como una variable o constante (0~5).
Esta sentencia configura la referencia de voltaje que se usa en las entradas analógicas es decir, recordamos que en las entradas analógicas solo podíamos detectar 1024 valores posibles, el valor que pongamos aquí será el valor correspondiente al 1023. Supongamos que tenemos un rango de 0V a 5V. Esto implica que la resolución que estamos aplicando es 5V equivales a 1024 osea 0.0049V (4.9 mV). Si cambiamos la referencia y ponemos un valor menor como por ejemplo 2V la resolución cambia y ahora sería 2V el equivalente a 1024 que equivale a lecturas de 0.00195V (1.95mV). Puede tomar 3 valores diferentes:
analogReference(tipo)
Existen dos métodos por los cuales Arduino puede simular salidas analógicas usando puertos digitales. El periodo y el ancho del tren de pulsos puede determinar la potencia entregada a dicho circuito. Las señales PWM son comúnmente usadas para el control de motores DC (si decrementas la frecuencia, la inercia del motor es más pequeña y el motor se mueve más lentamente), para ajustar la intensidad de brillo de un LED, para hacer sonar una frecuencia en un oscilador piezo eléctrico, etc.
Recuerda que la frecuencia (Hz) es la inversa del periodo (s)
Es el método por el cual Arduino usa ciertos puertos digitales para generar salidas analógicas llamadas PWM (Pulse Width Modulation). El ancho del tren de pulsos o Duty-cicle determinar la potencia entregada a dicho circuito. Si, por ejemplo, tenemos una amplitud de pulso de 5 V y lo modulamos con un duty cycle del 10%, obtenemos 0.5 V de señal analógica de salida.
En los Arduinos con ATmega 168 y ATmaga 328p, únicamente funciona en seis (6) pines digitales: 3, 5, 6, 9, 10 y 11, todos funcionan a una misma frecuencia de 490 Hz y no se puede cambiar. El valor de PW (Pulse Width) representa el ancho del pulso en tiempo, debe estar entre 0~255.
analogWrite(pin, PW);
Existe un parámetro asociado o que define a la señal PWM, denominado "Duty cycle", el cual determina el porcentaje de tiempo que el pulso está en estado activo (on) durante un ciclo.
Esta instrucción sirve para escribir un pseudo-valor analógico usando el procedimiento de modulación por ancho de pulso (PWM) a uno de los puertos digitales tipo PWM de Arduino por los pines 9 o 10, que es una señal de frecuencia constante (30769 Hz) y que sólo nos permite cambiar el "duty cycle" o el tiempo que el pulso está activo (on) o inactivo (off), usando la función analogWrite(). El valor que se puede enviar a estos pines de salida analógica puede darse en forma de variable o constante, pero siempre con un margen entre 0~255.
% | Valor | Salida V |
---|---|---|
0 | 0 | 0 |
25 | 64 | 1.25 |
50 | 127 | 2.50 |
75 | 191 | 3.75 |
100 | 255 | 5 |
Donde pin puede ser 3, 5, 6, 9, 10 o 11. Valor puede ser entre 0~255.
analogWrite(3, 0); // Pone 0V analogWrite(5, 127); // Pone 2.5V analogWrite(9, 255); // Pone 5V
Debido a que esta es una función de hardware, en el puerto PWN se generará una onda constante después de ejecutada la instrucción analogWrite() hasta que se llegue a ejecutar otra función analogWrite() o una llamada a digitalRead() o digitalWrite() en el mismo pin.
Si enviamos el valor 0 genera una salida de 0 voltios en el pin especificado; un valor de 255 genera una salida de 5 voltios de salida en el pin especificado. Para valores de entre 0 y 255, el pin saca tensiones entre 0 y 5 voltios - el valor HIGH de salida equivale a 5V. Teniendo en cuenta el concepto de señal PWM , por ejemplo, un valor de 64 equivaldrá a mantener 0 voltios de tres cuartas partes del tiempo y 5 voltios a una cuarta parte del tiempo; un valor de 128 equivaldrá a mantener la salida en 0 la mitad del tiempo y 5 voltios la otra mitad del tiempo, y un valor de 192 equivaldrá a mantener en la salida 0 voltios una cuarta parte del tiempo y de 5 voltios de tres cuartas partes del tiempo restante.
Otra forma de generar señales PWM es usando la capacidad del microprocesador. La señal de salida obtenida de un microprocesador es una señal digital de 0 voltios (LOW) y de 5 voltios (HIGH). Con el siguiente código y con sólo realizar modificaciones en los intervalos de tiempo que el pin seleccionado tenga valor HIGH o LOW, a través de la función digitalWrite(), generamos la señal PWM.
void setup(){ pinMode(4, OUTPUT); } void loop(){ digitalWrite(4, HIGH); delay(500); digitalWrite(4, LOW); delay(500); }
Es claro que aquí el pin puede ser cualquier digital.
Con el siguiente código y con sólo realizar modificaciones en los intervalos de tiempo que el pin seleccionado tenga valor HIGH o LOW, a través de la función digitalWrite(), generamos la señal PWM a una determinada frecuencia según la tabla.
int PW = 1136; //Para generar 440 Hz void setup(){ pinMode(10,OUTPUT); } void loop(){ digitalWhite(10, HIGH); delayMicroseconds(PW); digitalWhite(10, LOW); delayMicroseconds(PW); }
El programa pone el puerto a HIGH una vez por segundo, la frecuencia que se genera en dicho puerto es de 1 pulso por segundo (1 Hz). Cambiando la temporización del programa, podremos cambiar la frecuencia de la señal. Por ejemplo, si cambiamos las dos líneas con delay(500) a delay(250), multiplicaremos la frecuencia por dos, de forma que estamos enviando el doble de la cantidad de pulsos por segundo que antes (2 Hz).
La función tone(), genera una onda cuadrada de la frecuencia especificada (con duty cycle de 50%) en un pin. Se puede especificar una duración, de lo contrario, la ola continúa hasta que se llame a la función noTone(). El pin se puede conectar a un zumbador piezo eléctrico u otro altavoz para reproducir tonos.
tone(pin, frecuencia); tone(pin, frecuencia, duración);
Solo se puede generar un tono a la vez. Si ya se está reproduciendo un tono en un pin diferente, la llamada a la función tono() no tendrá efecto. Si el tono se reproduce en el mismo pin, la llamada establecerá su frecuencia.
La función tone() tomando control de uno de los temporizadores internos de ATmega, configurándolo a la frecuencia que desee y usando el temporizador para pulsar un pin de salida. Como solo usa un temporizador, solo puede tocar una nota a la vez. Sin embargo, puede tocar notas en diferentes pines, de forma secuencial. Para hacer esto, necesita apagar el temporizador por un pin antes de pasar al siguiente.
void loop ( ) { //Desactivar la función de tono para el pin 8: noTone(8); //Reproducir una nota en el pin 6 durante 200 ms: tono(6, 440, 200); delay(200); //Desactiva la función de tono para el pin 6: noTone(6) ; //Reproduce una nota en el pin 7 durante 500 ms: tono(7, 494, 500); delay(500); //Desactiva la función de tono para el pin 7: noTone(7); //Reproduce una nota en el pin 8 durante 300 ms: tono(8, 523, 300); delay(300) ; }
El uso de la función tone() interferirá con la salida de PWM en los pines 3 y 11. No es posible generar tonos inferiores a 31 Hz.
Nota | Tone Hz | PW |
---|---|---|
c | 261 | 1915 |
d | 294 | 1700 |
e | 329 | 1519 |
f | 349 | 1432 |
g | 392 | 1275 |
a | 440 | 1136 |
b | 493 | 1014 |
C | 823 | 956 |
Es posible alterar la frecuencia base de una pareja pines PWM, usando un divisor distinto. Tenga en cuenta que cambiar la frecuencia de PWM cambia los temporizadores de ATmega e interrumpe el funcionamiento normal de muchas funciones que dependen del tiempo como delay(), millis(), Servo library(), etc.
Pines | Función | Frecuencia base | Divisores |
---|---|---|---|
3 y 11 | timer2() | 31250 Hz | 1, 8, 32, 128, 256 y 1024 |
9 y 10 | timer1() | 1, 8, 64, 256 y 1024 | |
5 y 6 | timer() | 62500 Hz |
setPwmFrequency(pin, divisor);
Veamos algunos ejemplos prácticos.
setPwmFrequency(6,1); //32500/1 = 62500 Hz setPwmFrequency(9,8); //31250/8 = 3906 Hz setPwmFrequency(10,1024); //31250/1024 = 31 Hz
Aquí esta descrita la función setFrecuency() explicada mas arriba
void setPwmFrequency(int pin, int divisor) { byte mode; if (pin == 5 || pin == 6 || pin == 9 || pin == 10) { switch (divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 64: mode = 0x03; break; case 256: mode = 0x04; break; case 1024: mode = 0x05; break; default: return; } if (pin == 5 || pin == 6) { TCCR0B = TCCR0B & 0b11111000 | mode; }else{ TCCR1B = TCCR1B & 0b11111000 | mode; } }else if (pin == 3 || pin == 11) { switch (divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 32: mode = 0x03; break; case 64: mode = 0x04; break; case 128: mode = 0x05; break; case 256: mode = 0x06; break; case 1024: mode = 0x07; break; default: return; } TCCR2B = TCCR2B & 0b11111000 | mode; } }
La librería TimeOne actúa sobre los puertos D9 y D10 en Arduino UNO.
Los pines 0 (RX) osea la entrada y 1 (TX) osea la salida, son el puertos serie, se usan para comunicación entre dispositivos. La característica principal de los puertos serie es que envían la información bit a bit, enviando un bit cada vez. En una computadora el puerto serie se usa para conectar como teclados, mouses, módems, impresoras, etc.
Los pines 0 (Rx) y 1 (Tx) son el puerto serie. Pasa saber mas del puerto serie
Serial Peripherical Interdace (SPI) es un protocolo de datos en serie síncrono usado por los uC para comunicarse rápidamente con uno o más dispositivos periféricos en distancias cortas. También se puede usar para la comunicación entre dos uC. Con una conexión SPI, siempre hay un dispositivo maestro (generalmente el uC) que controla los dispositivos periféricos. Normalmente, hay tres líneas comunes a todos los dispositivos: MISO, MOSI y CLK y una linea SS por cada esclavo.
En Arduino UNO los pines 10, 11, 12 y 13 son los pines SPI. Para saber mas del bus SPI
Inter Integrated Circuit (I2C) o también llamada de 2 alambres, es otro protocolo de comunicación muy parecida al SPI también sirve para conectar varios dispositivos. Cada dispositivo debe tener una dirección única en el rango de 8~119. En este tipo de comunicación cada dispositivo tiene una dirección única y cada dispositivo puede funcionar como Master o Slave. En Arduino UNO el SDA (Serial Data Line) (pin A4) y se usa para la transmisión de datos en serie. El SCL (Serial Clock Line)(pin A5) suministra la señal de reloj para mantener el sincronismo.
En Arduino UNO los pines A4 (SDA) y A5 (SCL) son los pines I2C. Para saber mas del bus I2C
Los pines digitales 2 y 3 nos permiten interrumpir el funcionamiento del bucle loop(). Estos pines detienen precisamente ese bucle y obligan a ejecutar un código asignado a cada pin.
En Arduino UNO los pines 2 y 3 soportan interrupciones. Para saber mas de las Interrupciones.
La función AnalogReference, configura la tensión de referencia para las entradas analógicas. Existe un pin Aref que es el pin que nos suministra la tensión para el rango máximo de los puertos analógicos, normalmente 5V.
analogReference(tipo);
Donde tipo puede ser:
Después de cambiar la referencia analógica, las primeras lecturas de analogRead () puede que no sean exactas.
No use nunca tensión menor de 0V o mayor de 5V en pin AREF. Si está usando una referencia externa en el pin AREF, debe establecer la referencia analógica a EXTERNAL antes de llamar a la función analogRead(), dDe lo contrario se produce un cortocircuito entre la tensión de referencia interna y la tensión aplicada al pin AREF, dañando el uC de la placa Arduino. Como alternativa, puede conectar la tensión de referencia externa al pin AREF a través de una resistencia de 5K, que le permite cambiar entre las tensiones de referencia externa e internas. Tenga en cuenta que la resistencia va a alterar la tensión que se usa como referencia porque hay una resistencia interna de 32 K en el pin AREF. Las dos actúan como un divisor de tensión, por lo que, por ejemplo, 2V5 aplicados a través de la resistencia producirá 2V2 (2.5 * 32 / (32 + 5)) en el pin AREF.
Input Output Reference, es el pin que nos suministra la tensión para el estado HIGH de los pines digitales. Por norma general si conectamos el Arduino a 5V este pin nos dará 5V, en caso contrario serán 3V3.
Es un pin de entrada de alimentación hacia el regulador (NCP1117) de 5V de la placa Arduino por lo que puedes poner entre 6~12V. Esta entrada no está protegida y por lo tanto hay que tener un especial cuidado con el voltaje que suministramos ya que podemos quemar el regulador.
A esta entrada se le llama PWRin y esta protegida contra polaridad inversa por un diodo. Al otro lado del diodo esta Vin.