Arduino IoT: Tutorial Simple Programar ATtiny85

Arduino Honduras Santiapps Marcio Valenzuela

Tutorial Simple Programar ATtiny85

 

En algun momento llegaremos a querer reducir el tamaño de nuestros proyectos por ejemplo para “wearables”, proyectos usados como vestimenta por la gente.

Aqui aprovechamos a programar la ATtiny85 via una Arduino UNO R3, aunque es posible obtener programadores standalone.

Esta es la ATTiny85 comparada con la ATmel y la Arduino UNO R3:

Arduino IoT: Tutorial Programming ATtiny85 via Arduino UNO R3 ArduinoISP by Santiapps Marcio Valenzuela
Arduino IoT: Tutorial Programming ATtiny85 via Arduino UNO R3 ArduinoISP

Como podemos ver, no solo en tamaño sino que en componentes, la ATtiny85 tendrá la ventaja de consumo energético ademas de espacio.

Primero, tenemos que actualizar nuestro Arduino IDE para poder interface con una ATtiny85.  Esto lo hacemos en Preferences y Boards Manager:

https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json

Segundo, debemos cargar el sketch de ArduinoISP en el Sketchbook del Arduino IDE a la Arduino UNO R3 que vamos a usar como ISP.

Board: UNO > ATTiny85 (Clock 1, 8 o 16MHz)

Progr: AVRISPMkII > Arduino as ISP

Tercero, debemos hacer las conexiones entre la UNO R3 y la ATtiny85:

Arduino IoT: Tutorial Programming ATtiny85 via Arduino UNO R3 ArduinoISP by Santiapps Marcio Valenzuela
Arduino IoT: Tutorial Programming ATtiny85 via Arduino UNO R3 ArduinoISP

Cuarto, vamos a cargar el sketch de Blink al ATtiny85 pero haciendo la siguiente modificación al codigo, cambiamos el pin 13 por el pin 0 porque la ATtiny85 no tiene tantos pines:

int ledpin = 0;
void setup() {
pinMode(ledpin, OUTPUT);
}
void loop() {
digitalWrite(ledpin, HIGH); 
delay(2500); 
digitalWrite(ledpin, LOW); 
delay(2500); 
}

Ahora cargamos el sketch Blink-modificado a la ATtiny85 modificando los parámetros de board y puerto para acceder a la tiny via la UNO.

Finalmente podemos ver los resultados:

OJO

Arduino IoT: Tutorial Programming ATtiny85 via Arduino UNO R3 ArduinoISP by Santiapps Marcio Valenzuela
Arduino IoT: Tutorial Programming ATtiny85 via Arduino UNO R3 ArduinoISP

Arduino IoT: RTD PT 100 Sensores Industriales Parte II

Arduino IoT Arduino (IoT): Simple Tutorial de Infrarojo (IR) Receptor/Transmisor by Santiapps Marcio Valenzuela
Arduino IoT Arduino (IoT): Simple Tutorial de Infrarojo (IR) Receptor/Transmisor

Arduino (IoT): RTD PT 100 Sensores Industriales Parte II

 

Arduino IoT: RTD PT-100 Sensores Industriales by Santiapps Marcio Valenzuela
Arduino IoT: RTD PT-100 Sensores Industriales

En el tutorial anterior vimos como obtener resultados de un sensor industrial, PT100.  3 puntos importantes a recalcar:

  1. PT100 es un sensor muy sensible.  De hecho PT100 viene de “Pt” el símbolo para platino, que es un elemento usado por su confiabilidad.  Su resistencia varia de manera constante y confiable a lo largo de un gran rango de temperaturas.  Es esta resistencia la que medimos para obtener nuestros datos.
  2. La resistencia del circuito esta ligada al Voltage pero los voltajes son muy sensibles a ruido y podríamos confundir ruido de las lineas de transmisión con mediciones reales.  Por tanto usamos la corriente que es mucho mas estable y también esta relacionada a la R y V, según V=IR.  Para medir la corriente usamos un transmisor 4/20mA current loop.  Este aparato mide corriente y esa corriente es la que usamos para calcular la resistencia y convertirla a temperatura.
  3. Uno de los puntos mas importantes de cualquier medición es que las mediciones son instantáneas.  Es decir, se toman en un instante y muchas cosas pueden pasar entre un instante y otro.  Esto da como resultado varianzas que deben ser eliminadas.  Para ello es importante tomar varias muestras y obtener un promedio.  Existen cómputos estadísticos mas sofisticados que se pueden emplear para eliminar ruido y valores extremos pero por ahora veremos el mas sencillo, el promedio.

