Desarrollamos firmware de pedal para aprender a tocar la balalaika

Realmente amo los videos tutoriales. Por alguna razón, personalmente percibo muy mal la información del texto. Pero hay cosas en las que no hay mucha información en papel. Tomemos, por ejemplo, las lecciones de tocar la balalaika: en YouTube hay maravillosas discusiones sobre cómo tocar esta o aquella melodía (a quién le interesa, estamos buscando "Sergey Vorontsov"), pero es difícil repetir y memorizar la secuencia del video en tiempo real. Es necesario ya sea escribir en papel (a juzgar por los comentarios de las lecciones, algunos lo hacen) o comprar materiales adicionales (pero no soy codicioso, sino hogareño).



En general, en mi caso de balalaika, y con muchos otros, tengo que ir así: miré el fragmento, lo detuve, lo repetí varias veces detrás del autor y seguí mirando. Si algo no está claro: rebobinado, mira más de cerca. ¿Pero cómo terminarlo todo si tus manos están ocupadas? Además, en mi caso están ocupados, si no con un gran acordeón de botones, pero aún algunos, pero con una balalaika. Entonces, necesitas trabajar con tus piernas.

Hace muchos, muchos años, cuando toda la humanidad progresiva usaba teclados PS / 2, nos trajeron docenas de teclados USB para el proyecto. Por supuesto, los conectamos a una máquina, presionamos Ctrl en una de ellas, Alt en la segunda y Del en la tercera. El efecto se ha logrado. Desde entonces, sé que los teclados USB funcionan completamente en paralelo, por lo que puede conectar otro para ayudar al principal, que enviará algunos códigos en su lugar.

Entonces, la idea nació para hacer un pedal que finge ser un teclado y envía códigos de control del jugador. Como jugador, inicialmente elegí VLC Player, ya que tiene botones de control bien documentados, pero luego resultó que los códigos que seleccioné tenían exactamente el mismo propósito al ver videos en YouTube en modo de pantalla completa. Esto es bueno, porque con múltiples vistas en línea, para las impresiones del anuncio, algo parece caer en la mente del autor. Verlo descargado no sería tan ético.

Entonces, comenzamos a diseñar el dispositivo.

Lógica de trabajo


Al principio quería hacer varios pedales, cada uno para su propia función. Inicialmente, conté 3-4 de estas funciones: encendido, apagado, viento allí, viento de regreso. Pero luego descubrí cuánto plástico tomaría, además, cómo entendería los pedales al tacto, y me entristeció. Por lo tanto, se decidió revisar radicalmente toda la lógica. ¿Qué características se necesitan en absoluto? Start-stop, pero a menudo depende de la misma tecla, generalmente en un espacio. Y rebobinando. VLC Player tiene "Shift + Izquierda". YouTube, como resultó, también. Y, si lo crees, no hay más funciones.

Genial Hagamos que el pedal use brevemente la función "Start-Stop", y durante mucho tiempo con la función "Rewind".

En el futuro, puede ampliar la funcionalidad. Puede entrenar el pedal para reconocer el código Morse. Mi esposa, al enterarse de la idea, sugirió codificar impulsos de control utilizando elementos de danzas irlandesas ... En general, puede ampliar la funcionalidad a su gusto. Pero una cosa está clara: un pedal es suficiente. Bueno, ahora haremos el reconocimiento de prensas largas y cortas.

La mecanica


Para aquellos que caminan en casa con zapatillas, hay una solución muy simple (la encontré en el sitio web de Thingiverse). Tomamos un botón con un diámetro de más de un centímetro, lo atornillamos a cualquier objeto en forma de caja, obtenemos un pedal. El problema es que no me gustan las zapatillas, por lo que esta opción no me conviene personalmente. Necesito una superficie más grande para que el pie no duela.

Los pedales en grandes cantidades se venden en Ali Express, debe buscar la palabra interruptor de pie. Los precios comienzan en 30 rublos, pero a este precio, el costo de envío puede ser de unos cuatrocientos rublos. Después de buscar, descubrí que es bastante posible encontrar un pedal para el cual la suma "precio más entrega" será de 150 rublos. Pero tendrá que esperar un promedio de un par de meses (he estado esperando aquí recientemente una tarjeta SD durante los tres meses).

Así que fui por el camino más rápido: hice un pedal en una impresora 3D. La experiencia personal (y todas las opciones con Thingiverse) muestran que el eje debe ser metálico, de lo contrario, todo se romperá rápidamente. Tomé el perno del mueble M6x60 que tenía con la tuerca unida a él, así como el botón (PSW-13), que estaba en las piezas de radio vecinas, y los rodeé tan plásticos como pude. Así es como se veían los materiales de origen:



