Felix Maocho

Para quien le interese lo que a nosotros nos interesa

1º Ejercicio de entradas analógicas Conceptos previos a la resolución de la “Linterna con potenciómetro”

Félix Maocho
9/4/2017

Objetivo de este capítulo

Comprender por qué las simulaciones digitales no alcanzan nunca la identidad as a la realidad física. Cómo se reperesntan las operaciones aritméticas en Arduino y cuales son las diferencias con la aritmética clásica . Tipos de variables, razones de por que hay diferentres tipos, foma de elegir el tipo adecuado en cada caso. El riesgo del “overflow” o desbordamiento, como prevenirlo y eludirlo. Ámbito alcance de las variables del Sistema, Globales y Locales. .Uso del mandato “millis”

 

Material necesario

Excepcionalmente este capítulo no precisa material, porque es únicamente teórico. Nos bastaremos con el simulador UnoArduSim

Conocimientos previos necesarios

Saber que son los pines digitales y analógicos, y las nociones que hemos estado dando hasta el momento de variables, mandatos, funciones,

 

Previo a la resolución del siguiente ejercicio hay que conocer una serie de conceptos que necesitaremos para su desarrollo y aunque ninguno es absolutamente nuevo, pues los hemos utilizado habitualmente. en esta ocasión les necesitamos entender con mayor profundidad, por lo que dedicaremos esta entrada a explicarlos con más profundidad.

Simulaciones del mundo real en el mundo digital.

Muy probablemente has visto en alguna película como los radios de alguna diligencia parecen moverse en sentido contrario al movimiento, o mas sencillo podéis hacer una peonza que vista en un vídeo se ve como estas:

¿Por qué se ve así?

Porque la simulación digital de la realidad analógica es algo defectuosa y da lugar a que aparezcan efectos sorprendentes. Un vídeo da 24 imágenes por segundo, que son entre si. un poco diferentes y es el cerebro, el encargado de interpretar las diferencias. Si las imágenes sucesivas muestran imágenes de igual aspecto en posiciones ligéramente más atrasadas, en vez de interpretar el cerebro que la rueda avanza, interpreta que retrocede, pues la imagen parece ir para atrás.

Si vwmoas en la realidad la peonza del vídeo, recibimos un continuo de imágenes y la vemos rotar correctamente, pero cuando la filmamos, se muestran una sucesión de momento, y según la velocidad de rotación, nuestro cerebro se engaña y la vemos unas veces girar en un sentido y otras en otro, e incluso, a cierta velocidad de giro parece que no se mueve.

Lo mismo pasa al hacer un video de una salida PWM, la pantalla del ordenador selecciona una serie de momentos de la salida. La realidad es que en determinado momento, los led o lucen a toda potencia o están apagados, pero si lo vemos en real, nuestro cerebro lo que percibe es que lucen mas o menos. según el tiempo que están luciendo y el tiempo que están apagados, pues en cierto tiempo, hemos recibido más o menos radiación luminosa.

Sin embargo, al aparecer sólo momentos determinados de la emisión, según la frecuencia del pin PWM, los momentos seleccionados serán a veces varios seguidos apagados y a veces, varios encendidos, eso hace que nuestro cerebro en vez de una atenuación de la luz, vea un parpadeo de la luz más o menos rápido. La simulación parece imperfecta cuando en realidad es perfecta, la luz unas veces esta encendida y otras apagada pero no luce de forma medianamente potente nunca.

Veamos una prueba. Vamos a hacer un programa que simplemente aumenta el numero que controla la frecuencia de la salida PWM de 8 en 8 unidades. El hardware sera un led unido a un pin PWM, por ejemplo el “5” y el software consiste simplemente aumentar el valor de “var” hasta “255” y a continuación reducirlo hasta “0” mostrando en cada instante, durante un cierto tiempo la luz que se genera en el pin PWM 5

Vemos ahora un video de la simulación,

