martes, 20 de noviembre de 2018

Redireccionar salida de los comandos DOS a fichero de texto. Eñes y otros caracteres.

No es que lo utilice mucho pero de, vez en cuando, utilizo alguno de los viejos comandos DOS. Últimamente he  preparado un par de trabajos en excel: 
  • En uno de ellos recojo, por un lado, todos los ficheros mp3 que tengo en mi PC para copiarlos en una tarjeta SD, siguiendo los criterios necesarios para utilizarlos con una DFPlayer mini. Utilizo excel como elemento auxiliar para preparar un ejecutable .bat que cree los directorios necesarios y que realice la copia final.
  • En el otro trabajo quiero controlar todas las fotos que tengo en mi colección de fotos.
  • Para encontrar todos los ficheros de un determinado tipo utilizo el comando Dir del viejo DOS.
  • Me interesa conocer la fecha y tamaño de los ficheros, por eso utilizo el formato largo.
  • Cuando abro una ventana con un terminal DOS y lanzo el comando Dir *.jpg /s (desde el directorio de mi colección de fotos) tanto las eñes como las vocales acentuadas salen correctamente, las eñes se ven como eñes y las vocales acentuadas como vocales acentuadas.
  • Si redirecciono la salida del comando a un fichero de texto, al editar ese fichero de texto tanto las eñes como las vocales no se ven ni como eñes ni como vocales acentuadas.
  • Desde un punto de vista funcional, como cuando preparé la copia de los distintos mp3, creando un ejecutable bat para ello, es necesario mantener fichero original sin cambiar los caracteres que sustituyen a las eñes y vocales acentuadas por otros. El fichero BAT resultante va a trabajar con el conjunto de caracteres original. Al cambiarlos se  produce  una sustitución de caracteres en el nombre del fichero que va a impedir su correcto funcionamiento .

  • Se puede preparar un fichero bat para copiar los ficheros sin problemas, aunque veamos los caracteres cambiados.
  • Si se va a trabajar con otros programas, esos caracteres cambiados si dan problemas.

Le he dado bastantes vueltas a este tema, en realidad es un mero problema de configuración, aunque esté poco claro como solucionarlo. Por tanto se trata de encontrar algo que nos permita cambiar el conjunto de caracteres al conjunto de caracteres del español.

En su momento, antes de WindowsXp, se podía programar el conjunto de caracteres en DOS con Keyb (sp para español y 850 como código). Desaparecido el comando Keyb no encuentro manera de cambiar genéricamente el conjunto de caracteres.

Trasteando, de momento he encontrado un par de soluciones que me permite ver las eñes como eñes y las vocales acentuadas como vocales acentuadas. No es la super solución que todos desearíamos, pero es una buena solución o, al menos, una solución.

Sin instalar nada nuevo en nuestro PC:




  • Parto de una colección de canciones de los años 70, con sus eñes y sus vocales acentuadas. 
  • Alguno de los nombres ya tienen en origen las eñes cambiadas por otros caracteres. Estos cambios no se solucionan con este cambio de configuración.
  • Redireccionamos la salida del comando DOS a un fichero de texto. En el ejemplo mp3_2.txt.
  • Editamos este fichero de texto. Le añadimos, como cabecera, la siguiente instrucción HTML:
<meta http-equiv="content-type" content=text/html   charset=ibm850>

  • Con esta instrucción cambiamos en conjunto de caracteres.
  • Salvamos el fichero de texto como un fichero HTM (mp3_2.htm). Lo convertimos en una página web.
  • Abrimos ese fichero (mp3_2.htm) con Internet Explorer. A mi me funciona solo si se abre con Internet Explorer, con otros navegadores no funciona. 
  • Si en otros PC la cosa se comportase como en el mío, se verían las eñes y las vocales acentuadas.
  • Con el botón derecho del ratón pulsamos sobre el texto web. Se abre un desplegable, elegimos "Ver código fuente".
  • En el código vemos eñes y vocales acentuadas. Salvamos como texto.

Instalando en nuestro PC Libre Office:
  • Pinchamos sobre la salida txt del comando DOS con el botón derecho del ratón. 
  • Seleccionamos Abrir Con->Libre office Calc.
  • En mi PC, al menos, nos presenta un formulario de importación en el que podemos seleccionar el conjunto de caracteres que vamos a utilizar.
  • Seleccionamos "Europa occidental (DOS/OS2-850/internacional)
  • Podemos aprovechar para separar los campos que nos puedan interesar, o no. Siempre se puede hacer después.
  • Salvamos el fichero como xls, html o como odt. Ni los copia pega ni los guardar como texto conservan el cambio de caracteres. No funcionan.


martes, 16 de octubre de 2018

Estadísticas a partir del track de una excursión.



He preparado este trabajo para aquellos que les gusta trastear con el GPS y que les gustaría poder hacer sus propias estadísticas de una ruta. De paso incluyo la posibilidad que tiene excel de crear nuestras propias funciones con VBasic.

  • El primer paso consiste en pasar los datos de la ruta al libro excel.
  • Hay muchas maneras de hacerlo, desde el copia pega desde BaseCamp (propiedades de la ruta) hasta salvar los datos a un fichero de texto (o un fichero csv) o, incluso, utilizar Ibpindex para obtener esos datos.
  • A partir de estos datos puedo conocer directamente los incrementos de altura y de tiempos. Incremento = "Lo que hay" - "Lo que había"
  • La distancia recorrida hay que calcularla.
  • El rumbo hay que calcularlo.
  • Los acumulados de tiempo, distancia y alturas son una suma.