Aquí están, insertados en la mitad inferior. Como puede ver, la característica principal del diseño son las paredes, de al menos cuatro milímetros de espesor. Con estos parámetros, incluso un prototipo suave se vuelve bastante duradero. El botón se instala sin una tuerca, ya que cualquier vacío debajo de él provocará la ruptura del plástico, y se mantiene bastante bien.



Aquí hay una versión casi compilada:



Y aquí está el montaje del pedal:



En principio, adjuntaré los archivos STL, pero la solución no fue perfecta. Sin embargo, cualquiera puede repetirlo (si encuentra el perno M6x60 con la tuerca correspondiente y el botón PSW-13). Suficiente por primera vez, y luego, puede estampar la mecánica y ordenar con ALI.

Dispositivo USB


Aunque últimamente he estado promoviendo activamente PSoC, usarlo en los pedales es un desperdicio inaudito. Considero que la mejor solución es una placa de pruebas basada en STM32F103C8T6, que ahora se puede pedir en ALI Express por aproximadamente 120 rublos (incluida la entrega).



Por supuesto, podemos especular que hay placas más baratas basadas en AVR, pero la diferencia de precio no es significativa allí, y STM32 tiene significativamente menos tiempo de desarrollo debido a la depuración a través de JTAG. Una hora de tiempo (incluso en casa): también cuesta algo. Entonces, de acuerdo con el criterio total "precio del dispositivo + costos laborales", STM32F103 es la mejor opción para esta tarea. Además, tengo una docena y media de maquetas en la tienda para tal caso, por lo que el tiempo de espera de entrega ahora es igual a cero para mí.

Navegué por la red en busca de teclados USB listos para usar basados ​​en este chip. Encontré un artículo sobre Habr sobre cómo hacer un mouse USB. Pero necesito un teclado. Sobre el tema de los teclados, encontré muchos consejos inteligentes en los foros (pero quería algo listo) y algunos proyectos complejos pero completados en GitHub (pero quería algo claro). Pero el que busca siempre encontrará. Aquí hay un artículo maravilloso en el que hay todo lo que se necesita (aunque hay uno en el código, no tengo miedo de esta palabra no rusa, DeadLock potencial, pero escribiré mi propio código). Lo principal es que todos los pasos se describen claramente en él, cómo obtener un teclado USB de un "pez" terminado hecho en Cube MX. Lo único que el autor no hizo fue no publicar los códigos clave. Agréguelos aquí:



Lo importante es que en la versión moderna de Cube MX, los nombres de archivos, funciones e incluso constantes son ligeramente diferentes de los especificados en ese artículo, pero por analogía todo se encuentra rápidamente. Podría escribir una nueva versión del texto, pero ¿dónde está la garantía de que los desarrolladores no cambiarán todo de nuevo? A ellos les gusta hacerlo. En general, puedes ver los análogos en mi ejemplo.

Entonces Creé un proyecto básico en Cube MX, hice todos los cambios recomendados por el artículo mencionado anteriormente. Que sigue A continuación, agregue la descripción del puerto del botón. Elegí PB12 (simplemente porque el contacto correspondiente se encuentra en la esquina de la placa de pruebas). Como siempre trabajo con hierro a través de la biblioteca mcucpp de Konstantin Chizhov, eliminamos la definición de macro “-C99” en las propiedades del proyecto, cambiamos el nombre de main.c a main.cpp y luego agregamos la declaración:

typedef Mcucpp::IO::Pb12 pedal1; 

Agregamos la inicialización de puertos a la función main () (habilitación de marcado de puertos, configuración de la dirección de la pierna, encendido del suspensor):

 pedal1::ConfigPort::Enable(); pedal1::SetDirRead(); pedal1::SetPullUp (pedal1::Port::PullUp); 

En realidad, todo se inicializa. Decidí construir el cuerpo principal en la imagen del proceso Verilog. No sé por qué, solo quería hacerlo. El proceso generalmente se llama en pulsos de reloj. Decidí que los ticks del sistema se toman perfectamente como ticks. Por lo tanto, la función regular del controlador de tics del sistema en el archivo stm32f1xx_it.c se agregó de la siguiente manera:



Mismo texto:
 void SysTick_Handler(void) { /* USER CODE BEGIN SysTick_IRQn 0 */ /* USER CODE END SysTick_IRQn 0 */ HAL_IncTick(); HAL_SYSTICK_IRQHandler(); /* USER CODE BEGIN SysTick_IRQn 1 */ TickProcess(); /* USER CODE END SysTick_IRQn 1 */ } 


