Training Stopwatch

Guanijei

Me animo a abrir el hilo casi en formato blog sobre este pequeño proyecto en el que estoy trabajando. Antes que nada, decir que para las cosas que se ven por aquí, esto es una mierda, pero me parece un proyectito curioso y quizás le sirva a otro user. Explicando lo que uno hace se descubren fallas y posibles futuros problemas, además, si puede ser una herramienta para recibir feedback y mejorar, pues matamos dos pájaros de un tiro. Espero que sea suficiente contenido para un hilo, si no, lo cerramos y lo puedo poner como un post en alguno de los hilos de python/raspberry.

Un poco de background

spoiler

El problema

Después de la pandemia como mucha otra gente empecé a entrenar en casa y en estos últimos años nos hemos ido montando un gimnasio "coqueto". El problema viene a la hora de controlar descansos, series y repeticiones en los entrenamientos. Al estar escuchando música, oyendo un podcast o viendo algo de reojo en twitch o youtube, me pasa a menudo que, o me olvido de apuntar las repeticiones, o no sé si me quedan dos o tres series, o simplemente me parece un poco coñazo salir del video/podcast/spotify para apuntar algo en el excel en el que llevo el control. Además, muchas veces me olvido de reiniciar el cronómetro casio y no sé cuanto llevo de descanso.

La solución

Desde hace tiempo he querido montar algo parecido a esto pero adaptado a mis necesidades. Así que aprovechando que tenía una raspberry por casa cogiendo polvo y que tenía ganas de aprender a soldar y quizás trastear con el diseño 3D me he animado a con esto. La idea es montar la raspberry junto a una pantalla como esta, una batería y empacarlo todo en una carcasa impresa. Todo esto debería poder controlarse de manera remota con un mando. Mi objetivo es montar algo yo mismo y aprender sobre soldadura, pero no descarto pillar algo así, pero para empezar estoy con un mando de Xbox y funciona de maravilla.

Lo que pides / lo que te llega

Por darle un poquito de vistosidad al tema:

El objetivo:

Lo que tenemos:

Intentaré arreglar un poco el repositorio para dejarlo medio decente y dejarlo por aquí.

Otros puntos:

  • El programilla conecta con una base Postgres que runea un contenedor en la raspberry (siguiendo este enlace me pareció bastante sencillo). Ahora mismo el esquema es el siguiente:

Esto es importante porque quiero que la aplicación lea (los usuarios y los entrenamientos ya se obtienen directamente de ahí) y escriba en la tabla las repeticiones para cada entrenamiento, ya que lo que aparece en la tercera interfaz en el gif está todo hardcoded para probar el layout.

  • Como comenté he conseguido utilizar el mando de la Xbox por bluetooth para reiniciar el contador para los descansos, me pareció relativamente sencillo, ya se verá en el repositorio.

  • Los siguientes pasos serán:

    • Organizar un poco el código
    • Modificar la tercera interfaz para que muestre las repeticiones del último entrenamiento y un campo donde añadir las del actual
    • Añadir también a esta interfaz la información de manera interactiva desde la base de datos
4
Kike_Knoxvil

Si te entran ganas de ponerte manitas y de aprovechar los GPIO, yo miraría de hacerme un display de digitos para las horas, minutos y segundos con leds. Algo como esto pero más sencillote y para poder verlo mejor a distancia:

1 1 respuesta
Guanijei

#2 De hecho era mi primera opción pero como quería meter bastante más información en la pantalla (ejercicios, reps del entrenamiento anterior, etc.) me decanté por la pantalla TFT de

1
hda

Me parece muy interesante. Por aquí me quedo :D

1
Guanijei

Pues como había comentado ayer, he estado trabajando un poco en la estructura del proyecto y aquí está el repo. He preparado el query para recuperar el último entrenamiento para el user/sesión elegido y me he estado peleando con tkinter. Por ahora va ganando este, si intento quitarle la title bar por alguna razón deja de funcionar la implementación de la navegación con las teclas. Según he encontrado es un problema conocido, porque pierde el focus de la ventana pero ya lo miraré con más calma en otro momento. Lo siguiente en lo que quiero centrarme es el layout de la interfaz con el cronómetro para añadir los datos directamente de la base de datos y cambiar un poco el diseño.

Guanijei

