Está en la página 1de 15

Integración de Sistemas en

la nube

Interrupciones
Contenidos :

● Interrupciones
● Manejo de intervalos de Tiempo
● Interrupciones por timer y Control de periodos de tiempo
● Codigo ejemplo de leer dos sensores:uno cada medio segundo procesar los datos y
acumularlos el segundo sensor se leera cada 15 minutos. Ambos datos se enviaran cada
15 minutos
● Codigo ejemplo de enviar datos de dos sensores a base de datos via wifi :uno cada medio
segundo procesar los datos y acumularlos el segundo sensor se leera cada 15 minutos.
Ambos datos se enviaran cada 15 minutos . los datos tambien se enviaran a hoja de
excell via wifi

Las interrupciones

https://tecmikro.com/content/68-interrupciones-microcontroladores-pic

Las interrupciones son eventos que hacen que el microcontrolador deje de realizar la tarea
actual y pase a efectuar otra actividad. Al finalizar la segunda actividad retorna a la primera
y continúa a partir del punto donde se produjo la interrupción. Las interrupciones permiten
que un solo microcontrolador ejecute varias tareas (no exactamente al mismo tiempo)
dependiendo del evento que desencadene la interrupción. Estos dispositivos tienen desde
10 hasta 15 fuentes de interrupción dependiendo del tipo específico de microcontrolador. El
manejo de las interrupciones se programa por medio de registros especiales que controlan
el comportamiento del microcontrolador bajo determinadas circunstancias.
Cuando se activa una interrupcion se ejecuta un pedazo de codigo llamada manejador de
la interrupcion o Interrupt handler.
Interrupciones por Timer
https://www.electrontools.com/Home/WP/como-usar-las-interrupciones-en-arduino/#:~:text=Inter
rupciones%20por%20Timer,alimentar%20motores%20de%20corriente%20continua.

Estas interrupciones son disparadas cuando se cumple un cierto tiempo que


nosotros mismos definimos, son muy usadas para controlar y leer sensores cada
determinado tiempo y también para crear señales PWM para alimentar motores
de corriente continua.

Como estas interrupciones se ejecutan cada un determinado tiempo, somos


dependientes del cristal y del tiempo de cada pulso de clock de nuestro arduino.
Pero gracias a que utilizamos librerías no tenemos que hacer ninguna cuenta, es
importante saber que somos dependientes de eso, es decir no es lo mismo tener
un cristal de 32 que uno de 16 MHZ. Pero como todos los arduinos traen un
cristal de 16MHZ no nos preocupemos demasiado.

Los timers tienen algo que se conoce como prescaler, son divisores de la
frecuencia de clock, cuando dividimos la frecuencia ganamos en tiempo pero
perdemos en precisión, la frecuencia del cristal se puede dividor por 1,8,64,256

El siguiente ejemplo ejecuta una interrupcion por timer cada 250ms y prende y
apaga un led cada vez que se la atiende.

#include <TimerOne.h>
const int led = 13; // the pin with a LED
int ledState = LOW; // El LED empieza apagado
volatile unsigned long blinkCount = 0; // La definimos como volatile

void setup(void)
{
pinMode(led, OUTPUT);
Timer1.initialize(250000); // Dispara cada 250 ms
Timer1.attachInterrupt(ISR_Blink); // Activa la interrupcion y la asocia
a ISR_Blink
Serial.begin(9600);
}

void ISR_Blink()
{ ledState = !ledState ;
blinkCount++ ; // Contador veces se enciende el LED
}