Como observan, lo que debiera verse como una luz que cada vez brilla mas para después ir perdiendo brillo, se ve como una luz intermitente y bastante irregular, que en unos momentos predomina que está apagado hasta predominar que está encendida y volver a disminuir. Esto es lo más que podemos acercar el mundo digital a lo que vemos en el mundo real.

¿Por qué es tan mala la simulación?

Como indicamos los pins PWM envían a los led una onda de pulsos modulados cuya gráfica varia en función de “var” como se ve a continuación.

Si estos pulsos cíclicos los cortamos 24 veces por segundo, es decir de una forma regular pero arbitraria, el primer corte caerá sobre cualquier punto de la onda, sea cundo está en alto o en bajo y el segundo, como no será a una cantidad exacta de ondas, caerá o un poco mas a la derecha o a la izquierda, como pasaba con los radios de las ruedas, por tanto varios cortes seguidos caerán en lo alto de la onda y a continuación caerán en lo bajo. Por tanto. al hacer la emisión, tendremos varios “fotogramas” seguidos apagados y varios encendidos, dando lugar al parpadeo que observamos.

Operaciones aritméticas

Hemos visto que la aritmética en los sketch no coinciden al 100% con la que nos enseñaron en la escuela.

Quizá la diferencia de mayor calado es que el signo “=” no quiere decir que lo que a hay al lado izquierdo tenga el mismo valor que lo que hay al lado derecho, este signo no es de igualdad sino de asignación, sino que es mas bien es de asignación, o que traslada el valor de la expresión que tiene a la izquierda a la variable que tiene a la derecha. Por eso en Informática tiene sentido lo que en matemáticas es un absurdo como la siguiente expresión

x=x+1

En Matemáticas clásica seria como afirmar que “0” es igual a “1”, mierras que en informática quiere decir que si antes x valía “5”, a partir de ahora vale “6”.

Quizá lo mas correcto sería haber utilizado el signo “←”, pero el utilizar el “=” como asignación tiene ya mucha historia encima y no es fácil cambiarlo. Por eso cuando queremos indicar una identidad estamos obligados a utilizar el doble igual “==” , como por ejemplo hacemos en las condiciones que hacen que se ejecuten una serie de mandatos por ejemplo escribimos

if(8== var)

que solo se ejecutará cuando “var” tenga realmente el valor 8

Esta es quizá la mayor de las diferencias con las matemáticas clásicas, pero no la única vamos a repasar todas las operaciones relacionadas con las cuatro reglas para observar la diferenciar

  • Asignación a = b
  • Suma a + b
  • Resta a – b
  • Multiplicación a * b
  • División a / b

Todo es conocido, salvo que la multiplicación se utiliza el símbolo “*” en lugar del “x” que podría confundirse con el nombre de una variable.

Menos conocidos son las operaciones con operadores compuestos, es una forma de abreviar la escritura pero a mi no me gustan en exceso por que lo que se abrevia no se compensa con la obscuridad que se introduce en las expresiones. Observarán que todos los operadores compuestos tiene una equivalencia tradicional mucho mas comprensible.

Operadores compuestos

  • a++      Incremento  equivalente a    a=a+1
  • a–      Decremento  equivalente a    a=a-1
  • a+=b     Adición compuesta  equivalente a    a=a+b
  • a-=b     Sustracción compuesta  equivalente a     a=a-b
  • a*=b     Multiplicación compuesta  equivalente a    a=a*b
  • a/=b     División compuesta  equivalente a    a=a/b

De todas estas expresiones la única que yo utilizo y en un lugar muy concreto es el incremento, cuando quiero aumentar el valor de un contador una unidad.

Declaración de variables

Cuando en la zona de “Declaración de variables escribimos una instrucción del tipo:

int nomvar = 0

Estamos declarando una variable, o sea, que estamos indicando al ordenador que utilizaremos en el sketch una variable de nombre “nomvar” que inicialmente va a tener el valor “0” y que es del tipo “int”, o lo que es lo mismo que será un número entero con signo que ocupará en memoria 16 bits (2 btytes u octetos) que puede contener números comprendidos entre -32,768 y 32,767

