Lo que realmente hace muy versátil al Arduino es que su entorno se puede ampliar mediante el uso de librerías, al igual que la mayoría de las plataformas de programación. Una librerías proporcionan una funcionalidad adicional para usar en el Arduino, por ejemplo: trabajar con algún modulo (hardware especifico) o manipular datos. Para usar una librería selecciónela desde el IDE y dele a Importar librería. Las librerías mas comunes ya vienen instaladas con el IDE, pero Ud puede descargar mas librerías desde el repositorio oficial que tiene 1529 librerías (18-MAY-2017) y puedes encontrar algunas referencias de uso en referencias de librerías, la comunidad que lo soporte o crear las suyas propias.
Arduino = hardware + software + comunidad
La librería Time.h
Método | Descripción |
---|---|
year() | Año de 4 dígitos, 2018 |
month() | Mes del año (1~12) |
day() | Dia del mes (1~31) |
weekday() | Dia de la semana. 1 = sábado |
hour() | Horas (0~23) |
minute() | Minutos (0~59) |
second() | Segundos (0~59) |
hourFormat12() | Formatea la hora en 0~12 |
isAM() | Verdadero y es AM |
isPM() | Verdadero si es PM |
now() | Hora unix actual en segundos. Desde 1-ENE-1970. |
time_t t = now(); //Guarda la hora actual Unix hour(t); //Da los horas minute(t); //Da los minutos second(t); //Da los segundos
Funcion | Descripción |
---|---|
monthStr() | Mes del año (1~12) |
monthShortStr() | Mes del año (1~12) |
dayStr() | Dia del mes (1~31) |
dayShortStr() | Dia del mes (1~31) |
setTime() | Establece fecha |
adjustTime() | Ajusta fecha |
timeStatus() | Indica si la hora esta puesta |
setSyncProvider(getTimeFunction) | Pone un proveedor externo |
setSyncInterval(seg) | Intervalo entre re-sincronizaciones. |
time_t t = now(); //Guarda la hora actual Unix monthStr(t); //No funciona monthStr(month(t)); //Si funciona dayStr(weekday(t)); //Si funciona setTime(22,30,00,14,07,2018);
Las posibles respuestas de timeStatus() son: timeNotSet (1-ENE-1970, no disponible); timeNeedSync la hora debe ser sincronizada y timeSet.
if (timeStatus() == timeNotSet){ Serial.println("Esperando para sincronizar"); }else{ Serial.print(hour()); Serial.print(":"); Serial.print(minute()); Serial.print(":"); Serial.println(second()); }
La librería RTClib.h permite simular fecha & hora mediante un estimado partiendo de la hora de inicio de Arduino y sumando los millis() transcurridos. No requiere hardware adicional.
#include <Wire.h> #include <RTClib.h> RTC_Millis rtc; void setup () { Serial.begin(57600); //Toma como referencia de fecha & hora de compilacion rtc.begin(DateTime(F(__DATE__), F(__TIME__))); //11 de marzo del 2018 a las 7 pm //rtc.adjust(DateTime(2018, 3, 11, 17, 0, 0)); } void loop () { DateTime hoy = rtc.now(); Serial.print(hoy.year(), DEC); Serial.print('-'); p2dig(hoy.month()); Serial.print('-'); p2dig(hoy.day()); Serial.print(' '); p2dig(hoy.hour()); Serial.print(':'); p2dig(hoy.minute()); Serial.print(':'); p2dig(hoy.second()); Serial.print('.'); p3dig(millis()%1000); Serial.println(); delay(1500); } //Funcion para imprimir siempre 2 digitos void p2dig(int num) { if (num < 10) { Serial.print('0'); } Serial.print(num); } //Funcion para imprimir siempre 2 digitos void p3dig(int num) { if (num < 100) { Serial.print('0'); if (num < 10) { Serial.print('0'); } } Serial.print(num); }
La libreria NTPClient.h esta GitHub permite controlar que un Arduino mediante una conexion: ethernet o WiFi, consulte un servidor horario como ntp.org. Por omision se conecta al servidor "time.nist.gov" cada 60 segundos sin cambio de zona horaria.
NTPClient timeClient(ntpUDP, "pe.pool.ntp.org", -18000, 86400); //Servidor, Zona (-5 hr), intervalo (diario)
Método | Descripción |
---|---|
begin() | Inicia servicio |
setTimeOffset() | Cambiar la zona horaria (segundos) |
setUpdateInterval() | Cambiar el intervalo de actualización (segundos) |
update() | Hace una actualización y da TRUE si lo logra |
forceUpdate() | Fuerza una actualización y da TRUE si lo logra |
getDay() | Dia de la semana 0=domingo |
getHours() | Horas |
getMinutes() | Minutos |
getSeconds() | Segundos/td> |
getFormattedTime() | Cadena h:m:s |
getEpochTime() | UnixTimeStamp, segundos desde 1970. |
end() | Finaliza servicio |
#include <ESP8266WiFi.h> #include <NTPClient.h> #include <WiFiUdp.h> const char *ssid = "<SSID>"; const char *password = "<CLAVE>"; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP); //NTPClient timeClient(ntpUDP, "pe.pool.ntp.org", -18000, 86400); void setup(){ Serial.begin(115200); WiFi.begin(ssid, password); Serial.println(""); Serial.print("WiFi"); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); } Serial.println(""); Serial.print("IP: "); Serial.println(WiFi.localIP()); timeClient.begin(); Serial.print("NTP"); while (!timeClient.update()){ Serial.print("."); delay(500); } Serial.println(""); } void loop() { Serial.println(timeClient.getFormattedTime()); delay(1000); }
La librería Wire.h permite la comunicación entre dispositivos o sensores conectados a través del bus de interfaz de dos hilos I2C. En Arduino UNO R3, la SDA (línea de datos) es pin A4 y SCL (línea de reloj) es pin A5.
A partir de Arduino 1.0, la biblioteca hereda de las funciones Stream, lo que la hace compatible con otras bibliotecas de lectura/escritura. Debido a esto, send() y receive() han sido reemplazados por read() y write().
Hay versiones de 7 y 8 bits de direcciones I2C. 7 bits identifican el dispositivo, y el octavo bit determina si se está escribiendo o leyendo. La biblioteca Wire usa direcciones de 7 bits en todo momento. Si tiene una hoja de datos o un código de muestra que usa una dirección de 8 bits, querrá soltar el bit bajo (es decir, desplazar el valor un bit hacia la derecha), obteniendo una dirección entre 0 y 127. Sin embargo, las direcciones de 0 a 7 no se usan porque están reservados, por lo que la primera dirección que se puede usar es 8. Tenga en cuenta que se necesita una resistencia de pull-up al conectar los pines SDA/SCL.
La biblioteca Wire usa un búfer de 32 bytes, por lo tanto, cualquier comunicación debe estar dentro de este límite. El exceso de bytes en una sola transmisión simplemente se eliminará.
La librería SPI.h permite comunicarse via Bus SPI (Serial Peripheral Interface), con el Arduino como dispositivo maestro.
SPI es un protocolo de datos en serie sincronía 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 uP. Con una conexión SPI, siempre hay un dispositivo maestro (generalmente un uP) que controla los dispositivos periféricos. Normalmente, hay tres líneas comunes a todos los dispositivos:
Nombre | Descripción | Pin Arduino |
---|---|---|
MISO | La línea esclava para enviar datos al maestro. (Master In Slave Out) | 12 o ICSP-1 |
MOSI | La línea maestro para enviar datos a los periféricos. (Master Out Slave In) | 11 o ICSP-4 |
SCK | Los pulsos de reloj que sincronizan la transmisión de datos generada por el maestro. (Serial Clock) | 13 o ICSP-3 |
SS | Pin en cada dispositivo que el maestro puede usar para habilitar y deshabilitar dispositivos específicos. (Slave Select) | 10 |
Cuando el pin de SS de un dispositivo está LOW, se comunica con el maestro. Cuando es HIGH, ignora al maestro. Esto le permite tener múltiples dispositivos SPI compartiendo las mismas líneas MISO, MOSI y CLK, pero comunicarse solo con uno la la vez. Con la mayoría de los dispositivos SPI, después SPI.beginTransaction(), escribirá el pin SS a LOW, invoque SPI.transfer() las veces que necesite para transferir datos, luego escriba el pin SS a HIGH y finalmente llamará SPI.endTransaction() para liberar SPI.
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0)); SPI.transfer() SPI.endTransaction()
La librería Firmata.h permite la comunicación con aplicaciones informáticas usando un protocolo serie estándar. La librería Firmata implementa el protocolo Firmata para comunicarse con el software en una computadora host. Esto le permite escribir firmware personalizado sin tener que crear su propio protocolo y objetos para el entorno de programación que está usando. Para saber mas de Firmata.
Windows 10 implementa el protocolo Firmata de forma nativa.
La librería ???.h esta librería permite controlar un Arduino (Uno, Leonard o Mega) mediante una conexion: USB, bluetooth, ethernet o WiFi. Esta librería se apoya en el protocolo Firmata. Existe una aplicación llamada Universal Windows Arduino (UWA) que permite explorar las funcionalidades GPIO, analog y PWM desde cualquier dispositivo ejecutando Windows 10.
Un controlador Proporcional Integral Derivativo PID calcula un valor de 'error' como la diferencia entre una entrada [Input] medida y un punto de referencia [setPoint] deseado. El controlador intenta minimizar el error ajustando la salida [Output]. La librería PID_v1.h requiere de tres paramentos kp, ki y kd.
Existe una libreria PID Autotune que te puede ayudar a elegir los parámetros de ganancia: kp (proporcional), ki (integral) y kd (derivada).
PID(&Input, &Output, &Setpoint, Kp, Ki, Kd, Direction);
Aunque un controlador PID está diseñado para funcionar con una salida analógica, es posible conectarlo a una salida didital, como un relé. En este caso se debe definir un ciclo de trabajo y lo que hace el PID en establecer la proporcion entre HIGH y LOW mediante los metodos: SetSampleTime(ciclo) y SetAoutputLimits(min,max)
Método | Descripción |
---|---|
Computer() | Calcula una nueva salida cada ciclo. Responde verdadero si se calculo. |
SetMode(modo) | Especifica si PID esta AUTOMATIC o MANUAL |
SetOutputLimits(min,max) | Especifica el rango de salida |
SetSampleTime(ciclo) | Determina el ciclo, predetreminado es 200 ms |
SetTunings(kp,ki,kd) | Permite reajustar los parámetros iniciales de reaccion del PID |
SetControlDirection(dirección) | Especifica si la salida es DIRECT o REVERSE. |
Lectura de entrada analogica A0 para controlar salida analogica PWM D3
#include <PID_v1.h> float Input, Output, Setpoint; PID miPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT); void setup(){ Setpoint = 100; miPID.SetMode(AUTOMATIC); } void loop(){ Input = analogRead(0); miPID.Compute(); //Señal PWM analogWrite(3,Output); }
Lectura de entrada analogica A0 para controlar salida digital D6 con un ciclo de trabajo de 5 segundos. Por eso se establece la salida del PID entre 0 y 5 segundos de modo que el PID ajustara el % de tiempo que el rele esta activado durante cada ciclo.
#include <PID_v1.h> float Input, Output, Setpoint; PID miPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT); int ciclo = 5000; unsigned long StartTime, now; void setup(){ pinMode(6, OUTPUT); Setpoint = 100; miPID.SetOutputLimits(0, ciclo); miPID.SetMode(AUTOMATIC); StartTime = millis(); } void loop(){ now = millis(); if (now - StartTime > ciclo){ StartTime += ciclo; } Input = analogRead(0); miPID.Compute(); if (Output > now - StartTime){ digitalWrite(6, HIGH); }else{ digitalWrite(6, LOW); } }
Uno de los beneficios de la esta libreria es que se puedes cambiar los parámetros de ajuste (kp, ki, kd) en cualquier momento. Esto puede ser útil si queremos que el PID sea agresivo algunas veces y conservador en otros.
#include <PID_v1.h> float Input, Output, Setpoint; float aggKp=4, aggKi=0.2, aggKd=1; //PID agresivo float consKp=1, consKi=0.05, consKd=0.25; //PID conservador PID miPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT); void setup(){ pinMode(3, OUTPUT); Setpoint = 100; miPID.SetMode(AUTOMATIC); } void loop(){ Input = analogRead(0); double gap = abs(Setpoint-Input); if (gap<10){ miPID.SetTunings(consKp, consKi, consKd); }else{ miPID.SetTunings(aggKp, aggKi, aggKd); } miPID.Compute(); //Señal PWM analogWrite(3,Output); }
Configurar el PID para usar P_ON_M hacer que la salida se mueva más suavemente cuando el punto de ajuste (Setpoint) está cambiado. Además, puede eliminar el sobrepico en ciertos procesos. Las opciones son: P_ON_M (Proportional ON Measurement) y P-ON_E (Proportional ON Err).
#include <PID_v1.h> float Input, Output, Setpoint; PID miPID(&Input, &Output, &Setpoint, 2, 5, 1, P_ON_M, DIRECT); void setup(){ pinMode(3, OUTPUT); Setpoint = 100; miPID.SetMode(AUTOMATIC); } void loop(){ Input = analogRead(0); miPID.Compute(); //Señal PWM analogWrite(3, Output); }