¿Como paso los datos a mi libro excel?
Esta vez voy a utilizar la utilidad que tienen algunos editores de rutas, Oziexplorer, BaseCamp, MapSource y OruxMaps, entre otros, para volcar los datos, coordenadas, alturas y fechas a un fichero de texto (.txt o .csv).
  • Oziexplorer, el editor de rutas mas antiguo que conozco, tiene la posibilidad de exportar a texto con varias, y distintas, posibilidades.

  • El trabajo que he realizado lo he hecho exportando a texto (csv) un fichero GPX con BaseCamp.

  • Abro directamente con excel el fichero csv.
  •  Elimino todo aquello que no sea los puntos de la traza.
  • Desde datos->Texto en columnas paso cada item a su columna.

  • Pasados los campos a su columna copio los datos y los pego en el libro EstadísticasManuales.xls, hoja Datos.

Como mínimo, a partir de fecha, coordenadas y alturas puedo calcular:

  • Distancia entre dos puntos y distancia acumulada.
  • Tiempo entre dos puntos y duración total.
  • Incremento de altura entre dos puntos y acumulados de subida y bajada.
  • Velocidad de recorrido. Entre puntos y total.
  • Tiempo en movimiento y de parada.
  • Eliminar puntos que no cumplen o que cumplen unos determinados criterios. En el ejemplo tiempo mínimo entre puntos, distancia mínima entre puntos y velocidad máxima. Otro criterio que se puede incluir es el de velocidad vertical (de subida o bajada), etc..
  • Para calcular tiempos y, dado que depende del tiempo, velocidades, hay que tener presente el sistema de fechas de excel. 

  • Si en una celda escribimos una fecha y cambiamos el formato fecha a formato numérico vemos un número en vez de una fecha. Es el número de días trascurridos desde el 1/1/1900. Uno equivale a un día, la fracción de uno es la fracción de día. Este sistema no me acaba de gustar, es bastante imperfecto. 
  • Las velocidades, en km/hora se calculan con distanciaEnMetros/(tiempo*24000). 1000 para pasar los metros a km y 24 para pasar los días, o su fracción, a horas.
  • Las duraciones, sin embargo, se calculan restando sin mas  las fechas y sus acumulados sumando las duraciones.
  • Los incrementos de altura son sencillamente una resta. Altura del punto2 menos la altura del punto1.
  • El calculo de las distancias es lo único realmente complejo de todo esto. Hay varias posibilidades, incluida una manera aproximada de calcularla.

Distancia entre dos puntos:

Buscando en internet encontré, hace ya varios años, una fórmula que es la que utilizo desde que empecé a hacer mis propias estadísticas.


La fórmula es bastante compleja, no difícil convertirla a fórmula excel pero queda un formulón,  por lo que creo mi propia función en VBasic a partir de esa fórmula, la funcion DGeo (distancia geográfica), que es mucho mas sencilla de manejar:



Function DGeo(Lat1, Lon1, Lat2, Lon2)

Dim GaR, R, Lat1R, Lat2R, Lon1R, Lon2R
DGeo = -1
On Error Resume Next
'57.29577951 para convertir grados a radianes
'6378137 Radio de la tierra
GaR = 57.29577951
R = 6378137
Lat1R = Lat1 / GaR
Lat2R = Lat2 / GaR
Lon1R = Lon1 / GaR
Lon2R = Lon2 / GaR





'DGeo = R * Atn(Sqr((1 - (Sin(Lat1 / GaR) * Sin(Lat2 / GaR) + Cos(Lat1 / GaR) * Cos(Lat2 / GaR) * Cos(Lon2 / GaR - Lon1 / GaR)) ^ 2)) / _

(Sin(Lat1 / GaR) * Sin(Lat2 / GaR) + Cos(Lat1 / GaR) * Cos(Lat2 / GaR) * Cos(Lon2 / GaR - Lon1 / GaR)))





DGeo = R * Atn(Sqr((1 - (Sin(Lat1R) * Sin(Lat2R) + Cos(Lat1R) * Cos(Lat2R) * Cos(Lon2R - Lon1R)) ^ 2)) / _

(Sin(Lat1R) * Sin(Lat2R) + Cos(Lat1R) * Cos(Lat2R) * Cos(Lon2R - Lon1R)))





On Error GoTo 0

End Function



Esta función, mi función, la función añadida por mi, como fórmula excel queda:

=Radio* ATAN(RAIZ((1 - (SENO(D2*GaR) * SENO(D3*GaR) + COS(D2*GaR) * COS(D3*GaR) * COS(E3*GaR - E2*GaR)) ^ 2)) / (SENO(D2*GaR) * SENO(D3*GaR) + COS(D2*GaR) * COS(D3*GaR) * COS(E3*GaR - E2*GaR)))



Donde:


  • Radio=radio de la tierra. Es una variable con nombre.
  • De GaR sirve para convertir grados a radianes. Es una variable con nombre. Podía haber utilizado la función RADIANES().
  • Columna D es la latitud. 
  • Columna E es la longitud.
Entre ambas maneras de calcular distancias hay una pequeña diferencia.

Para distancias cortas he encontrado una manera aproximada de calcular la distancia entre dos puntos, columna I de la hoja "datos2". Empiricamente hay muy poca diferencia para puntos cercanos en metros y bastante diferencia para puntos muy separados. Creo que como estamos trabajando con la traza de una excursión a pie o en bici los puntos están muy cerca unos de otros podemos utilizar la siguiente fórmula:
  • =RAIZ(((D2-D3)*M_G)^2+(M_G*COS(D3*GaR)*(E2-E3))^2), que tampoco se puede considerar una formulita.
  • Columna D es la latitud. 
  • Columna E es la longitud.
  • M_G es una variable con nombre. Es el número de metros por grado en el Ecuador de la tierra.