Otros tipos de variables

Pero en muchos casos se tiene que guardar valores mas grandes, por ejemplo en este programa nos encontraremos que en un momento tenemos que multiplicar 255*800 = 204000 una cantidad claramente mas larga ¿Como declaramos la variable que contenga el valor de ese producto? – Tenemos la posibilidad de declarar variables de tipos diferentes que pueden contener valores de diferentes clases

Los nombres de los los diferentes tipos son, char, byte, int, unsigned int, long, unsigned long, float y double, que podemos traducir por, caracteres, (alfanumericos), byte, entero, entero sin signo, larga, larga sin signo. flotante, (coma flotante, 6 dígitos entre enteros y decimales de precisión), y doble (precisión), que indican mas o menos claramente que tipo de contenidos pueden tener

En la resolución de este problema utilizaremos “int” como hemos utilizado habitualmente que vale para utilizar enteros positivos y negativos moderadamente grandes. En la memoria del ordenador se destina un espacio de 16-bit (2 byte u octetos) . O lo que es lo mismo 16 espacios consecutivos rellenos de “0” y “1” en el que un espacio indica el signo, que indican si el numero es positivo o negativo y los 15 espacios siguientes, si en la composición del numero representado en potencias de 2 esa potencia entra o no. Con ello el rango de valores va de -32,768 to 32,767 (de (-2^15) (2^15) – 1).

Por ejemplo el número 13764 en base 2 es 1011010110111010, o lo que es lo mismo, el primer dígito  indica que es positivo que esta formado por las potencias de dos que vienen indicadas con un 1

13764=0*(2^14)+1(2^13)+1(2^12)+0(2^11)+1*(2^10)+0(2^9)+1(2^8)+1(2^7)+0*(2^6)+1(2^5)+1(2^4)+1(2^3)+0*(2^2)+1(2^1)+0(2^01)=(0*16384)+(1*8192)+(1*4096)++(0*2048)+(1*1024)+(0*512)+(1*256)+(1*128)+(0*64)+(1*32)+(1*16)+(1*8)+(0*4)+(1*2)+0(1)=8192+4096+1024+256+128+32+16+8+2

Esta página te permite cambiar un número ene base decimal (los normales)  una basa a otro en base a base binaria, (formado por “1” y “0” , si quieres saber cual es el valor en base 2 de cualquier número decimal basta introducir el numero decimal yen la casilla d correpondiente y pulsar para que en la otra casilla aparezca el número buscado tal como indica la imagen

“unsigned int” es igual que “int” reserva en la memoria del ordenador los mismo 16 bits, solo que no utiliza un bit para signo, lo que le permite dedicar una potencia de 2 mas para guardar el número, pero siempre el número es positivo. Con ello podemos duplicar la capacidad del número mas grande, pero perdemos la capacidad de guardar números negativos. Algo que se puede utilizar para guardar números que por lógica siempre sean positivos, como lo es por ejemplo el cuenta kilómetros de un coche, su rango va de 0 a 65,535 o sea (2^16) – 1)

“byte”, es muy parecido a “int”, solo que ocupa la mitad, solo 8 bits, y además no indica signo, por lo que solamente vale para si necesitamos números positivos pequeños que como máximo valgan de 0 a 255 o sea ((2^8)-1). Por ejemplo, utilizaremos este tipo de variables para los parámetros de los pin utilizados

“long” en cambio reserva en la memoria del ordenador 32 bits, (4 bytes u octetos),y los guarda con signo lo que permite guardar un rango -2,147,483,648 a 2,147,483,647. o sea (2^31)-1

Análogamente “unsigned ´long” sólo guarda números positivos en 32 dígitos por lo que permite conservar números el doble de grandes de 0 a 4,294,967,295 (2^32 – 1).

