Achtung die kurve en ESP32

Mi nueva misión va a ser reconstruir un antiguo videojuego multijugador en un microcontrolador para manejarlo con 2 botones o un potenciómetro conectado por vga a una pantalla.

El juego consiste en dos gusanos que parten de no ocupar ningún pixel hasta ir ocupando la pantalla. El primero que choque contra el otro o contra si mismo pierde la partida.


 Mis avances hasta ahora han sido:

2021-06-02

-Planificación inicial, elección de piezas y librerías:

En este caso he elegido el Esp8266 (NodeMCU) que lo tenía cogiendo polvo. Un pequeño microcontrolador que nos brinda wifi y una potencia y memoria altas a muy bajo coste.

Nuestro amigo smaffer nos brinda de una librería para juguetear con vga ya sea desde Esp8266 o arduino uno. Pero siempre limitados a la potencia de cada microcontrolador.

https://github.com/smaffer/espvgax

En el caso de este microcontrolador estamos limitados a usar 2 colores que elijamos y a una resolución de 512×480.

Cuenta con otra librería para este microcontrolador que permite usar 16 colores, pero como coste nuestra resolución máxima se reduce a 320×240. Y en el caso de las librerías para Arduino Uno no superaríamos los 200 pixeles.


2021-06-03

-Prueba de botones para manejar el juego:

Voy a utilizar tanto un potenciómetro como dos botones que van a hacer la función del potenciómetro ya que solo necesitamos dos órdenes (izquierda o derecha)

*El potenciómetro leerá valores entre 0 y 1023

*Ambos botones están conectados al mismo pin de entrada, y leen una resistencia diferente en base a qué boton se pulse.
De esta manera en la lectura analógica de voltaje (valores 0-1024):
->Si no pulsamos nada devolverá 0
->Si pulsamos el botón con la resistencia de 1K devolverá 930
->Si pulsamos el botón con la resistencia de 2K devolverá 851
->Si pulsamos ambos botones devolverá 959

De esta manera conseguimos poder usar dos botones usando un único pin de entrada.

La idea es:
-Almacenar el último valor utilizado
*Como valor inicial mediremos un instante antes de empezar la partida
*Para evitar fallos:
>Si el valor inicial es 0 (0-2) (botón) lo ponemos a 900
>Si leemos 959 (958-960) no lo tomamos en cuenta (doble pulsación de botones)
-Si el nuevo valor medido es menor giramos hacia la izquierda y almacenamos el nuevo valor. Y viceversa en caso contrario.

Aprovecharemos el 959 de la doble pulsación para usarlo como botón de comienzo de partida.
*En el potenciómetro le pondremos un botón adicional que mida 959 para poder iniciar desde éste la partida.
\_En vez de liarlo con más componentes dejaremos a la pericia del usuario el encontrar el valor 959 en el potenciómetro para iniciar partida ^:)

Esquema de los botones para la prueba inicial con Arduino Pro Micro

Una vez todo probado y funcionando le imprimí una carcasa al potenciómetro, y la modifiqué en blender para duplicarla y así poder meter dos botones:

La carcasa es esta: https://www.thingiverse.com/thing:2970774

Y este el resultado una vez impresa y soldados los cables al potenciómetro

El día finalizó sin entender por qué no leía nada el potenciómetro en el ESP8266.


2021-06-04

Tras comprobar que los valores si eran leídos en el Arduino Pro Micro me da por fijarme que aunque el NodeMCU tenga muchas puertas de entrada salida, únicamente tiene UNA sola entrada para lectura analógica.

¿Solución? Pues o multiplexar las entradas que recibe tomándolas en intervalos de tiempo distinto o añadirle un módulo multiplexor como el ADS115.

Como la solución no me convencía del todo, he dado un paso atrás para dar dos hacia adelante (como a veces decía de forma metafórica mi maestro de artes marciales): He optado por usar el ESP32.