Rumbo: El rumbo es el ángulo que forma nuestra dirección, la dirección que llevamos al movernos,  con el eje norte-sur, con una brújula graduada es fácil de ver. Es una información, también desde mi punto de vista, mas útil en náutica que sobre tierra, en tierra nuestros tramos rectos son pequeños y nuestro camino va por donde va, casi nunca podemos ni elegir el rumbo ni salirnos del camino. Hay varios casos mas en los que el ángulo entre una dirección y el eje norte-sur se puede utilizar, pero no vienen al caso.
  • No he conseguido encontrar una fórmula exacta de calcular el rumbo, pero si una fórmula aproximada para puntos cercanos.
  • Queda una fórmula compleja, por lo que ni siquiera intento pasarla a excel. Solo hago la fórmula en VBasic.
  • En tierra solo he visto utilizar el rumbo para eliminar algunos puntos. Si tres puntos consecutivos tienen el mismo rumbo se puede eliminar el punto central sin perder demasiada información.
Código de Rumbo:

Function Rumbo(Lat1, Lon1, Lat2, Lon2)
Dim D1 As Double, D2 As Double, D3 As Double, ArcoTan As Double
'corregir casos 2 y 4
'111319.491
'Pi = 3.141592654

D1 = DGeo(Lat1, Lon1, Lat2, Lon2)
D2 = DGeo(Lat1, Lon1, Lat2, Lon1)
D2 = Abs(111319.491 * (Lat2 - Lat1))
D3 = DGeo(Lat2, Lon1, Lat2, Lon2)
D3 = Abs(111319.491 * (Lon2 - Lon1) * Cos(Lat2 * 2 * Pi() / 360))
On Error Resume Next

C = 0
ArcoTan = Atn(D3 / D2)
e = Err()
If (D2 > 0 And D3 > 0) Then
If Lat2 >= Lat1 And Lon2 <= Lon1 Then
Rumbo = (2 * Pi() - ArcoTan)

End If
If Lat2 >= Lat1 And Lon2 >= Lon1 Then
Rumbo = ArcoTan

End If
If Lat2 <= Lat1 And Lon2 <= Lon1 Then
Rumbo = Pi() + ArcoTan

End If
If Lat2 <= Lat1 And Lon2 >= Lon1 Then
Rumbo = (Pi() - ArcoTan)

End If
End If

If D2 = 0 Then
Rumbo = Pi() / 2
If Lon1 > Lon2 Then Rumbo = 1.5 * Pi()
End If

If D3 = 0 Then
Rumbo = 0
If Lat1 > Lat2 Then Rumbo = Pi()
End If

On Error GoTo 0
'f = "0." & Left("0000000000000", Dec)
'Rumbo = Format(Rumbo * 360 / (2 * Pi()), f) + 0
Rumbo = Rumbo * 360 / (2 * Pi())
End Function

Function Pi()
Pi = 3.141592654

End Function

En donde Lat1,Lon1,Lat2 y Lon2 son las coordenadas del punto de inicio y del punto de destino.

viernes, 5 de octubre de 2018

Cambios de base. De decimal a binario y de decimal a hexadecimal.

Estoy trabajando, en mi blog de cacharreo, con un reproductor de mp3, el DFPlayer Mini y un Arduino Uno. El aparato se puede programar directamente, según la documentación del fabricante, o se puede programar siguiendo alguna de las librerías preparadas al efecto. La muy escasa documentación del fabricante sobre este aparato hace referencia a unos comandos escritos directamente en hexadecimal, aunque en la práctica ese hexadecimal se convierte en una base de ocho bits, los ocho bits de un carácter ascii.
Como apoyo a lo que estoy haciendo, por un lado hablar el mismo idioma (hexadecimal) del pdf del fabricante y por otro trabajar, de hecho, con una base de 8 bits, he preparado un libro excel que me permite estar seguro, antes de entrar en la programación del Arduino, de lo que estoy haciendo.





  • La primera conversión, líneas 6 y 7 es la de decimal a binario. En este caso no la utilizo para nada, pero es la base de la electrónica digital.
  • Hago una conversión de decimal a hexadecimal en las líneas 21 y 22.
  • Hago una conversión de decimal a una base byte, una de dos caracteres u una de cuatro caracteres.
  • Por último hago una conversión de decimal a decimal, como comprobación de la idea.
  • Normalmente, en nuestro sistema de numeración, el número de menor peso es el de más a derecha y el de mas peso es el de mas a la izquierda.
  • Independientemente de la base de numeración, cada una de las unidades  de una cifra vale el número de valores que toma la base de numeración elevado a un exponente, cero el de mas a derecha, uno el siguiente, dos, tres y así sucesivamente.
  • Esto es fácil de seguir, partiendo de cero, sumando sucesivamente uno, en binario pasamos de cero a uno y de uno a 10. En decimal pasamos de 9 a 10. En hexadecimal pasamos de 0F a a 10.
  • Para pasar de una cifra a otra debemos incrementar n (número base, contando el cero) veces la cifra de la derecha.
  • Si continuamos el razonamiento, para llegar a la tercera cifra hemos tenido que incrementar n^2 veces el cero inicial. En decimal 100, tres cifras, es 99 +1, es 10^2 cada unidad de esa tercera cifra vale 10^2. Lo mismo para 1000, cuatro cifras, 999+1, cada unidad de esa cifra vale 10^3.
  • Este razonamiento es válido para el resto de las posibles bases de numeración que se nos ocurra.
  • En la conversión de decimal a otra base hay que introducir el concepto resto. Vamos a calcular la cifra N (empezando en cero). Debemos quitar el valor de las cifras de mas a la izquierda, a partir de N+1, esto se hace hallando el resto de dividir el valor decimal por la base elevada a N+1.
  • El entero de dividir ese resto por la base elevada a N nos da el valor de esa cifra.
  • Repitiendo ese proceso hallamos todas las cifras de la conversión.