Aunque parezca muy grande en este programa vamos a necesitar una variable de este tipo, porque utilizaremos el mandato “millis” que devuelve en este formato los milisegundos que lleva el sketch en funcionamiento y será el valor que toma el resultado cuando el sketch ha estado en funcionamiento 4.294.967.295 milisegundos, que son 49 días, 17 horas, 2 minutos, 47 segundos y 292 milisegundos. Algo que puede ser mucho tiempo en la mayoría de los casos pero que hay que tener en cuenta en equipos que vayan a trabajar de forma ininterrumpida como por ejemplo un semáforo

Pasado ese tiempo la cifra no cabe en ningún sitio y se produce el error de “overflow”, (desbordar) que explicaremos a continuación.

Problemas con los cálculos matemáticos (overflow)

El ordenador guarda en su memoria y los espacio previstos al declarar las variables, tanto los el resultado parciales como el resultado final de las operaciones matemáticas. Por tanto estos resultados han de estar dentro del rango del tipo de variable que que hemos elegido al declarar las variables. De ser mayor que lo que cabe en el espacio reservado, el sistema trunca el resultado dando lugar a los errores llamados de “overfñow” o desbordamiento.

Pudiera resultar que al efectuar una suma, el resultado sea superior al rango que puede contener el tipo elegido para contener el resultado, en cuyo caso obtendremos valores erróneos y difíciles de predecir, mas aun si el tipo elegido tiene signo. pues puede que aparezca un resultado negativo cuando todos los elementos que intervienen en la operación son positivos

Un ejemplo nos explicara mejor lo que ocurre que mucha teoría. Este pequeño sketch no hacemos que sumar a y b y guardarlo en c: el resultado de la operación es 23900+30000= 53900. Hemos definido todas las variables como “int” con a y b aparentemente no tenemos problemas, pero c tendrá que albergar a 53900 que supera el rango de “int” que admite valores entre – 32768 a 32767.

Al ejecutar el programa que ha compilado correctamente obtenemos el siguiente resultado.

Si observan c adquiere el valor  -11636 absolutamente absurdo pues no solamente es erróeo, sino que además es negativo en una suma donde ambos sumandos son enteros.  Tenemos pues un típico caso de “overwlow”.

Pudiera parecer que si declaramos del tipo “long” a c1 los problemas desaparecen, pero podemos observar que no desaparecen hasta que declaramos como “long” todos los componentes que intervienen en la suma.

C1 que contendrá el resultado de la suma de dos elementos “int” n continñúa dando el resultado erroneo pese a que le hemos declarado como “long” que tiene un rango de  -2,147,483,648 a 2,147,483,647.

Es de resaltar lo traicioneros que son estos problemas de “overflow” pues, por un lado la compilación no detecta la posibilidad de que se produzcan “overflows”, por tanto creeremos que le programa esta bien y por otra parte no siempre se producen errores sino que sólo se producirán en los casos que los cálculos no quepan con lo cual tendremos errores intermitentes que son los más difíciles de localizar pues al introducir unos valores de prueba unas veces darán error y otras no, sin que estemos seguros que hemos probado todas las probabilidades.

El manual de Arduino dice al respecto de los owerflows aritméticos

“Estos operadores devuelven la suma, diferencia, producto o cociente (respectivamente) de los dos operandos. La operación se realiza utilizando el tipo de datos de los operandos, por lo que, por ejemplo, 9/4 da 2 ya que 9 y 4 son ints. Esto también significa que la operación puede desbordarse si el resultado es mayor que el que se puede almacenar en el tipo de datos (por ejemplo, añadiendo 1 a un int con el valor 32.767 da -32.768). Si los operandos son de tipos diferentes, se utiliza el tipo “mayor” para el cálculo.”

Por tanto en nuestro caso bastaría haber hecho solo a “a” o “b” (ademas de “c” que lo va a recibir) “long” para que la operación fuera correcta. Hacemos un último ensayo con estos tipos de valores

Similar a lo que he explicado para la suma ocurre con la resta, el producto y la división, al menos el resultado y uno de los componentes de la operación han de ser de un tipo con un rango suficiente para contener los cálculos numéricos.