void loop(void)
{
unsigned long N; // Haremos copia del blinkCount
digitalWrite(led, ledState); // Asignamos el valor del
// status a la salida
noInterrupts(); // Suspende las interrupciones
N = blinkCount;
interrupts(); // Autoriza las interrupciones

Serial.print("Ciclos = ");
Serial.println(N);
delay(100);

Manejo de intervalos de tiempo y Tiempo Real

Cuando se necesita controlar con precisión el tiempo se pueden usar los timers de los
microcontroladores. Existen dos metodos :

1. Contando ciclos de trabajo(uso funcion millis())


2. Por interrupciones por timer

Se sugiere leer blog: https://programarfacil.com/blog/arduino-blog/millis-micros-arduino/

Contando ciclos de trabajo(uso funcion millis())

La función millis() permite obtener la cantidad de milisegundos que han pasado desde
que comenzó la ejecución del código, es decir, que toma el registro de pulsos generados por
el contador y los emplea para calcular el tiempo en milisegundos.
La sintaxis de la función es muy simple:

1 unsigned long tiempo = millis()

Por ejemplo, si quieres obtener la temperatura de un sensor conectado al A0


cada cinco segundos y que parpadee un LED a la vez cada segundo.
Implemenatcion:

En la función loop() lo primero que se hace es obtener el tiempo actual


ejecutando la función millis() y almacenando su valor en la variable actual. El
valor obtenido representaría la posición de millis() sobre la línea de tiempo.

const unsigned long INTERVALO_TEMP = 5000UL;


const int pinLED = 3;

unsigned long evento_led;


unsigned long evento_temp;

void setup() {
Serial.begin(9600);
pinMode( pinLED, OUTPUT );
}

void toggleLed(){
if( digitalRead( pinLED ) )
digitalWrite(pinLED, LOW);
else
digitalWrite(pinLED, HIGH);
}

void sensor(){
int raw = analogRead(A0);
float temp = ((float)raw)* 5.0 * 100.0 / 1024;

Serial.print( "la temperatura es: " );


Serial.print( temp, 2 );
Serial.println(" C");
}

void loop() {
unsigned long actual = millis();

if( actual > evento_led ){


toggleLed();
evento_led += INTERVALO_LED;
}

if( actual > evento_temp ){


sensor();
evento_temp += INTERVALO_TEMP;
}

// otras acciones

Interrupciones por timer para manejo de tiempos


Tomado de https://www.pjrc.com/teensy/td_libs_TimerOne.html

Interrupt Function

Timer1.attachInterrupt(function);
Run a function each time the timer period finishes. The function is run as an interrupt, so special care is needed to share any
variables beteen the interrupt function and your main program.
Timer1.detachInterrupt();
Disable the interrupt, so the function no longer runs.

Example Program

#include <TimerOne.h>
// This example uses the timer interrupt to blink an LED
// and also demonstrates how to share a variable between
// the interrupt and the main program.

const int led = LED_BUILTIN; // the pin with a LED

void setup(void)
{
pinMode(led, OUTPUT);
Timer1.initialize(150000);
Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.15 seconds
Serial.begin(9600);
}

// The interrupt will blink the LED, and keep


// track of how many times it has blinked.
int ledState = LOW;
volatile unsigned long blinkCount = 0; // use volatile for shared variables

void blinkLED(void)
{
if (ledState == LOW) {
ledState = HIGH;
blinkCount = blinkCount + 1; // increase when LED turns on
} else {
ledState = LOW;
}
digitalWrite(led, ledState);
}

// The main program will print the blink count


// to the Arduino Serial Monitor
void loop(void)
{
unsigned long blinkCopy; // holds a copy of the blinkCount

// to read a variable which the interrupt code writes, we


// must temporarily disable interrupts, to be sure it will
// not change while we are reading. To minimize the time
// with interrupts off, just quickly make a copy, and then
// use the copy while allowing the interrupt to keep working.
noInterrupts();
blinkCopy = blinkCount;
interrupts();

Serial.print("blinkCount = ");
Serial.println(blinkCopy);
delay(100);
}

Interrupt Context Issues


Special design is necessary to share data between interrupt code and the rest of your program.

Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations
that assume variable can not spontaneously change. Because your function may change
variables while your program is using them, the compiler needs this hint. But volatile alone is
often not enough.

When accessing shared variables, usually interrupts must be disabled. Even with volatile, if
the interrupt changes a multi-byte variable between a sequence of instructions, it can be read
incorrectly. If your data is multiple variables, such as an array and a count, usually interrupts
need to be disabled for the entire sequence of your code which accesses the data.

Código ejemplo

leer dos sensores:uno cada medio segundo procesar los datos y acumularlos el segundo
sensor se leera cada 15 minutos. Ambos datos se enviaran cada 15 minutos . Para facilidad
leeran cada 9 segundos descomentar intervalo según el caso

#include <TimerOne.h>
const int led = LED_BUILTIN; // the pin with a LED
//interrupcion es cada .1 segundo para generar un
//ciclo de 15 minutos
//necesito 10 interrpciones*60*15=9000 interrupciones
//const int intervalo=9000;//par 15 min
const int intervalo=90;//para prueba

void setup(void)
{
pinMode(led, OUTPUT);
Timer1.initialize(100000);
Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.1 seconds
Serial.begin(9600);
}

int ledState = LOW;


volatile unsigned long blinkCount = 0; // use volatile for shared variables
volatile unsigned long contador = 0;
volatile long potencia=0;
volatile long demanda=0;
int sensorPin = A0; // select the input pin for the potentiometer
int sensor2Pin = A1;
int sensorValue = 0;
int sensor2 = 0;

void blinkLED(void)
{
sensorValue = analogRead(sensorPin);
potencia=float(sensorValue)*127; // suponer correinte es igual a sensorvalue
demanda=demanda+(potencia*0.1)/(3600000); //
wattsegundo(1kw/1000watt)(1hora/3600seg)
sensor2 = analogRead(sensor2Pin);

if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}

blinkCount = blinkCount + 1;
if(blinkCount>=intervalo )
{
blinkCount=0;
Serial.print("demanda=");
Serial.print(demanda);
Serial.print("\t"); // simbolo para tabulador
Serial.print("sensor2=");
Serial.println(sensor2);
}

digitalWrite(led, ledState);
}

void loop(void)
{
unsigned long blinkCopy; // holds a copy of the blinkCount

noInterrupts();
blinkCopy = blinkCount;
interrupts();

// Serial.print("blinkCount = ");
// Serial.println(blinkCopy);
delay(100);
}
Codigo ejemplo de enviar datos de dos sensores a base de
datos via wifi
https://drive.google.com/drive/folders/1qtJ-bwdFuTxyR4-anJ
DIhONf3j1y9qLg?usp=sharing

Codigo principal
#include <TimerOne.h>

// This example uses the timer interrupt to blink an LED


// and also demonstrates how to share a variable between
// the interrupt and the main program.

const int led = LED_BUILTIN; // the pin with a LED


//interrupcion es cada .1 segundo para generar un
//ciclo de 15 minutos
//necesito 10 interrpciones*60*15=9000 interrupciones

//const int intervalo=9000;//par 15 min


const int intervalo=90;//para prueba

String server = "api.pushingbox.com";


const String devid = "vA88F19936AB8481";
String cadena="";
void setup(void)
{

pinMode(led, OUTPUT);
Timer1.initialize(100000);
Timer1.attachInterrupt(blinkLED); // blinkLED to run every 0.10 seconds
Serial.begin(9600);
Serial2.begin(9600);

Serial2.println(F("AT"));
if(Serial2.find("OK"))
Serial2.println(F("Respuesta AT correcto"));
else
Serial2.println(F("Error en ESP8266"));
//-----Configuración de red-------//Podemos comentar si el ESP ya está configurado

//ESP8266 en modo estación (nos conectaremos a una red existente)


Serial2.println(F("AT+CWMODE=1"));
//if(SerialESP8266.find("OK"))
// Serial.println(F("ESP8266 en modo Estacion"));

//Nos conectamos a una red wifi


Serial2.println(F("AT+CWJAP=\"INFINITUM89DD_2.4\",\"rabr535455\""));
//Serial.println(F("Conectandose a la red ..."));
Serial2.setTimeout(10000); //Aumentar si demora la conexion
if(Serial2.find("OK"))
Serial.println(F("WIFI conectado"));
else
Serial.println(F("Error al conectarse en la red"));
Serial2.setTimeout(2000);
//Desabilitamos las conexiones multiples
Serial2.println(F("AT+CIPMUX=0"));
if(Serial2.find("OK"))
Serial.println(F("Multiconexiones deshabilitadas"));
delay(1000);
//------fin de configuracion--------------

int ledState = LOW;


volatile unsigned long blinkCount = 0; // use volatile for shared variables
volatile unsigned long contador = 0;
volatile long potencia=0;
volatile long demanda=0;
int sensorPin = A0; // select the input pin for the potentiometer
int sensor2Pin = A1;
int sensorValue = 0;
int sensor2 = 0;

void blinkLED(void)
{
sensorValue = analogRead(sensorPin);
potencia=float(sensorValue)*127; // suponer correinte es igual a sensorvalue
demanda=demanda+(potencia*0.1)/(3600000); //
wattsegundo(1kw/1000watt)(1hora/3600seg)
sensor2 = analogRead(sensor2Pin);

if (ledState == LOW) {
ledState = HIGH;

} else {
ledState = LOW;
}

blinkCount = blinkCount + 1;
if(blinkCount>=intervalo )
{
blinkCount=0;
Serial.print("demanda=");
Serial.print(demanda);
Serial.print("\t"); // simbolo para tabulador
Serial.print("sensor2=");
Serial.println(sensor2);
}

digitalWrite(led, ledState);
}

void loop(void)
{
unsigned long blinkCopy; // holds a copy of the blinkCount

noInterrupts();
blinkCopy = blinkCount;
interrupts();

delay(100);
}

Función enviar enviowifi()

void enviowifi(void){
//--- programa-------
//Nos conectamos con el servidor:

Serial2.println("AT+CIPSTART=\"TCP\",""\"" + server + "\"" ",80");

if( Serial2.find("OK"))
{
Serial.println("\r\n\r\n\r\n ESP8266 conectado con el servidor...");

int humidityData =20; int pulsos=21; int TemperatureC=22;


int photocellReading=15;
String peticionHTTP= "GET /pushingbox?devid=";
peticionHTTP=peticionHTTP+devid;
peticionHTTP=peticionHTTP+ "&humidityData=" + (String)humidityData;
+ "&celData=" + (String)pulsos;
+ "&fehrData=" + (String)photocellReading;
+ "&hicData=" + (String)pulsos;
+ "&hifData=" + (String)pulsos; +" HTTP/1.1\r\n";

peticionHTTP=peticionHTTP+"Host: api.pushingbox.com\r\n\r\n";
peticionHTTP=peticionHTTP+"Connection: close\r\n\r\n" ;

//Enviamos el tamaño en caracteres de la peticion http:


Serial2.print("AT+CIPSEND=");
Serial2.println(peticionHTTP.length());
delay(500);
//esperamos a ">" para enviar la petcion http
if(Serial2.find(">")) // ">" indica que podemos enviar la peticion http
{
Serial.println("Enviando HTTP . . .");
Serial2.println(peticionHTTP);
if( Serial2.find("SEND OK"))
{
Serial.println("Peticion HTTP enviada:");
Serial.println();
Serial.println(peticionHTTP);
Serial.println("Esperando respuesta...");

///
boolean fin_respuesta=false;
long tiempo_inicio=millis();
cadena="";

while(fin_respuesta==false)
{
while(Serial2.available()>0)
{
char c=Serial2.read();
Serial.write(c);
cadena.concat(c); //guardamos la respuesta en el string "cadena"
}
//finalizamos si la respuesta es mayor a 500 caracteres
if(cadena.length()>500) //Pueden aumentar si tenen suficiente espacio en la
memoria
{
Serial.println("La respuesta a excedido el tamaño maximo");
Serial2.println("AT+CIPCLOSE");
if( Serial2.find("OK"))
Serial.println("Conexion finalizada");
fin_respuesta=true;
}
if((millis()-tiempo_inicio)>10000) //Finalizamos si ya han transcurrido 10 seg
{
Serial.println("Tiempo de espera agotado");
Serial2.println("AT+CIPCLOSE");
if( Serial2.find("OK"))
Serial.println("Conexion finalizada");
fin_respuesta=true;
}
if(cadena.indexOf("CLOSED")>0) //si recibimos un CLOSED significa que ha
finalizado la respuesta
{
Serial.println();
Serial.println("Cadena recibida correctamente, conexion finalizada");
fin_respuesta=true;
}
}

}
else
{
Serial.println("No se ha podido enviar HTTP.....");

////
}

}
}
else
{
Serial.println("No se ha podido conectarse con el servidor");
}

//-------------------------------------------------------------------------------

// delay(5000); //pausa de 10seg antes de conectarse nuevamente al servidor (opcional)

También podría gustarte