Realmente lo que debemos hacer es tomar varias muestras a lo largo del tiempo, almacenarlas y tomar un promedio de ellas. En programación podemos almacenar un gran grupo de datos en una estructura llamada arreglos, o arrays.  En Arduino definimos un array asi:

float analogVals[numReadings];

Aqui decimos que el array de nombre analogVals sera te valores tipo float y tendrá un cierto numero de elementos o items según la cantidad numReadings.

//Array vars
const unsigned int numReadings = 100;
float analogVals[numReadings];
unsigned int i = 0;

Aqui definimos el valor de numReadings en 100 y creamos un valor contador “i” iniciando con valor 0.  Este lo usaremos para incrementarlo cada vez que agreguemos un nuevo valor de temperatura al array y lo compararemos contra el numReadings de 100.  Al llegar a 100 valores, tomaremos el promedio.

analogVals[i] = f1;
if (i>=numReadings) {
//2. get average and go to test logic
float theAvgIs = average(analogVals,i);
//3. call logic
logicAction(theAvgIs);
i=0; //reset
} else {
i++;
}

Dentro del loop, almacenamos el valor del sensor, f1 y lo almacenamos en la primera posición del array analogVals[0] porque i empieza en 0.

Luego hacemos una prueba, si “i” ya llego a ser mayor o igual a 100, promediamos, de otra manera, solo le sumamos 1 a i, usando i++, y ahora i = 1 y volvemos al loop para tomar otra medicion.

Eventualmente cada vez que tomemos una medición y le sumemos 1 a i, i llegara a 100.  En ese momento ya hemos almacenado 100 valores en nuestro array y podemos hacer cálculos.

float average (float * array, int len){
float sum = 0L ;
for (int i = 0 ; i < len ; i++)
sum += array [i] ;
return ((float) sum) / len ;
}

En ese entonces llamamos esta función pasándole el array completo y su numero de elementos.  Esta función suma los valores del arreglo y los va almacenando en la variable sum.  Al final divide ese total entre len, el valor de items en el array para darnos un promedio y lo regresa al loop.

Regresando al loop ponemos ese valor en theAvgIs y lo pasamos a la función siguiente para tomar una decision sobre la lectura:

void logicAction(float thisIsIt){
if (thisIsIt > 20.0){
//its hot
Serial.println(“done…>20”);
Serial.println(thisIsIt);
} else {
//its cold
Serial.println(“done…<20”);
Serial.println(thisIsIt);
}
}

Aqui vemos que si el valor pasado es > a 20, esta caliente y si es menor a 20 esta frío.  En ese caso tomaríamos la accion en base a cada posibilidad, como cerrar válvulas, incrementar calor de la caldera etc.

Al final los resultados son:

Arduino IoT: RTD PT-100 Sensores Industriales by Santiapps Marcio Valenzuela
Arduino IoT: RTD PT-100 Sensores Industriales

Como podemos observar,  al calentar el sensor arriba de 20, la respuesta cambia y podríamos tomar las acciones necesarias.

Recordemos que hay otras mejoras; por ejemplo aquí esperamos a volver a llenar el array con 100 valores nuevos para obtener un nuevo promedio y poder comparar con lo deseado y tomar acciones.  Esperar 100 mediciones es bastante tiempo.  Podríamos ir llenando valores nuevos para reemplazar los mas viejos en el array, y tomar otro promedio al tener 10 nuevos y 90 viejos.  Así el promedio se actualizaría mas seguido y podríamos tomar mejores decisiones.

Arduino IoT: Tutorial Medidor de Agua Inteligente