A la hora de declarar las variables debemos estudiar el máximo valor que vayan a tomar tanto como resultado final como en los cálculos internos y en función de ello definir el tipo de variable a utilizar y en caso de duda declararlas de un tipo pon mayor rango.

No obstante si podemos elegir con seguridad variables de rango mas reducido, hacerlo, pues tiene dos ventajas, por un lado ahorramos memoria, que es algo que equipos modestos, como Arduino Uno tiene escaso. Pero eso no es lo mas importante, al operar con variables mas largas. Lo mismo que como ocurre en el cálculo manual, el tiempo de cálculo de dispara.

No se tarda lo mismo en multiplicar dos números de tres cifras que dos de cinco. Si bien el espacio de memoria destinado a las variables crece linealmente, variables el doble de grandes, precisan el doble de espacio, el tiempo de proceso de las operaciones crece geométricamente, dos variables el doble de grandes, precisan para procesarse, el cuadrado de tiempo, eso quiere decir que si dos pequeñas precisan 3 nano segundos, dos grandes precisan 9 y eso si ralentiza mucho los sketch.

Ámbito de las variables y su persistencia

Las variables en Arduino, soló tienen vigencia ahí donde hayan sido declaradas. Esto quiere decir que en los sketch de Arduino las variabkles existen solo dentro del ámbito donde han sido declaradas. Ello da lugar a tres grupos diferentes de variables, las “Variables del Sistema”, que han sido declaradas junto con el lenguaje IDE de programación que utiliza Arduino, las “Variables Globales”, declaradas por el programador en los sketch antes de de la función “setup” y las “Variables Locales”, definidas en un párrafo dentro del programa.

Las “Variables del Sistema” se las utiliza y se las reconoce en cualquier lugar. Ejemplo de estas variables son, HIGH y LOW definidas para indicar que un pin se ponga en “ALTO“, (5 voltios) o en “BAJO”. (0 voltios). Estas variables tiene unos nombres reservados, que no se pueden utilizar para un uso diferente. Podemos utilizarlas en cualquier momento, pero no podemos cambiar su valor, son realmente mas que variables, “Parámetros del Sistema”

Las variables que definimos en la zona que nosotros llamamos “Área de declaración de variables”, anterior a la función “setup” son “Variables Globales”. Pueden tener libremente el nombre que queramos darla y son del tipo y valor inicial que deseemos que tengan, se pueden utilizar en cualquier lugar del programa y también, a diferencia de las “Variables del Sistema” se puede cambiar su valor en el transcurso del programa.

Por último están las “Variables Locales”, que se declaran dentro de un párrafo limitado por un determinado par de corchetes “{…}” como pueden ser los de una función o de incluso de algún mandato condicional como “if” o “for”. Estas variables sólo tiene existencia, en el transcurso de la ejecución del contenido de los los corchetes, desapareciendo una vez que ha finaliza la ejecución de lo limitado por ellos.

Igual que las “Variables Globales“ cuando se declaran, se las adjudica un tipo y un valor inicial que se pueden cambiara en el transcurso de la ejecución del párrafo donde se las declaró.

Mientras que los nombres de las “Variables del Sistema” son fijos y exclusivos, los de las variables Globales y Locales son de libre elección, por lo que pudiera ocurrir que un mismo nombre, se utilizara tanto como Variable Global y Local, o que se declare en dos funciones diferentes de un mismo sketch. Hay cierta probabilidad que esto ocurra con nombres genéricos como “numero”, “pin”, “tiempo”, “primeravez”, sin embargo no se produce problemas, el sketch sabrá en cualquier momento a que variable nos estamos refiriendo.

Las variables locales priman dentro de los corchetes donde se declararon, por tanto si hemos declarado en dos funciones una variable con el mismo nombre, no hay duda, en la función que se esté ejecutando, actúa la variable declarada dentro de la función, pues entonces la otra no tiene existencia, El problema puede surgir entre una variables declarada en el “Área de declaración de variables” y otra con el mismo nombre declarada en una función.

