Techo - Una GUI para la EVT de CH32V003
El CH32V003 se hizo famoso por su bajo precio, un chip de menos de 0.5€. Pero el precio no lo es todo. Disponer de kits de desarrollo a un precio muy ajustado y un IDE profesional, como es MounRiver, además de sus increibles características, ayudan mucho.
Puedes encontrar sus especificaciones en CH32V003.
La idea
Hace algo más de 6 meses lancé Techo, una herramienta que permitía a este pequeño microcontrolador, utilizando la placa mostrada arriba, operar de forma parecida a un osciloscopio.
Evidentemente solo puede estudiar señales en DC, pero es una herramienta útil que es algo más que un simple prototipo sin utilidad.
Todo esto viene de un antiguo proyecto que tenía en el cajón desde hace tiempo pero que, desde hace más o menos un año he estado desarrollando.
La idea vino tras leer Programming Arduino Next Steps de Simon Monk y el fabuloso blog de Jean-Claude Wippler (JeeLabs) donde en 2010 realizó un pequeño prototipo de oscilocopio con menos de 100 líneas de código. Posiblemente, este blog (aunque antes tenía otro dominio), es de los 3 mejores blogs que he leído nunca sobre electrónica/informática. Aquí su github.
Al final, la idea del proyecto es tan idenpendiente que he podido replicarla en diferentes osciloscopios:
- uno creado con Arduino y CA3306
- DSO112A de JyeTech
- DSO183 de JyeTech
- DSO152 de FNIRSI
Ya que simplemente necesito la lectura del ADC y su frecuencia de sampleado (para el espectrograma).
Mucho mejor si el osciloscopio tiene un protocolo de comunicación con el que poder controlarlo, como el DSO112A, pero si no lo tiene, también la herramienta es útil.
El “osciloscopio”
Por tanto, al aplicar esta idea a la plaquita del CH32V003, obtuve un pequeño “oscilocopio” capaz de llegar a 1.7Msps.
Aunque la documentación de WCH no se puede comparar con la de STM, es cierto que viene con una serie de ejemplos, así que se puede empezar a cacharear.
La primera versión de Techo seguía el patrón de sus hermanos mayores:
- enviar los datos del ADC como cadenas de longitud fija
Pero esta vez el ADC es de 10b y con 2kB de RAM la cosa pintaba mal. Aún así, Techo era una realidad.
Punta de lanza
Estos días he estado continuando el desarrollo de TDSO152, el programa que permite controlar el DSO152 de FNIRSI. Aunque el programa funciona bien, y estoy contento, siempre quieres mejorar ciertas cosas (tal vez por eso, esto del software es una mierda… porque siempre estás mejorando cosas y las mejoras nunca se acaban).
La principal idea es integrar TDSO152 con Sigrok, y para ello tenía que implementar el disparo del trigger en el propio firmware.
Esto me llevó a pensar a que necesito un buffer circular y sin quererlo, me vinieron a la cabeza dos ideas más:
- cómo hacer para reducir la RAM necesaria para el buffer
- mejorar/simplificar el protocolo para la lectura de los datos del ADC
Ahí entra Techo, porque es un proyecto más sencillo.
Paso de un buffer de 2B a 1B
Como el ADC es de 10b, un buffer de 512 puntos ocupa el solito 1kB (512 x 2 = 1024). Lo que es algo justo teniendo en cuenta que el CH32V003 dispone de solo 2kB.
Aunque está en la documentación, y ya lo había hecho antes con Arduino, no se me había ocurrido alinear el RDATAR a la izquierda y usar solo 8b para el buffer. Al haber leído que el ADC usa 10b sí o sí, me hice la idea mental de que el buffer tenía que ser de 2Bytes.
Lo que yo hacía es obtener los 10b del ADC y después en el programa, quedarme con los 8 más significativos.
Justo ayer la cabeza me hizo click e hice una prueba con la alineación
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Left;
...
DMA_Tx_Init(DMA1_Channel1, (u32)((volatile u8 *)&ADC1->RDATAR + 1U), (u32)ADCBuf, ADCBUFSIZE);
y los ajustes para que el DMA trabaje con bytes en lugar de words
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
¡¡tacháaaaaan!!
y ya puedo utilizar mi buffer de 8b volatile u8 ADCBuf[ADCBUFSIZE];, con lo que ya puedo usar sin problema los 512 puntos (incluso puede que pueda usar 1024…)
Optimización inesperada
Si todos los datos del ADC son de 8b ¿por qué no enviar un byte en lugar de cadenas de bytes?.
En versiones anteriores enviaba cadenas de 4 dígitos + 1 espacio (en realidad en lugar de 4 dígitos me valía con 3). Es decir, para un byte de datos enviaba 5 bytes… Por tanto, enviando 1 byte aumentaba la velocidad de refresco x5.
Esto también traía una optimización inesperada. Cuando enviaba las cadenas de los datos del ADC, puesto que se transmiten por USART, pueden llegar fraccionadas, por ejemplo, 016 0 21 03 8… Es decir, estaba obligado a tener que agrupar de 3 en 3 para no perder datos válidos. En la primera versión simplemente los perdía. Todo aquello que no seguía el formato esperado, era descartado, lo que provocaba que las señales del osciloscopio estuvieran algo sucias (se podían usar, pero en el estudio frecuencial se veían sucias).
Ahora con la transmisión byte a byte, te puedes olvidar de eso.
El prototipo era funcional, pero había un pequeño detalle: otra vez la comunicación asíncrona. Aunque el CH32V003 envía 512 datos del ADC no sabemos cómo van a estar empaquetados, así que se pueden mezclar unas tramas con otras, lo que se manifiesta en glitches en la señal.
Gracias a Dios que este era un problema fácil de solucionar: crear una cabecera al inicio de la transmisión. Con esto ya podríamos tener una máquina de estados, FSM (Finite State Machine), para controlar el flujo. Esto ya lo hacía con el DSO112A de JyeTech y funcionaba muy bien.
Evidentemente, hubo que cambiar otra vez las tripas de la UI, pero esta vez solo teníamos que asegurarnos de que el puerto serie leía en formato byte, y teníamos que crear una pequeña FSM.
Aquí se puede ver una senoidal de 100kHz y su espectrograma.
Como se puede ver, la claridad de las señales son muy buenas. ¡¡Recordemos que esto lo estamos haciendo con un micro de menos de 0.5€!!
Especificaciones
Yo estoy alimentando la placa a 3.3V, así que puedo estudiar señales de 0-3.3V, aunque parece que se puede alimentar a 5V sin problemas. Es más, esta es la tensión recomendada para hacer funcionar el ADC a 24MHz (3.3.14 10-bit ADC characteristics).
Con esta velocidad de reloj, el ADC toma 24MHz/(11 + 3)ciclos = 1.7Msps, con lo que podemos estudiar señales de 1.7x10^6 / 8 muestras/cliclo = 200kHz y detectar correctamente señales de hasta unos 1.7x10^6 / 2 = 850kHz.
Y la teoría concuerda con la práctica:
Como vemos estamos ya al límite en la frecuencia en la que podemos representar señales.
Aquí aún nos sobran 50kHz hasta llegar a fs/2, que es el eje de simetría, aunque es cierto que tenemos ruido, sobre todo en frecuencias bajas (picos al principio y al final de la gráfica. Todo es simétrico respecto a fs/2).
El compañero ideal
Aunque por sí mismo, ya creo que es un circuito útil a un precio más que razonable, el DSO183, tiene un par de cosas muy buenas, y es que, además de mostrarte el esquemático, tienes accesible el frontend analógico… es decir, puedes usarlo para que nuestro pequeño Techo sea un osciloscopio de verdad.
Utilizas el frontend, y sacas la señal ya normalizada por el punto V2, y lo llevas a tu EVT CH32V003.
Cierto es que para que de verdad mole, hay que cambiar los interruptores manuales por unos pequeños relés y poder así controlarlo desde el propio PC… pero es un inicio.
Aquí podemos ver el montaje para una senoidal de 20Vpp en AC a 200kHz.
y Techo
Evidentemente no están calibrados los niveles de tensión, pero la frecuencia es correcta. Es más, parece que se visualiza mucho mejor (esto es debido a que no cargamos el ADC ya que el front-end del DSO183 tiene un AO como seguidor).
Podemos pensar que con el DSO183 podemos llevar más allá también en la frecuencia a nuestro pequeño CH32V003, veamos una senoidal a 300kHz:
que si lo comparamos con las capturas del CH32V003 sin el DSO183, vemos una apreciable diferencia:
pero en realidad es debido a la amplitud aparente de la señal. La primera, al ser más pequeñita parece menos algulosa, pero evidentemente, el número de puntos es el mismo… así que no, en principio el resultado es estéticamente más bonito, pero en la realidad es (casi) lo mismo.
Futuro
Evidentemente, la próxima modificación hardware es controlar el DSO183 mediante el PC, así que se vienen transistores y relés… pero es que tengo un osciloscopio propio con Arduino y CA3306 a 5Msps que tengo que terminar y modificar para usar una Black Pill y poder llegar a los 15Msps (sí, el CA3306 está muy desfasado hoy día, pero es tan fácil de montar que da mucho juego).
Así podré usar el front-end para otros osciloscopios… o incluso modificar su firmware para tener algo propio…
¡¡Se vienen muchos proyectos nuevos!!