Esto, quizás parezca un poco lioso, pero el la práctica resulta sencillo.



martes, 7 de agosto de 2018

Copia y renombre masivo de ficheros con apoyo en Excel. Preliminar.

Una noche de insomnio compre en amazón un lector mp3 para Arduino, con el fin de incorporar música a alguno de mis proyectos. Como lo compré sin meditarlo mucho, al empezar, al intentar utilizarlo, me di cuenta de que no era exactamente lo que yo pensaba que era, no se ajustaba exactamente a lo imaginado. Lleva un soporte de tarjeta microsd en donde se supone que tenemos que tener la música.
En concreto los diferentes mp3 ni pueden llamarse de cualquier manera, ni pueden estar donde me apetezca, deben tener como nombre un número y estar en la raíz de la tarjeta microsd.
¿Como hago yo una copia masiva de mis mp3 y, además les pongo otro nombre?:Con el antiguo DOS y con apoyo en Excel.



  • En windows, abriendo un terminal DOS (con CMD en la línea ejecutar) o bien creando un fichero ejecutable .bat
  • Utilizo el comando dir c:\*.mp3 /s /b >mp3.txt
  • Este comando da todos los mp3 que hay en el disco C: y redirecciona la salida a un fichero de texto (mp3.txt)
  • Por supuesto que no es necesario buscar en todo el disco, podemos buscar en varios directorios de uno en uno. Solo hay que incorporar una línea por directorio y redireccionar la salida como >>mp3.txt
  • En mi PC algunos caracteres no se representan correctamente. No importa, al utilizarlos de vuelta, se compensa ese error.
  • Este error parece que se soluciona configurando el DOS a teclado en español (keyb sp o kb16 sp dependiendo del tipo de windows), pero en mi windows no están instalados ninguno de ellos.
  • Con cualquier editor de texto, o abriendo el fichero de texto directamente desde excel, copiamos el contenido de este fichero en una hoja excel (a1)
  • Vamos a preparar un fichero ejecutable .bat de DOS.  En las columnas B y C preparo el ordinal, el nombre de la copia. En B incremento el ordinal (B2=B1+1) y en C pongo los ceros a la izquierda necesarios, con =DERECHA(100000+B1;5).
  • En la columna D preparamos una línea con el comando de DOS copy. El nombre original va precedido y seguido de comillas, de esa manera podemos incluir espacios en blanco en los nombres.
  • El nombre de destino, en este caso, no tiene espacios en blanco, luego no necesitamos incluir las comillas.
  • El comando resultante, uno por línea, es:="copy " & CARACTER(34) & A1 & CARACTER(34) & " c:\temp\mp3\" &C1 & ".mp3".
  • Copiamos toda la columna en un fichero .bat, ejecutable en DOS. Salvamos.
  • Ejecutamos el .bat, podemos o no desviar la salida a un fichero de texto, lo que nos permite controlar los posibles errores de copia. Nos copia todos los ficheros mp3 en un solo directorio y con los nombres adecuados.
  • Ya solo nos queda pasarlos, si no lo hemos hecho directamente, a la tarjeta SD.
Ayer por la mañana escribí la primera parte de este articulo. Por la tarde me estuve documentando sobre el lector de mp3 y parece que si admite que la tarjeta SD tenga directorios aunque con algunas limitaciones.
Preparo una segunda  hoja (hoja2), en el libro CopiarMp3_2.xls, que me separa los mp3 por directorios. En principio tanto las canciones como los directorios toman un nombre numérico, que es lo que recomiendan algunas páginas.
  • Para separar los directorios necesito conocer la última posición del carácter "\". Para ello creo una función, Ultima,  en vbasic para encontrar esa ultima posición.
  • Una vez separado el directorio , con =SI($B4<>$B3;$D3+1;$D3) incrementamos el número de directorio. Esta instrucción se puede leer como "si el directorio actual es distinto del directorio anterior, incrementa uno. Si no déjalo como está"
  • Para numerar las canciones dentro de su directorio utilizo =SI($B4<>$B3;1;$H3+1), que puede leerse como "si el directorio anterior es distinto del actual pon 1, si no incrementa uno".
  • En la columna F preparo unas instrucciones DOS, con = " mkdir " & $H$1  & DERECHA($D3+1000;3), para crear los directorios mediante un fichero ejecutable ".bat". Estas instrucciones se copian en un fichero .bat, que debe ejecutarse antes de la copia de los mp3.
  • Dejo abierta la posibilidad de trabajar con los nombres de directorios o/y ficheros.
Mi propia función, la función Ultima(): Entrando en los módulos VBasic podemos verla. No tiene gran explicación, se basa en la instrucción vbasic InStrRev que nos da la última aparición de un determinado carácter en una cadena alfanumérica


Function Ultima(Cad, Sep)

