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