Por ejemplo una variable global llamada “numero” y declarada con el mismo nombre dentro de una función. En el interior de esa función, “numero” será la variable declarada localmente, con le valor inicial que la diéramos ahí, no “existiendo” mientras se ejecute esta función, la variable global “numero”, que volverá a existir a todos los efectos, con el último valor que tuviera, tan pronto como finalice la función, fuera el que fuera el valor que “numero” haya adquirido en el interior de los corchetes de la función.

Algo sumamente útil, pues una forma de programar eficiente, consiste en hacer copy/paste de la funciones que previamente hemos programado y probado en otro sketch, Si esas funciones utilizan variables declaradas en su interior, no nos tendremos que preocupar de que en nuestro programa existan variables con el mismo nombre, a los efectos es como si una variable, tuviera además de nombre, apellido, el de la función que la declaró de forma que aunque coincidan en el nombre tengan cada una su propia identidad.

Pese a ello y para mayor claridad es norma, no de obligado cumplimiento pero si conveniente, que las variables del sistema cono HAIG o LOW, se escriban en mayúscula las variables globales se escriban en minúscula con nombres de mas de cinco letras que de alguna forma indiquen su naturaleza como “primeravez” “looppar” o cosas parecidas y que las variables locales se las nombre con nombres de tras letras como “num” “val” “pin” etc. De modo que de un vistazo sepamos si nos referimos a una variable del Sistema Global o Local.

 

Mandato millis

Hasta ahora siempre que queríamos mantener la salida de un pin abierta por un tiempo, calculábamos el tiempo con el mandato “delay” bien en un solo mandato o calculando el tiempo transcurrido mediante la suma de los intervalos de consecutivos “delay” ejecutados en ” loops” diferentes.

Por ejemplo el mas famoso sketch de Arduino la luz intermitente, la resolvíamos con un “delay”

void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}

Como hemos visto repetidas veces el mandato “delay” tiene el inconveniente de que “paraliza” el sketch de Arduino hasta su nacionalización lo que dificulta el hacer otras tareas en el mismo loop. Sin embargo el mandato “millis” no genera esos problemas, por lo que en muchas ocasiones es mas practico utilizar este mandato

Lo que hace el mandato “millis” es devolver ver los milisegundos que han transcurrido desde que el sketch se puso en marchaba. Su sintaxis es la siguiente

tiempo = millis()

Donde

“tiempo” es el tiempo transcurrido en milisegundos, desde que el sketch se puso en marchaba
“millis” es el nombre del mandato que carece de parámetros de entrada. La variable donde descarga millis ha de ser del tipo “unsigned long” que tiene un rango de 0 a 4294967295

Por ejemplo en el caso anterior haríamos lo siguiente

// Sketch 8.13 Intermitencia con millis
// Área de declaración de variables
byte pinouput = 13;
byte primerloop = 0 ; // 0 = primer loop, 1= siguientes
byte pinencendido = 0; // 0 = apagado 1 = encendido
unsigned long tiempo = 0; // tiempo leído por “millis”
unsigned long iniciotiempo = 0; // tiempo de inicio de la intermitencia
unsigned long tiempoactual = 0; // tiempo en este momento
unsigned long tiempotranscurrido = 0; // tiempo transcurrido desde que se cambio el led
unsigned long periodo =1000; // milisegundos que dura medio parpadeo
void setup() { // función setup ******************
pinMode(pinouput, OUTPUT);
}
void loop() { // función loop *********************
tiempo = millis();
if (0 == primerloop) { // cálculos que se hacen solo la primera vez
iniciotiempo = tiempo ;
digitalWrite(pinouput, HIGH);
pinencendido =1 ; // encendido el pin
primerloop=1 ; // fin del primer loop
}
else { // si no es el primer loop
tiempoactual = tiempo ;
tiempotranscurrido = tiempoactual – iniciotiempo;
if (tiempo < tiempotranscurrido) { // sobrepasada media intermitencia
if (pinencendido ==1 ) { // apagamos el pin
iniciotiempo = tiempo ;
digitalWrite(pinouput, LOW);
pinencendido =0 ;
}
else { // encendemos el pin
iniciotiempo = tiempo ;
digitalWrite(pinouput, HIGH);
pinencendido =1 ;
}
} // fin de if (tiempo < tiempo transcurrido)
} // fin else primer loop
} // fin loop