El Esp32 es otro microcontrolador ligeramente más potente, y que incluye 18 canales ADC frente al único canal ADC que trae el ESP8266. Lo que nos permite no solo conectar un montón de mandos para jugar, sino ¡utilizar una resolución mayor para la pantalla y poder utilizar diferentes colores!

Lo podemos encontrar por 5€ en aliexpress. Lo cual me lleva a hacer un paréntesis:

Para encontrarlo y comparar precios en aliexpress he tenido que buscarlo a través de la red de Tor, ya que por lo visto aliexpress está ocultando resultados de las búsquedas a los usuarios en base a ¿Su ip?. El caso es que cada vez que cambiaba de ip me mostraba una, tres, siete, o incluso 0 páginas de resultados de productos. Me di cuenta cuando buscando "ttgo" o algo tan simple como "vga female connector", no aparecía nada.

Como quiero avanzar ya el proyecto aprovechando que ahora tengo tiempo libre, lo pedí a amazon al doble de precio :/ (tiempo es dinero)

Dado que la parte de pruebas con el microcontrolador está capada hasta que me llegue, he seguido avanzando diseñando el pseudocódigo y soldando el pequeño circuito de los botones.

Dos botones con su correspondiente tapa marcada con el nombre del mítico juego

Y por último el pseudocódigo

->calcular la salida aleatoria de cada jugador y almacenarla (posición y ángulo)
	*con una ligera mayor probabilidad de aparecer en el centro y apuntando hacia el centro
LOOP
	->ponemos el contador de rondas a 0
	LOOP
		->calcular sig. pos. con el ángulo 
			*librería "Coordinates.h" integrada en arduino. 
			->Llamamos a fromPolar() con el ángulo en radianes y nos lo transforma en coordenadas que almacenamos en float
		->dibujamos la posición tomando los vectores x e y transformados a cartesiano a partir de fromPolar() y para dibujar redondeamos el valor con floor()
		->calculamos si colisiona con otro jugador, o pared si hay límites en el mapa
		->finalizamos partida si hubo colisión BREAK
		->leemos mando
			->IF analogRead lee un valor superior del mando (+/-15) 
				-> aumenta   el ángulo x grados a la derecha
			->IF analogRead lee un valor inferior del mando (+/-15) 
				-> disminuye el ángulo x grados a la izquierda
	ENDLOOP
	->sumamos número de rondas
	->IF rondas == max_rondas
		->mostramos la puntuación y salimos del bucle BREAK
ENDLOOP

2021-06-05

He decidido cambiar la forma de medir los controladores.
Ya no mediré “izquierda” si el valor es menor que el anterior, sino si es menor que 500 en la lectura analógica y viceversa para la derecha.
Ya no solo porque la forma anterior era más enrevesada, sino también porque estoy casi seguro de que con esa configuración la sensibilidad con botones tendría que ser muy alta y con el potenciómetro muy baja para lograr un control medianamente jugable. Y quiero poder conectar uno u otro indistintamente. De esta manera no tendría problemas.

Como ya hice ambos controladores, lo que he hecho es añadir al mando de botones 3 resistencias de 10Kohm entre tierra y la señal de entrada, de esta manera serán sumados en paralelo al que tiene actualmente, y nos devolverá una medida analógica que para el botón izquierdo ronda los 470 y para el derecho los 640. Para el próximo controlador que haga usaré directamente una resistencia de 2.5KOhm entre tierra y señal en vez de la de 10KOhm que usaba antes y así conseguir estos valores de medida por encima y por debajo del 500.

En otro orden de cosas, esperaba el ESP32 para el lunes, pero el pobre repartidor sobreexplotado de amazon no esperó tanto tiempo.

Así que hoy mismo he conseguido probarlo y ver que lee bien los mandos e imprime con distintos colores por vga a 800×600 pixels. Yesss!


2021-06-06