Puse la función TickProcess () en sí misma en main. cpp . Primero, considérelo en su totalidad, luego en partes.

Aquí está la función completa:
 uint8_t report [8] = {0,0,0,0,0,0,0,0}; uint32_t* pReport = (uint32_t*)report; extern "C" void TickProcess() { //      20!!! static const int shortTime = 700; //      static const int longTime = 2000; //    static int localTick = 0; static int tickDuringButton = 0; static bool bButtonStatePrev; bool bButtonState = pedal1::IsSet(); //     if ((!bButtonState) && bButtonStatePrev) { tickDuringButton = 0; } //     if (bButtonState && (!bButtonStatePrev)) { //       //  ,  50  () if ((tickDuringButton >100)&&(tickDuringButton < shortTime)) { //    report [2] = 0x2C; } } //    if ((!bButtonState) && (!bButtonStatePrev)) { if ((tickDuringButton == shortTime)||(tickDuringButton > longTime)) { //  Shift+ report [0] = 2; // Shift report [2] = 0x50; //  } } //    bButtonStatePrev = bButtonState; tickDuringButton += 1; if (localTick++ % 20 == 0) { USBD_HID_SendReport (&hUsbDeviceFS,report,sizeof(report)); pReport [0] = 0; pReport [1] = 0; } } 


La primera tarea que se implementa en este controlador es simple. Cada 20 milisegundos enviamos un informe que contiene información sobre los botones presionados (si no hay botones, los enviamos de todos modos, solo con ceros). Como la función se llama cada milisegundo, el informe debe enviarse a una de sus veinte llamadas. Para hacer esto, hay una variable al comienzo de la función:

  static int localTick = 0; 

y el código al final (enviamos los datos, después de lo cual borramos el búfer para comenzar a enviar ceros desde la próxima sesión):

  if (localTick++ % 20 == 0) { USBD_HID_SendReport (&hUsbDeviceFS,report,sizeof(report)); pReport [0] = 0; pReport [1] = 0; } 

La segunda tarea es más complicada. Realiza un seguimiento de la naturaleza de presionar el pedal y llena el informe para su posterior envío. ¿Por qué dije que la ideología es como Verilog? Porque siempre capto las diferencias en ese idioma: tengo una variable en la que se coloca el estado actual del botón:

  bool bButtonState = pedal1::IsSet(); 

y hay una variable en la que se almacena su estado anterior (como recordamos, el estado anterior es el estado del botón durante el procesamiento de interrupción anterior desde el temporizador de 1 ms):

  static bool bButtonStatePrev; 

El botón presionado da el valor falso , el botón presionado - verdadero . Por lo tanto, siempre podemos concluir sobre el estado dinámico del botón:

bButtonStatebButtonStatePrevCondición
ciertociertoLargo liberado
ciertofalsoLanzado en la medida anterior
falsociertoPresionado sobre medida anterior
falsofalsoLargo presionado

Introducimos dos constantes. Uno establece el tiempo de prensa corto. Si la prensa duró menos de 700 ms, entonces es de corta duración. El segundo establece el tiempo cuando la repetición automática está activada. Si justo después de setecientos milisegundos comienzas a enviar el código clave, el reproductor comenzará a enrollarse demasiado abruptamente. Esto se identifica empíricamente. Por lo tanto, la lógica del trabajo es la siguiente: después de 700 ms, se envía un solo código "Shift + Left", después de lo cual el usuario tiene la oportunidad de soltar el pedal. Si el pedal continúa presionado, desde el segundo segundo el envío constante de este código ya comienza hasta que se suelta el pedal.

  const int shortTime = 700; //      const int longTime = 2000; //    

El tiempo durante el cual se presiona el botón se almacena en una variable:

  static int tickDuringButton = 0; 

Si el botón acaba de presionarse, ponemos a cero esta variable, comenzando a medir un nuevo período de tiempo:

  //     if ((!bButtonState) && bButtonStatePrev) { tickDuringButton = 0; } 

Si el botón se acaba de soltar, verificamos la hora en que se presionó. Si solo un poco (ahora dice "menos de 100 ms"), esto es una charla. Esto no cuenta. Ignora este clic. Si no hacemos nada más que la duración de la pulsación corta, a continuación se procesan las pulsaciones largas. Si, dentro de una breve presión, creamos un informe en el búfer con un espacio (que se enviará cuando llegue el momento):

  //     if (bButtonState && (!bButtonStatePrev)) { //       //  ,  100  () if ((tickDuringButton >100)&&(tickDuringButton < shortTime)) { //    report [2] = 0x2C; } } 

Si el botón se ha mantenido presionado durante mucho tiempo, enviamos "Shift + Left" en dos casos:

  • el botón se mantiene exactamente 700 ms (paquete único);
  • el botón se mantiene presionado durante más de 2 segundos (se envía cada informe posterior hasta que se suelta el botón).

  //    if ((!bButtonState) && (!bButtonStatePrev)) { if ((tickDuringButton == shortTime)||(tickDuringButton > longTime)) { //  Shift+ report [0] = 2; // Shift report [2] = 0x50; //  } } 

Eso, de hecho, es todo. Este código no es más diferente del "pez" que Cube MX nos hizo. Nos reunimos, flasheamos ... No, es imposible sin errores (aquí están todos atrapados, pero no pude prescindir de ellos inicialmente), los identificamos en 10 minutos a través de la depuración JTAG (hola a AVR), estamos cosiendo, estamos felices ...

Diseño alternativo


En general, tales cosas son útiles sin una balalaika (u otra visualización de video tutoriales). En particular, me gusta leer las noticias, acostado en la cama, con una computadora portátil en el estómago. Para desplazarse por el texto, debe mantener la mano derecha doblada todo el tiempo, y esto provoca dolor en el codo. Por lo tanto, siempre he soñado con un gran botón rojo que podría desplazar las páginas sin doblar el brazo. En realidad, puede fabricarse con los mismos componentes que el pedal, reemplazando el perno del mueble con una pequeña cantidad de pegamento caliente. Total: botón PSW13, placa de prueba STM32F103C8T6, plástico para impresora 3D, adhesivo termofusible. Bueno, en el "firmware" reemplacé los códigos con "PgDn" presionando brevemente y "Arriba" por uno largo.





Conclusión


Puede usar sus piernas para controlar la visualización de videos tutoriales cuando sus manos están ocupadas. Para hacer esto, solo un pedal que simula el funcionamiento del teclado USB. Un pedal puede enviar múltiples códigos de teclas, seleccionándolos en función de diferentes tipos de pulsaciones de teclas. El artículo considera un pedal que analiza dos tipos (pulsación corta y larga).

La mecánica se puede encontrar en Ali Express bajo la palabra Foot Switch o se puede imprimir en una impresora 3D. Como electrónica, se puede utilizar la placa STM32F103C8T6. El "firmware" se realiza en menos de una hora sobre la base del "pez" creado por Cube MX del fabricante de controladores STM32. El código adicional ocupa varias pantallas de texto (para una resolución de 2K: una pantalla).

En general, todo el dispositivo (mecánica + "firmware") se diseñó por completo en una noche, además, se necesitaron unas cuatro horas para imprimir la mecánica en una impresora 3D.

Los archivos STL listos para la impresión a pedal se pueden descargar aquí (es conveniente bajar el elemento superior en 0,4 mm para evitar una gran cantidad de soportes: la superficie resultó ser ligeramente redondeada, bajando el modelo, haremos que la parte impresa quede plana).

Los archivos STL del "gran botón rojo" se pueden descargar aquí .

Los archivos de origen ya preparados para el proyecto y el archivo HEX para el firmware se pueden descargar aquí .

La fecha de publicación de este artículo no fue elegida por casualidad. El consejo decidió que es mejor publicar un artículo sobre tales cosas en un sitio serio ese día. Pero, de hecho, si mira los videos encontrados en las frases "Alexey Arkhipovsky", "Dmitry Kalinin", "Cranberry Show", "Alexey Kodenko", queda claro que la balalaika académica es como un ensamblador. Tanto allí como allí se combinan simplicidad absoluta y poder expresivo frenético. Y con la frase "Sergey Vorontsov" puedes entender cómo aprender a usar esta herramienta.

Además


Después de 8 meses de funcionamiento, el botón PSW-13 comenzó a funcionar una vez fuera de muchos, y solo con una presión muy fuerte. Al intentar reemplazar, resultó un detalle muy interesante. El nuevo botón, comprado al mismo tiempo que el anterior, tiene una reserva de energía completamente diferente y funciona en una posición completamente diferente. Como resultado, ella siempre estaba deprimida en mi pedal. Tuve que molerlo con un dremel. ¿Quién repetirá mi mecánica? Tenga en cuenta. Puede que tenga que modificar el botón con un archivo o viceversa, esculpir una cinta aislante para aumentarlo. La repetibilidad de la parte plástica de este botón no fue muy. Pero en general, después de tal revisión, todo vuelve a funcionar.

Source: https://habr.com/ru/post/445160/


All Articles