El video hecho con UnoArduSim permite ver como funciona perfectamente la intermitencia mientras que el “loop” va tan deprisa que casi no somos capaces de fer el valor de la variable “tiempo” que cuyo cambio indica que se inició un nuevo “loop”

Observarán en este sketch las siguientes cosas:

He utilizado variables del tipo “byte” en los casos en que los valores nunca subirán por encima de 255 como son le parámetro “pinoutput” que tiene un valor fijo de “13” y las variables “primerloop” y “pinencendido” que solo adquieren valores de “0” y “1” En cambio he utilizado variables del tipo “unsigned long” para todas las variables relacionadas con el tiempo, la razón es que “millis” devuelve un valor de este tipo, y por otra parte algunas de estas variables podrían alcanzar con el tiempo valores muy elevados por lo que conviene hacerlas de este tipo, “periodo” podía haber sido una variable de un tipo más ligero, pero entrando en operaciones aritméticas con las otras por seguridad prefiero mantenerla del tipo “unsigned long”

Por último piensen el porqué nunca podemos decir que un sketch funcionará perfectamente. Este sketch, (se supone que), funcionará perfectamente los primeros 49 días, 17 horas, 2 minutos, 47 segundos y 292 milisegundos. Pasado este tiempo “millis()” se pone a “0” y vuelve a contar, por tanto habrá una vez que tendremos la variable “iniciotiempo” con un valor muy grande y la variable “tiempoactual” con un valor muy pequeño, en consecuencia la linea donde dice

tiempotranscurrido = tiempoactual – iniciotiempo;

dará como resultado un número negativo y como “tiempotranscurrido” esta definido como “unsigned long” que solo acepta valores positivos  entre 0 y 4294967295, nos producirá un “overflow”

Así pues, teniendo en marcha un programa para hacer parpadear un led que funciona perfectamente, pasados 49 días falla “misteriosamente”. Como ven, nunca se puede asegurar que un sketch es perfecto, solamente que ha pasado todas las pruebas que le hemos hecho. Cuanto más extensas y completas que sean las pruebas, mas probabilidades hay que el sketch funcione bien en todas circunstancias, pero nunca tendremos al 100% la seguridad de que su funcionamiento es “perfecto”.

Para evitar este “overflów” tendríamos que incluir un nuevo “if” que substituya la linea que produce el posible “overflow” que dijera

if (tiempoactual < iniciotiempo){ tiempotranscurrido = tiempoactual – iniciotiempo;}
else (
tiempoactual = 4294967295 – iniciotiempo;
tiempotranscurrido = tiempoactual + iniciotiempo
}

Con esto superaríamos este posible problema pues siempre calcularíamos de forma correcta el tiempo transcurrido.

Repaso

Como repaso final te diré lo que has aprendido hoy

  • Diferencia entre simulacion digital y realidad física
  • Operaciones aritméticas con varuiables  operadores simpl4s y compuestos
  • Tipos de variables, y rangos de valores que permiten.
  • Riesgos de “overflow” como se previenen y formas de evitarlos.
  • Categorías de variables, Variables del Sistema, Globales y Locales
  • ämbito de actuación de las variables según su categoría.
  • Mandato “millis”
  • Utilizacón del mandato “Millis” para el control de duracion de procesos.

Félix Maocho

indice

Anuncios

9 abril 2017 - Posted by | Curso de Arduino, Robotica | , , , , , , ,

Aún no hay comentarios.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: