{"id":103,"date":"2016-02-26T21:57:43","date_gmt":"2016-02-26T20:57:43","guid":{"rendered":"http:\/\/lab.fawno.com\/?p=103"},"modified":"2022-03-07T01:27:05","modified_gmt":"2022-03-07T00:27:05","slug":"","status":"publish","type":"post","link":"https:\/\/lab.fawno.com\/en\/2016\/02\/26\/aventuras-con-arduino\/","title":{"rendered":"","raw":""},"content":{"rendered":"","protected":false,"raw":""},"excerpt":{"rendered":"","protected":false,"raw":""},"author":1,"featured_media":134,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","_es_post_content":"\n
Har\u00e1 como un mes que me lleg\u00f3 mi primer Arduino<\/a>, se trataba de un Arduino Nano<\/a> y estoy encantado con el juguete.<\/p>\n\n\n\n El caso es que como ten\u00eda por ah\u00ed los t\u00edpicos displays de 7 segmentos<\/a> pues me puse a jugar con un contador de segundos, tremenda tonter\u00eda, lo se.<\/p>\n\n\n\n La t\u00e9cnica b\u00e1sica para visualizar n\u00fameros en este tipo de displays es unir todos los segmentos e ir visualizando d\u00edgito por d\u00edgito a gran velocidad... de esta forma, igual que en el cine, enga\u00f1amos al ojo y ve todos los d\u00edgitos encendidos cuando en realidad s\u00f3lo hay uno.<\/p>\n\n\n\n El problema entonces se trata de extraer para cada display el d\u00edgito correspondiente y ah\u00ed es donde me he dado de bruces con algo que ten\u00eda olvidado.<\/p>\n\n\n\n Veamos, si tenemos el n\u00famero 1234 y queremos visualizar las decenas lo que hacemos es descartar los millares y las centenas y dividir el resto entre 10:<\/p>\n\n\n\n Bueno, pues esto est\u00e1 mal... nos funcionar\u00e1 estupendamente en cualquier ordenador y cualquier programa pero no funcionar\u00e1 bien en Arduino y nos dar\u00e1 errores de redondeo.<\/p>\n\n\n\n El problema no es la divisi\u00f3n, al ser Decenas<\/em> de tipo entero se truncar\u00e1n los decimales, que es lo que queremos. Arduino no tiene funciones de redondeo, por lo que para evaluar un n\u00famero de coma flotante (float<\/em>) como entero (int<\/em>) lo hace descartando la parte fraccional.<\/p>\n\n\n\n \u00bfEntonces?, el problema es que antes de la divisi\u00f3n realizamos un m\u00f3dulo de Numero<\/em>. M\u00f3dulo<\/em> <\/a>es la operaci\u00f3n matem\u00e1tica que nos devuelve el resto de una divisi\u00f3n<\/a>. \u00bfArduino calcula mal el m\u00f3dulo?, no. Para calcular el resto de una divisi\u00f3n hay que hacer varias operaciones, todas ellas en coma flotante y Arduino (m\u00e1s concretamente el microcontrolador Atmega328<\/a>) no tiene unidad de coma flotante<\/a> y ah\u00ed radica el problema.<\/p>\n\n\n\n Al no tener FPU, todos los c\u00e1lculos se hacen en la ALU, que es muy limitada al tratarse de un microcontrolador de 8 bits. As\u00ed que lo que nos encontramos, al realizar el m\u00f3dulo, un c\u00e1lculo redondeado que nos introduce un error en el siguiente c\u00e1lculo...<\/p>\n\n\n\n La manera correcta de hacer lo que queremos es:<\/p>\n\n\n\n Ahora extraemos las centenas descartando primero las decenas y unidades (dividiendo entre 100) y luego descartando el resto de d\u00edgitos de la izquierda (m\u00f3dulo 10). Es importante que antes de realizar el m\u00f3dulo le indiquemos al microcontrolador que nos convierta el float<\/em> resultante de la divisi\u00f3n en un int<\/em>. No obstante el IDE de Arduino<\/a> nos devolver\u00e1 un error y no compilar\u00e1 si no lo hacemos.<\/p>\n\n\n\n Se puede hacer un bucle para ir extrayendo todos los d\u00edgitos:<\/p>\n\n\n\n Y ya est\u00e1, problema resuelto... pero que me ha tenido loco dos semanas.<\/p>\n\n\n\n Ahora vendr\u00e1 el listo y me dir\u00e1 que c\u00f3mo no me he dado cuenta antes... pero el listo se olvida que todas las CPU desde el i486<\/a> llevan la FPU incorporada:<\/p>\n\n\n\n<\/a>
int Decenas = (Numero % 100) \/ 10;<\/pre>\n\n\n\n
int Centenas = int(Numero \/ 100) % 10;<\/pre>\n\n\n\n
for (int d = 0; d < NumeroDeDigitos; d++) {\n int N = int(Numero \/ pow(10, d)) % 10;\n}<\/pre>\n\n\n\n