Pues nada, he ido trabajando en los puntos que quería y están más o menos acabados. He cambiado la disposición del tercer layout:

  • En rojo y grande: Tiempo de descanso
  • Abajo izquierda: Tiempo de entrenamiento
  • Abajo medio: Hora
  • Arriba derecha: Ejercicio actual
  • Medio derecha: Peso | Serie
  • Abajo derecha: Repeticiones último entrenamiento / Repeticiones a añadir este entrenamiento

Toda la información se coge directamente de la BBDD dependiendo de las dos selecciones de los menús anteriores (user, entrenamiento).

Se me hace poco intuitivo la manera que funciona tkinter para el layout. No es una definición fija de las posiciones, sino que funciona de manera secuencial, los paneles siempre están referenciados al último panel definido. He añadido un parpadeo a las repeticiones que tienen que ser a añadidas en el entrenamiento actual para hacerlo más intuitivo. Ha sido un poco lío porque tkinter no permite texto enriquecido en su config y en realidad son dos paneles separados, pero creo que ha quedado bien.

Además, me he dado cuenta de que debería poner alguna referencia al próximo entrenamiento programado y he añadido un atributo en la BBDD ("TrainingOrder"). En el caso de una distribución Push/Pull/Legs, pues sería Push=1/Pull=2/Legs=3. Esto me permite mostrar una pequeña flecha en el próximo entrenamiento. Si soy sincero creo que esta implementación no es demasiado eficiente, estos días le daré una vuelta a ver si puedo mejorarla:

spoiler

Una pequeña demo de como se ve por ahora:

Próximos pasos:

  • Definir los procesos que cambiaran de ejercicio y serie
  • Hacer el insert del entrenamiento actual en la BBDD

No sé si en los próximos días le dedicaré mucho tiempo, ya que quiero trabajar un poco en un SQL formatter/beautifier que tengo atascado de hace tiempo.

2
Guanijei

Pues al final me he liado un poco más y he hecho un par de cambios:

  • En la creación de la clase TimerForm, genero dos DataFrames, uno para el entrenamiento anterior y uno en el que guardaremos los valores del entrenamiento que se está llevando a cabo. Creo que este planteamiento es más eficiente y menos propenso a errores. Mientras estemos entrenando todos los datos se guardan en este DataFrame (new_training_df) y solo hacemos el insert en la BBDD una vez completaddo el entrenamiento
    Además, he añadido un nuevo atributo a la tabla en Postgres con el objetivo de repeciones por ejercicio (GoalReps), esto me permite comparar las conseguidas en el último entrenamiento con las objetivo y en caso de haberlas igualado actualizo el peso para el entrenamiento actual. Todo esto porque sigo el rep goal system, para periodizaciones habría que cambiar la lógica. En caso de que se aumente el peso en las repeticiones del último ejercicio simplemente aparece un asterisco para visualizar que estamos trabajando con un nuevo peso.
  • Con la cruceta del mando ahora se puede cambiar entre ejercicio y serie. Esto actualiza automáticamente el peso.
  • He empezado con la implementación para añadir las repeticiones de la serie que acabamos de hacer, por ahora apretando el botón A del mando solo cambia el color del texto para visualizar que vamos a cambiar ese campo. La idea es que esto bloquee cualquier otra interacción y nos obligue a guardar las repeticiones. Posiblemente, tras esto cambie el color a verde, por si volvemos atrás en el ejercicio/serie quede claro que ese valor ya lo hemos añadido.

Pequeña demo, se ve el cambio de ejercicio y serie y hacia el final cambia el color de la rep actual una vez apretado el botón A:

Si se ven ciertos saltos es simplemente por el capturador de video de windows, en realidad va completamente fluido.

Que el recuadro de los ejercicios sea dinámico es algo buscado, simplemente hace un wrap. En el caso del peso cuando cambia de uno a dos dígitos no me parece que quede bien visualmente, posiblemente le dé algo más de espacio al peso y lo deje fijo.

ToDo's:

  • Trabajar en el proceso que inserta el número de repeticiones en el DataFrame, bloqueando el resto de inputs y poniendo algún tipo de confirmación visual

  • Pantalla de finalización de entrenamiento, algún tipo de pop-up con confirmación que haría el insert en la BBDD con los valores actuales

  • He empezado a informarme un poco de la conexión del TFT de 40 pins a la raspberry, no tengo ni la más mínima idea de electrónica, pero para eso es el proyecto. De lo poco que he encontrado me imagino que será algo así (quizás esté diciendo una burrada):

    Si alguien tiene alguna recomendación o recurso para leer, se lo agradeceré en el alma.

Usuarios habituales

  • Guanijei
  • hda
  • Kike_Knoxvil