'Cad=Cadena alfanumérica

'Sep=separador, carácter buscado.

Ultima = InStrRev(Cad, Sep)


End Function

La pregunta es ,Y dado que nos metemos a programar en vbasic ¿porque no lo hacemos todo de una tacada en vbasic?
Código de la función que lee el fichero con los mp3 y crea un ejecutable (.bat). Este ejecutable crea los directorios y copia los ficheros.
Aunque también escribe en el excel, este paso no es necesario. Se puede omitir.
Cuando utilizo un fichero de texto creado con windows 7 me aparecen una serie de caracteres (unicode) que me introducen unos salto de línea incontrolados, que se pueden eliminar copiando a excel la línea para después recuperarlos.

Código de la función:
Sub Proceso()
Dim Carac, Lin, DirT, Datos, Salida, N, Pos1, Pos2, LinA, C(255)
Dim Lat, Lon, V, FH, Fic, Dir2, Dir1, DirAnt, ND, NF
'DirEntr = "C:\Documents and Settings\Fernando y Use\Mis documentos\Mi Garmin\"
'Nom = "fUENCARRAL, tRES cANTOS, aLCOBENDASReal.gpx"
With Sheets("Config")
DirT = .Range("b1").Value
Datos = .Range("b3").Value
Salida = .Range("b2").Value
End With
'Sheets(1).Range("a" & 1 + NF) = DirEntr & Nom
Close #1
Close #2
Open Datos For Input As #1
Open Salida For Output As #2


Lin = ""
N = 1
With Sheets("Datos")
.Select
.Cells.Clear
'MsgBox DirEntr & Nom
Do While Not EOF(1)