Arduino Honduras Santiapps Marcio Valenzuela

Tutorial Medidor de Agua Inteligente Parte I

 

En este tutorial exploraremos mas sensores, pero aplicados.  En nuestro proyecto usamos un flujo metro construido a partir de un sensor Hall Effect para medir el flujo de agua por un conducto.

Se mira asi:

Arduino IoT: Tutorial Medidor de Flujo by Santiapps Marcio Valenzuela
Arduino IoT: Tutorial Medidor de Flujo de Agua by Santiapps

El codigo:

byte statusLed = 13;
byte sensorInterrupt = 0; // 0 = digital pin 2
byte sensorPin = 2;
// El sensor hall-effect emite ~ 4.5 pulses/sec/litre/min 
float calibrationFactor = 4.5;
volatile byte pulseCount;
float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;
unsigned long oldTime;
void setup(){

Serial.begin(38400);
// Usarmos una LED como salida
pinMode(statusLed, OUTPUT);
digitalWrite(statusLed, HIGH);
pinMode(sensorPin, INPUT);
digitalWrite(sensorPin, HIGH);
pulseCount = 0;
flowRate = 0.0;
flowMilliLitres = 0;
totalMilliLitres = 0;
oldTime = 0;

// Configuramos para que dispare con FALLING state (HIGH a LOW)
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
void loop(){
if((millis() - oldTime) > 1000) { // Only process counters once per second
// Dishabilitamos el interrupt al calcular flujo y enviar
detachInterrupt(sensorInterrupt);
// Calculamos ms transcurridos desde la ultima ejecucion para escalar el resultado. Aplicamos el factor calibrationFactor para escalar el resultado en base al # de pulsos/sec de medición (litres/minute en este caso) proveniente del sensor
flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
// Usar el tiempo de esta ejecucion porque deshabilitamos el interrupt por ende los millis() no funcionaran pero aun asi se retornara el valor justo antes que se deshabilito
oldTime = millis();
// Dividir el flujo en litres/minute por 60 para determinar cuantos L han pasado por el sensor en el intervalo de 1 sec y luego multiplicamos por 1000 para convertir a mL.
flowMilliLitres = (flowRate / 60) * 1000;
// Sumamos los mL pasados en este segundo al total cumulativo
totalMilliLitres += flowMilliLitres;
unsigned int frac;
// Imprimir el flujo para este intervalo de 1 segundo en litres / minute
Serial.print("Flujo: ");
Serial.print(int(flowRate)); // Imprimir el entero
Serial.print("."); // Imprimir el decimal
// Determinar la fraction. El 10 multiplicador nos da 1 decimal.
frac = (flowRate - int(flowRate)) * 10;
Serial.print(frac, DEC) ; // Imprimir la parte fraccional
Serial.print("L/min");
// Imprimir L fluidos en este segundo
Serial.print(" Liquido Fluido reciente: "); // Separador
Serial.print(flowMilliLitres);
Serial.print("mL/Sec");
// Imprimir cumulativo de L fluidos desde el inicio
Serial.print(" Cantidad total fluido: "); // Separador
Serial.print(totalMilliLitres);
Serial.println("mL");
// Resetear el pulse counter para iniciar de nuevo
pulseCount = 0;
// Habilitar el interrupt nuevamente
attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}
}
void pulseCounter(){
// Incrementar pulse counter
pulseCount++;
}

Y la connexion es sencilla:

Arduino IoT: Tutorial Medidor de Flujo de Agua by Santiapps Marcio Valenzuela
Arduino IoT: Tutorial Medidor de Flujo de Agua

Lo conectamos a una salida de agua como una bañera:

Arduino IoT: Tutorial Medidor de Flujo de Agua by Santiapps Marcio Valenzuela
Arduino IoT: Tutorial Medidor de Flujo de Agua

Los resultados:

Arduino IoT: Tutorial Medidor de Flujo de Agua by Santiapps Marcio Valenzuela
Arduino IoT: Tutorial Medidor de Flujo de Agua

Esto fue durante ~ 10 segundos.  Vamos a incorporar esto a nuestro proyecto de casa inteligente.