Hoy estuve viendo que funciones trae integradas la librería de vga ESP32lib que estoy usando.

Entre ellas, las más básicas, importantes, y las que sé para que sirven (dado que el autor no ha puesto documentación en su web ni comentarios en el código de la librería para entender qué hacen) son:

Funciones:
	setCursor(x,y) ponemos el cursor para pintar donde queramos
	get(x,y) devuelve el color de ese pixel
	RGBA(r,g,b,a) color con alpha
	setTextColor( color ) color de texto (tiene un posible segundo parámetro que no entiendo)
	setFont( font ) fuente
	print , println
	clear(color) limpia la pantalla (sin argumentos la pone negra)
	scroll(dy,color) hace scroll hacia abajo (mueve todos los pixels)(por lo que ví en el código si se pone dy negativo creo que lo mueve hacia arriba)
	líneas y figuras:
			xLine(x0,x1,y,color)
			triangle(v0,v1,v2,color)
			line(x1,y1,x2,y2,color)
			fillRect(x,y,w,h,color)
			rect(x,y,w,h,color)
			circle(x,y,r,color)
			fillCircle(x,y,r,color)
			ellipse(x,y,rx,ry,color)
			fillEllipse(x,y,rx,ry,color)
	
Variables:
	cursorX,cursorY lugar del cursor en este momento

También he programando toda la parte del gusano en movimiento y giros.

Para esta tarea hay que transformar coordenadas polares a cartesianas.

Me explico:

Para moverme por un escenario en 2 dimensiones, estoy limitado a los pixels que me ofrece el sistema. En este caso, 800 de ancho por 600 de alto.
Al mover pixel a pixel cualquier figura (en este caso el gusano), si lo movemos en línea recta sobre los ejes x o y, no tendremos problemas, pero si queremos moverlos en un ángulo diferente al 0,90,180,270 necesitamos calcular virtualmente la posición real de ese ángulo en coordenadas y almacenarla porque no podemos representar un punto decimal en pixels ya que son numeros enteros. Así que lo que hacemos es acumular esos decimales y en el siguiente paso sumarle los del anterior que no sumaban un número entero hasta sumar un numero superior o igual a 1 para ese eje.

Por ejemplo para girar a la izquierda, usaremos 30º y un radio de 1 (1 pixel). Esto pasado a coordenadas cartesianas, sería un punto situado en 0.87pixels del eje X y en 0.5 pixels del eje Y, y no lo podríamos representar como pixel en la pantalla.


2021-06-07

Tras ajustar bien los rangos de giro (la cantidad de radianes y cada cuanto tiempo es leído el mando).
Y arreglar problemas con las transformaciones polares (el rango negativo no lo había diseñado bien y además no se acumulaban bien los decimales sobrantes al sacar las coordenadas cartesianas).
Ya se mueve el gusano por la pantalla en todos los ángulos manejado por el controlador de dos botones o el potenciómetro.


*Y ahora han surgido dos fallos inesperados.

>Fallo 1: a veces de forma aleatoria la pantalla parpadea, pero solo si la sobrecargo con la impresión de valores de variables. Y no es tema de memoria ram ya que tiene suficiente libre al mostrarla por pantalla.
>Fallo 2: con el botón derecho consigo hacer circulos perfectos, pero no con el izquierdo.
*Esto ya está arreglado y se debía a que cuando gira a la izquierda y los radianes son menores que 0, en vez de partir desde 2*PI, sumarle los actuales y restarle los del giro, yo le restaba los actuales.

Superados estos fallos ya puedo comenzar a estructurar un poco el código, meterle colisiones, y más gusanos.


2021-06-18

Hoy me he dedicado a soldar casi todos los pines del pcb y el conector vga.


2021-06-21

Entre ayer y hoy he terminado el diseño/impreso de la carcasa en 3D de mi versión inicial.


Más adelante seguiré actualizando este diario tecnológico. 🙂

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

*

code

nasa pic of the day