Carac = Input(1, #1)
C(Asc(Carac)) = C(Asc(Carac)) + 1
'If Asc(Carac) = 127 Or Asc(Carac) = 129 Or Asc(Carac) = 141 Or Asc(Carac) = 143 Or Asc(Carac) = 144 Or Asc(Carac) = 157 Then MsgBox Asc(Carac)

If (Asc(Carac) = 10 Or Asc(Carac) = 13) And Lin <> "" Then
N = N + 1


Pos1 = Ultima(Lin, "\")
Fic = Mid(Lin, Pos1 + 1)
Dir1 = Left(Lin, Pos1 - 1)
Pos1 = Ultima(Dir1, "\")
Dir2 = Mid(Dir1, Pos1 + 1)
If DirAnt <> Dir2 Then

ND = ND + 1
.Range("f" & ND + 1) = " mkdir " & DirT & Mid(1000 + ND, 2)
'.Range("g" & ND + 1) = " mkdir " & DirT & Dir2
Print #2, " mkdir " & DirT & Mid(1000 + ND, 2)
NF = 1
End If

Sheets("config").Range("d1").Value = Lin
' en Sheets("config").Range("e1")  hay que colocar la fórmula =limpiar(D1)
Lin = Sheets("config").Range("e1").Value
.Range("a" & N) = Lin
.Range("b" & N) = Dir1
.Range("c" & N) = Dir2
.Range("d" & N) = ND
.Range("e" & N) = Fic
DirAnt = Dir2
Print #2, " copy " & Chr(34) & Lin & Chr(34) & " " & DirT & Mid(1000 + ND, 2) & "\" & Mid(1000 + NF, 2) & ".mp3"
Lin = ""
NF = NF + 1
Else

If Asc(Carac) <> 13 And Asc(Carac) <> 10 Then Lin = Lin & Carac

End If
Loop

'.Range("1") = N
For i = 0 To 255
.Range("h" & i + 2) = i
.Range("i" & i + 2) = C(i)
.Range("j" & i + 2) = Chr(i)
Next
End With


Close #1
Close #2

End Sub


Caracteres no imprimibles: En principio son aquellos cuyo código ascii es menor de 32 (espacio). los no imprimibles van de de 0 a 31. En texto unicode hay otros  caracteres no imprimibles (127,129,141,143,144 y 157).


martes, 10 de julio de 2018

Bascula de cocina con un FSR y un Arduino Uno. Estudio preliminar con excel.

Estoy preparando una bascula de cocina con un FSR, un sensor de peso, y un Arduino Uno, en una articulo anterior analizo un poco la gráfica del fabricante del sensor de peso. Esta vez, ayudándome, como la vez anterior, de un libro excel, analizo el posible comportamiento del proyecto.
  • Utilizo un divisor de tensión, una resistencia fija y el propio FSR. En este caso R2 en la resistencia fija y el FSR es R1.
  • La salida Vout se lleva a un convertidor A/D, lo que nos da un valor digital que a su vez, nos permite conocer el valor que tiene el FSR en ese momento y dado ese valor, conocer el peso que hay sobre el.

  • La conversión A/D da una serie limitada de valores, hay un salto conocido entre cada dos valores de tensión.
  • La gráfica del fabricante es logarítmica, el FSR tiene un comportamiento logarítmico, lo que supone que un mismo salto de tensión entre dos medidas en el convertidor A/D, no se corresponda con los mismos gramos de diferencia. Según aumenta el peso, el incremento de peso para un mismo salto  entre dos medidas, es mayor. 
  • Se supone, según la gráfica del fabricante, que el FSR puede pesar hasta 10kg. Como creo que es bastante difícil construir un platillo de báscula con menos de 50 gramos, el comienzo del tercer tramo lineal de la gráfica, solo considero en el libro excel ese tercer tramo.
  • El libro excel incluye la gráfica del fabricante (GResistenciaGramos) y los cálculos necesarios para conocer para conocer la pendiente del tramo lineal. (hoja Tramo3)
  • Sobre la gráfica del fabricante aparecen los valores calculados, tanto de la hoja Tramo3 como para la hoja GResistenciaGramos. 



Creando la gráfica XY

Valores de la Gráfica del fabricante.


Valor de los ejes y escala logarítmica.

Gráfica del fabricante como fondo de nuestra gráfica XY

  • La hoja GResistenciaGramos permite conocer, de momento de un modo preliminar, el comportamiento del proyecto.
  • Número de bits del convertidor A/D, en la celda A2. En esta celda se puede escribir lo que se quiera, aunque como es lógico, se debe incluir un valor que se corresponda con un valor de un convertidor A/D comercial.
  • El propio Arduino Uno incluye un convertidor A/D de 10 bits. En internet he encontrado convertidores externos al arduino de 12, 14 y 16 bits. 
  • Un mayor número de bits aumenta la precisión y un menor número de bits la disminuye. Con 10 bits, al aproximarnos al peso máximo, 10kg., cometemos un error de cuantificación de casi medio kilo. Con 14 bits pasa a ser de poco mas de 30 gr.
  • La hoja GResistenciaGramos está preparada para funcionar completamente con un convertidor de hasta14 bits. Con 16 bits funciona parcialmente, habría que expandir las formulas mas alla de la línea 65000.
  • Los cálculos están realizados con los valores digitales de tensión, tanto en su valor máximo como en los posibles valores intermedios.
  • La resistencia R2 se calcula en función, tanto del número de bits del convertidor como del primer valor que queremos que tengo nuestro proyecto así como del inicio del tramo que estemos considerando. En este caso parto, según la gráfica del fabricante, para 50 gramos, de 10000 ohmios.
  • En la celda B7 podemos variar el valor digital que queramos para esos 50 gr.
  • En C2 se calcula el valor teórico de R2. Entre D2 y D5 se aproxima, con hasta tres resistencias, puestas en serie, un valor comercial a ese valor teórico.
  • En H2 podemos indicar cual es el valor optimo de nuestra bascula. Aunque podamos pesar hasta 10kg, nuestro valor optimo puede ser mucho menor.
  • Da el primer peso superior a nuestro peso optimo, la línea en que aparece y el posible error que se puede producir, que se corresponde con el último salto entre pesos, y que también se corresponde con el máximo error que consideremos bueno para nuestro proyecto.
Gestión de errores:

La hoja GResistenciaGramos tiene un gran número de líneas con unas fórmulas que algún momento, según los valores correspondientes, producen un error. Estos errores se pueden gestionar de muchas maneras, pero creo que hay que gestionarlos, queda mucho mejor y evita otros errores en cadena, aunque ello suponga un incremento del peso de las fórmulas.
  • En la columna C controlo el posible cero o menor que cero cambiando el valor por el último valor superior a cero con =SI($C$2*(Vmax-$B12)/PV>0;$C$2*(Vmax-$B12)/PV;$C11)
  • En la columna E ese control de error lo hago con SI.ERROR(10^((LOG10(D8)-Cte)/Pend);$E7), aunque  este caso es un caso de error en cadena. Se produce cuando D8 (C8/1000) toma un valor negativo. Al haber resuelto el error, valor de C8 menor que cero, en esta columna no deberían producirse errores.


lunes, 2 de julio de 2018

Comprendiendo el gráfico de un sensor FSR. Preliminar a una bascula de cocina con Arduino Uno.

Sigo falto de ideas. Esta vez pienso en hacer una bascula de cocina con un Arduino Uno y un sensor de peso FSR. Aunque este tipo de sensores parece que no permiten medidas muy precisas, para una báscula de cocina probablemente valgan.
Documentarse, a veces, no es fácil, aunque en internet haya cientos de páginas de casi todo.
Un sensor FSR es un sensor de peso, es una resistencia variable que varía su valor en función del peso que esté sobre el. La gráfica fuerza/resistencia que he encontrado en internet para un FSR es la siguiente:



Con este tipo de gráficos el fabricante pretente explicar como se comporta su producto. Por otra parte, la pregunta es ¿Como llevo yo los valores  de la gráfica a mi proyecto? de alguna manera debo llevar a gráfica al proyecto.

Puede verse que el eje X está etiquetado en gramos y el eje Y lo está en ohmios.

  • En las hojas de características del sensor dice que es un gráfico "logaritmico".
  • Vemos que eje X presenta tres divisiones, del mismo tamaño, y cuatro etiquetas 10, 100, 1000 y 10000.
  • Estas divisiones necesariamente se corresponden con logaritmo (base 10) de lo etiquetado, logaritmo de 10 es uno, de cien es dos, de mil es tres y de diez mil 4.
  • Lo mismo pasa con el eje Y, divisiones con el mismo tamaño y etiquetas que no se corresponden con esas separaciones. 
  • Logaritmo de 0,1 es -1, de 1 es cero, de 10 es uno y de 100 es 2.
Vemos que  gráfica presenta tres tramos aparentemente lineales, tres tramos que se pueden asimilar a una linea recta (y=mx+c) 
  • El primer tramo (de izquierda a derecha) va desde 10 a 20 gr. (aprox.)
  • El segundo tramo va de 20 a 50. (aprox)
  • El tercer tramo va de 50gr. a 10 kgr.
Si vamos a construir una báscula de cocina es muy probable que solo el platillo de la báscula pese mas de 50 gramos, con lo que el peso que habrá sobre el sensor siempre estará por encima de esos 50 gramos que marcan los dos primeros tramos. Podemos no considerar, prescindir, al codificar el programa, de los dos primeros tramos, aunque incluirlos en nuestro código tampoco va a pesar mucho.

Incluyo la gráfica del FSR como fondo en una gráfica XY de excel:
  • Con los puntos resaltados en la propia gráfica del FSR compruebo (a ojo) lo que había supuesto, la presencia de tres  (o mas) tramos lineales.
  • Los dos primeros están claramente diferenciados, el tercero aunque también parece que se puede aproximar a  un solo tramo, tampoco pasaría nada si lo dividiésemos, a su vez, en varios tramos.
  • Me centro en el tercer tramo, sobre el que en un trabajo real trabajaremos. Con los valores obtenidos calculo los parámetros de la línea  (y=mx+c)  con la que vamos a trabajar.
  • Recordemos que nuestra gráfica del FSR es logarítmica, tanto los valores de X como los de Y son el logaritmo de X o de Y (log(y)=m.log(x)+c) 
  • Estos calculos están en la hoja Tramo3.
  • Incluyo en la gráfica GLog esos datos. Veo que la línea se sitúa sobre la imagen de fondo.

Con un Arduino podemos encontrar la respuesta del FSR ante un peso. Basta con hacer un divisor de tensión con una resistencia fija y conocida, la segunda resistencia sería el propio FSR, medir la tensión de salida y realizando el calculo adecuado encontraremos el valor de la segunda resistencia.


Con ese valor, Vout, calculamos la resistencia incógnita. Como estoy en los preliminares todavía no he decidido si el FSR va a ser R1 o va a ser R2, ni el valor de la resistencia fija que lo acompañara. Si fijamos R2, despejando, (R1=R2(Vin-Vout)/Vout) 
Con este valor entramos en  (log(y)=m.log(x)+c). En este caso Y=R1, despejamos log(X), hayamos el antilogaritmo y ya tenemos nuestro peso encontrado.

sábado, 24 de marzo de 2018

Cálculo del condensador de una fuente de corriente continua.



Este trabajo permite calcular el condensador de una fuente de corriente continua conocidas su tensión nominal y su consumo, en amperios, máximo. El resultado es en microfaradios.

Variables con nombre utilizadas:
  • Amp (=Condensador!$D$5) Consumo, en amperios.
  • CarQ1 (=Condensador!$D$7) Carga del condensador cuando la tensión es la tensión máxima.
  • CS (=Condensador!$E$5) Ciclos por segundo.
  • Descarga (=Condensador!$C$7) Perdida de carga entre Vmax y Vmin.
  • Periodo (=1000/CS) Tiempo de un ciclo de C.A.
  • TDesc (=Condensador!$B$7) Tiempo total de descarga.
  • Vmax (=Condensador!$C$3) Tensión máxima.
  • Vmin (=Condensador!$D$3) Tensión mínima.
  • Vn (=Condensador!$B$3) Tensión nominal.
Partimos de la tensión nominal de la fuente de C.C. y el consumo para la que estamos calculando el condensador.

  • Utilizamos una fuente con un trasformador del mismo valor nominal que la salida de C.C.
  • La señal a la salida del trasformador llega hasta ese valor nominal multiplicado por raíz de dos.
  • La tensión en bornes del condensador debe estar siempre por encima del valor nominal. En este caso he supuesto un margen de 1,5 voltios.
  • Supongo una descarga lineal del condensador. Estamos trabajando en un tramo casi lineal de la descarga.
  • El usuario solo debe indicar la tensión nominal, casilla B3 y el amperaje, casilla D5.
  • El resto de la hoja debería estar protegido, no lo está, lo dejo desprotegido para que cada cual pueda adaptarla a su gusto.
Cálculo matemático:
  • El condensador tiene una capacidad fija, no varía.
  • C=Q/V. Tenemos dos tensiones, la máxima y la mínima.
  • Esto supone que cuando el condensador está a la tensión máxima tiene una carga y cuando esta a la tensión mínima, tiene otra carga.
  • La diferencia entre ambas cargas la da el consumo, en amperios, por el tiempo de descarga.
  • El tiempo de descarga va desde el momento en que la señal alterna llega a su valor máximo y (1/4 del periodo), baja a cero y el momento en que la señal vuelve a alcanzar el valor mínimo deseado.
  • Vmin=Vmax*sen(a). Despejamos y calculamos el arco seno de a
  • Repartimos el periodo en proporcionalmente ese arco seno.
  • Td=Periodo*ArcoSeno/(2*pi)+1/4 Periodo.
  • Q1/V1=Q2/V2==>Q1/V1=(Q1-I*T)/V2.
  • Despejando Q1=I*T/(1-V2/V1)


martes, 2 de enero de 2018

Automatización de tareas con Excel. Manejo Power Point desde Excel con VBasic.Preliminar

En el artículo anterior hice una especie de gestor de fotos con excel. De momento sigue estando en fase preliminar pero cuando este terminado tendré que dotarlo de una manera sencilla de, además de tener una relación de fotos, un elemento que me permita ver las fotos seleccionadas. En la versión preliminar el libro excel  da un código html que hay que llevar a un fichero de texto (html), ejecutarlo y, con un poco de suerte, ver las fotos. Una de las posibilidades que permiten ver las fotos seleccionadas es incluirlas automáticamente en una presentación  Power Point, desde el gestor de fotos excel.

Trabajos preliminares, para empezar a usar códigos un poco, no mucho, mas complejos.

En Power point:
  • Por un lado, necesitamos saber el código vbasic de Power Point que nos permita incluir, en este caso fotos, objetos en una presentación.
  • Abro una presentación, busco la grabadora de macros, la activo, realizo manualmente la tarea deseada.
  • Añado una diapositiva. Añado una foto. Añado un cuadro de texto. 
  • Detenemos la grabación de la macro. Vemos el código escrito por la grabadora de macros. 
  • Hemos obtenido un código que nos facilitará en trabajo de escribir nuestro código.
En Excel:
  • Para manejar PP desde el vbasic de excel necesitamos incluir la librería correspondiente.
  • Abrimos el libro excel correspondiente y con Alt+F11 vamos a los módulos vbasic.
  • Con el menú Herramientas->Referencias busco y añado esa librería, en este caso "Microsoft Power Point 15.0 Object Library".
  • En uno de los módulos creamos una macro que incluya nuestro código.
  • En esa macro incluimos el objeto Power Point con Set ApliPP = New PowerPoint.Application.
  • Añadimos una presentación con Set PresenPP = ApliPP.Presentations.Add
  • Buscamos en la macro grabada por la grabadora de macros la manera de añadir una hoja. La adaptamos a nuestro código, y queda .Slides.Add(Index:=I, Layout:=ppLayoutBlank).Select
  • Buscamos, en la macro grabada, como añadir una imagen a la hoja.
  • Adaptamos esa instrucción a nuestro código. La instrucción resultante es 
  • ApliPP.ActiveWindow.Selection.SlideRange.Shapes.AddPicture(FileName:=Nom, LinkToFile:=msoFalse, SaveWithDocument:=msoTrue, Left:=40, Top:=30, Width:=640, Height:=480).Select
Con el siguiente código vbasic podemos importar todas las fotos de un directorio de nuestro PC a una presentación PowerPoint desde nuestro libro Excel.


Sub PresPower()
Dim ApliPP As PowerPoint.Application
Dim PresenPP As PowerPoint.Presentation
Dim Diapo As PowerPoint.Slide
Dim Hoja
Dim Nom As String
Dim H

Set ApliPP = New PowerPoint.Application

ApliPP.Visible = True
ApliPP.Activate
Set PresenPP = ApliPP.Presentations.Add

With PresenPP
'*********** Esta parte no es necesaria, la arrastro de otra versión 
'*********** Elimina todas las diapos. de una presentación
For Each Hoja In .Slides
Hoja.Delete
Next
'**********************
I = 1
x = Dir("C:\DiscoWindowsXP\Fotos\20131010Duraton\*.JPG")


  While x <> ""
  Nom = "C:\DiscoWindowsXP\Fotos\20131010Duraton\" & x
'  MsgBox Nom

.Slides.Add(Index:=I, Layout:=ppLayoutBlank).Select

Set H = PresenPP.Slides(I)

'On Error Resume Next
ApliPP.ActiveWindow.Selection.SlideRange.Shapes.AddPicture(FileName:=Nom, LinkToFile:=msoFalse, SaveWithDocument:=msoTrue, Left:=40, Top:=30, Width:=640, Height:=480).Select
On Error GoTo 0

I = I + 1
  x = Dir()
 Wend
End With
End Sub


Este otro código, un poco mas completo, recorre una hoja excel con una relación de fotos y las añade a una presentación PowerPoint, añadiendo, además, un cuadro de texto a cada foto.

Sub PPower()
Dim ApliPP As PowerPoint.Application
Dim PresenPP As PowerPoint.Presentation
Dim Diapo As PowerPoint.Slide
Dim Hoja
Dim Nom As String
Dim H
Dim DAnt, D, A As String
DAnt = ""
Set ApliPP = New PowerPoint.Application '

ApliPP.Visible = True
ApliPP.Activate
Set H = ActiveWorkbook.Sheets("Buscar")
Set PresenPP = ApliPP.Presentations.Add

With PresenPP
For Each Hoja In .Slides
Hoja.Delete
Next
End With

I = 1
j = 2
D = H.Range("d" & j).Value
DAnt = D
Nom = H.Range("d" & j) & H.Range("e" & j)
A = H.Range("h" & j).Value
  While Nom <> ""
 D = H.Range("d" & j).Value
 A = H.Range("h" & j).Value
If (D <> DAnt And Nom <> "") Or I > 100 Then
Set PresenPP = ApliPP.Presentations.Add
I = 1
DAnt = D
End If

PresenPP.Slides.Add(Index:=I, Layout:=ppLayoutBlank).Select


'On Error Resume Next
ApliPP.ActiveWindow.Selection.SlideRange.Shapes.AddPicture(Filename:=Nom, LinkToFile:=msoFalse, SaveWithDocument:=msoTrue, Left:=40, Top:=30).Select ' Width:=640, Height:=480).Select
er = Error()
'ApliPP.ActiveWindow.Selection.SlideRange.Shapes.AddTextbox(msoTextOrientationHorizontal, 20, 400, 900, 30).Select
'ApliPP.ActiveWindow.Selection.TextRange.Text = Nom & " " & er
ApliPP.ActiveWindow.Selection.SlideRange.Shapes.AddTextbox(msoTextOrientationHorizontal, 20, 500, 900, 30).Select
ApliPP.ActiveWindow.Selection.TextRange.Text = A
On Error GoTo 0

I = I + 1
j = j + 1
Nom = H.Range("d" & j) & H.Range("e" & j)

DAnt = D

 Wend



'End With


End Sub