martes, 5 de junio de 2018

Osciloscopio - Arduino - wxwidgets

Página principal

Osciloscopio
Arduino
wxwidgets

Hace tiempo había realizado un pequeño osciloscopio con un arduino. arosc.html
El programa que manejaba el osciloscopio lo había realizado con las librerías SDL, una librería especializada para juegos. Funciona bien y es multiplataforma, habiendo compilado en Windows y Linux.
Ahora como estaba en la época de la librería wxwidgets, era una buena ocasión de realizar el programa con esta librería.

Programa realizado con la librería wxwidgets.

Se ha mejorado bastantes cosas, una de ellas es la muestra real del voltaje en modo auto.
En el programa que hice bajo SDL la detección de la placa era automática, en este caso solo detecta los posibles puertos serie, nosotros debemos de seleccionar el adecuado. La rutina que me funcionaba en SDL no me funciona bajo wxwidgets, es curioso pero es así, no he querido profundizar de momento.
Otra cosa que me ha ocurrido es la diferencia entre versiones de librerías wxwidgets entre 2.8.12 y 3.1.1. Algunas rutinas funcionan y otras no, por lo que he tenido que retocar el código. Ahora funciona perfectamente en Linux y Windows (librería estatica o DLL), aunque veo que es algo más rápido bajo Linux.


PROGRAMA
Debian 9.4  y windows XP

Hasta pronto.
JUAN GALAZ


Bibliografía:
wxtutor.html
wxtem.html


viernes, 25 de mayo de 2018

Serial plotter con wxwidgets

Página principal
Serial plotter
wxwidgets

El programa Serial plotter es una utilidad que tiene arduino en versiones 1.6 . Sirve para crear una gráfica de dos canales analógicos que representan la tensión de los pines A0 y A1 del arduino.
Había realizado un programa parecido en Gambas (Visual Basic para Linux) ardupu.zip, y como estaba haciendo programas con la librería wxwidgets, decidí hacerlo con está librería.
La programación se realiza bajo Linux  Debian 9.4 y con la librería wxwidgets versión 3.1.1, esto lo especifico por su importancia.
La programación ha sido un tanto liosa y complicada.
En principio por los pocos ejemplos de dibujo en la librería de wxwidgets.
La segunda causa soy yo, no soy bueno en la programación en C++ , y en ciertas ocasiones pienso que hay tanta abstracción en la programación de objetos, que en algunos casos llega a convertirse en programación ofuscada.
El colocar los distintos botones y controles fue fácil, el problema fue el dibujado de lineas y control del repintado, me llevo bastante tiempo.
En Linux Debian 9.4 y bajo librería wxwidgets versión 3.1.1 el programa funciona perfectamente.
Pero cuando lo compile bajo Windows en las librerías
librería 2.8.12 y 3.1.1, compilaba bien, pero el funcionamiento era dispar.
Bajo la librería  2.8.12  simplemente no funcionaba se quedaba colgado.
Bajo la librería 3.1.1 el funcionamiento era extraño,  en principio funcionaba bien, pero cuando se interactuaba con él programa, se bloqueaba. Después de muchas pruebas el único modo de que funcionara era modificar la cantidad de datos que mandaba el arduino, de los 40 por segundo, debía rebajarse a los 10 por segundo.
Los datos que manda arduino por segundo son 40*9=360 Datos/Segundo , 360*10=3600 bps. Debería se suficiente la velocidad de 115200 del puerto serie.
Después de muchas vueltas buscando alguna solución, la encontré. Modificar los tiempos de espera entre bytes en la configuración serie. Esto se consigue cambiando los parámetros:
    time_out.ReadIntervalTimeout =     10;    //20;   
    time_out.ReadTotalTimeoutMultiplier = 1;    //2;
    time_out.ReadTotalTimeoutConstant = 2;    //50;

También existía diferencia entre las versiones 2.8.12 y la 3.1.1 en el repintado (onPaint) . Aunque en Linux funcionaba perfectamente en las dos versiones de las librería, en  Windows no pasaba lo mismo.
Para arreglar esto modifique:
#if YesWindows   
    dc.Blit(31,5,768,255, dcBuffer, 31, 5, wxCOPY, true);
#else
    dcPantalla->Blit(31,5,768,255, dcBuffer, 31, 5, wxCOPY, true);
#endif   

De esta forma funcionaba en los dos sistemas operativos.
Existe algún problema en el repintado, pero eso solo pasa si tenemos ventanas por encima de la nuestra.
También se podría realizar una rutina donde se busquen los puertos serie disponibles, es fácil, pero eso os lo dejo hacer a vosotros.


Programa funcionando.


Programa funcionando y con el código donde se muestra el programa que tiene que instalarse en el arduino.

PROGRAMA

Hasta pronto.
JUAN GALAZ


Bibliografía:
wxtutor.html
wxtem.html


viernes, 18 de mayo de 2018

Pequeño terminal serie , wxwidgets

Página principal

wxwidgets
Pequeño terminal serie


Había realizado varios programas que utilizaban el puerto serie, pero no había realizado un terminal serie.
En este programa realizo un pequeño terminal serie multiplataforma utilizando la librería wxwidgets.
Es sencillo sin muchas complicaciones, solo admite 8 bits.
He realizado la compilación bajo las versiones de las librería 2.8.12 y 3.11 , en formato estatico y con DLL.
Cuando se  compilan en dinamico se necesitan las DLL . wxtemdll.zip




PROGRAMA

Hasta pronto.
JUAN GALAZ



Bibliografía:
wxtutor.html
wxtem.html

sábado, 12 de mayo de 2018

Librería wxwidgets Crear programas multiplataforma

Página principal

Librería wxwidgets
Crear programas multiplataforma

Al crear un programa, lo primero que queremos es que sea utilizado por la mayor cantidad de gente. La plataforma que predomina es Windows, Linux y Mac solo es una pequeña parte de usuarios. Para el caso de querer que nuestro programa corra en las diferentes plataformas, debemos utilizar librerías multiplataforma, que con solo recompilar los archivos fuente, puedan ser utilizados los programas.
Para este caso vamos a utilizar la librería wxwidgets https://www.wxwidgets.org/.
En un anterior artículo wxtutor.html , había explicado como instalar y configurar wxWidgets en CodeBlocks bajo windows.
En este artículo he creado un monitor de temperatura externa, anteriormente lo había realizado en Gambas (VB para linux), pero bajo Windows no funciona. ard433.html
Para este programa he realizado varios makefiles para crear ejecutables para las diferentes versiones de librerías y modos, estaticas o DLL.
Al ser multiplataforma se recompila todo en Linux o Windows sin retocar ni una sola línea de código, salvo modificar el archivo define.h  y  poner:
    #define YesWindows 0
o
    #define YesWindows 1


Programa bajos Linux.


Programa bajos Windows.

Podemos observar los diferente ejecutables bajo Windows.
Los programas programa311.exe y programa1812.exe son pequeños, pero utilizan las DLL , que se tienen que colocar directorio system32 del directorio windows, o junto con cada uno de los ejecutables.
Los programas programa311s.exe y programa1812s.exe no necesitan las DLL, las llevan incorporadas en el propio programa. Son de mayor tamaño, pero quedan mejor en la distribución de un solo fichero para la utilización del programa. Se puede observar que dependiendo de la versión de la librería puede ser su tamaño más del doble.
Para reducir los programas ejecutables, se puede usar el programa upx.exe. Este programa comprime los ejecutables a la tercera parte. Se puede observar en los ficheros programa2812sz.exe y programa311sz.exe.

Para diferenciar entre programas, dll, y fuentes, los he distibuido en diferentes ficheros.

dll.zip

binarios.zip
fuentes.zip


Hasta pronto.
JUAN GALAZ

jueves, 10 de mayo de 2018

Configurando wxWidgets en CodeBlocks


Página principal

Configurando wxWidgets en CodeBlocks

xsetaseta@gmail.com


El otro día estuve viendo un magnífico video donde explicaba como configurar  wxWidgets en CodeBlocks bajo windows.
https://www.youtube.com/watch?v=LZacAgSBWa0
Son 26 minutos donde explica muy bien como configurar todo para poder compilar programas en windows.
En mi caso he utilizado:
Versiones de programas usadas
 wxWidgets-3.1.1  -  wxWidgets-2.8.12   -    CodeBlocks 17.12 -    tdm-gcc-5.1.0-3

He añadido el el Path de busqueda de windows el lugar de binarios del compilador.

%SystemRoot%\system32;%SystemRoot%;%SystemRoot%\System32\Wbem;C:\TDM-GCC-32\bin

Entrando en la consola y cambiando de directorio.
cd c:\wxWidgets-3.1.1\build\msw\
o
cd c:\wxWidgets-2.8.12\build\msw\

Para realizar las compilaciones de las librerías he utilizado la opción del compilador -j4  (4 procesadores) , que utiliza todos los procesadores de la máquina, reduciéndose bastante el tiempo de compilación.  También en mi caso lo hago para una máquina de 32bits.

-Para compilar las librerías estáticas usar lo siguiente:
mingw32-make -j4 -f makefile.gcc  RUNTIME_LIBS=static USE_XRC=1 MONOLITHIC=1 SHARED=0 UNICODE=1 BUILD=release TARGET_CPU=X32 CXXFLAGS="-std=gnu++11"

-Para compilar las librerías dinámicas usar lo siguiente:
mingw32-make -j4 -f makefile.gcc  RUNTIME_LIBS=dynamic USE_XRC=1 MONOLITHIC=1 SHARED=1 UNICODE=1 BUILD=release TARGET_CPU=X32 CXXFLAGS="-std=gnu++11"

Esto suele tardar bastante, dependiendo del tipo de procesador que tenga vuestro ordenador.
He realizado la compilación para las dos versiones de las librerías  wxWidgets (3.1.1 y 2.8.12) , por lo cual el trabajo ha sido doble.

Para los que no se quieran complicar mucho he creado un fichero donde se encuentran compiladas las dos librerías (wxWidgets-3.1.1 - wxWidgets-2.8.12)  junto con el compilador   tdm-gcc.
Solo tendrás que descomprimirlo en C:\ y empezar a utilizarlo. Tamaño 129M.
https://drive.google.com/file/d/1idPA5NczyadfQ4gUThiLbyIYrYJEkj05/view?usp=sharing  


Para que el  CodeBlocks no de errores en la compilación por falta de librerías he tenido que cambiar varias cosas en el menú del proyecto en Opciones de construcción.
Si compilamos programas en estático, cambiar   C:\wxWidgets-3.1.1\lib\gcc_dll  por   C:\wxWidgets-3.1.1\lib\gcc_lib






Listado de la consola de construcción
-------------- Build: Release in borrawx311 (compiler: GNU GCC Compiler)---------------
mingw32-g++.exe -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -DwxUSE_UNICODE -Wall -O2 -IC:\wxWidgets-3.1.1\include -IC:\wxWidgets-3.1.1\lib\gcc_dll\mswu -c "C:\Documents and Settings\Administrador\Mis documentos\borrawx311\borrawx311App.cpp" -o obj\Release\borrawx311App.o

mingw32-g++.exe -pipe -mthreads -D__GNUWIN32__ -D__WXMSW__ -DwxUSE_UNICODE -Wall -O2 -IC:\wxWidgets-3.1.1\include -IC:\wxWidgets-3.1.1\lib\gcc_dll\mswu -c "C:\Documents and Settings\Administrador\Mis documentos\borrawx311\borrawx311Main.cpp" -o obj\Release\borrawx311Main.o
windres.exe -IC:\wxWidgets-3.1.1\include -IC:\wxWidgets-3.1.1\lib\gcc_dll\mswu  -J rc -O coff -i C:\DOCUME~1\ADMINI~1\MISDOC~1\BORRAW~1\resource.rc -o obj\Release\resource.res

mingw32-g++.exe -LC:\wxWidgets-3.1.1\lib\gcc_dll -o bin\Release\borrawx311.exe obj\Release\borrawx311App.o obj\Release\borrawx311Main.o  obj\Release\resource.res -s -mthreads  -lwxmsw31u -lwxpng -lwxjpeg -lwxtiff -lwxzlib -lshlwapi -lversion -loleacc -lUxTheme -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32 -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lcomctl32 -lwsock32 -lodbc32 -lshlwapi -lversion -mwindows

Output file is bin\Release\borrawx311.exe with size 774.50 KB
Process terminated with status 0 (0 minute(s), 8 second(s))
0 error(s), 0 warning(s) (0 minute(s), 8 second(s))


El tamaño de los ejecutables resultan ser mas del doble en las dos en las diferentes versiones de las librerías.



He realizado un video de un programa realizado con  CodeBlocks

https://youtu.be/E6WA2n_Uib0

Para una mejor visión de todas las opciones de compilación, muestro el fichero resource.rc.
resource.rc
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
    <FileVersion major="1" minor="6" />
    <Project>
        <Option title="borrawx311" />
        <Option pch_mode="2" />
        <Option compiler="gcc" />
        <Build>
            <Target title="Release">
                <Option output="bin/Release/borrawx311" prefix_auto="1" extension_auto="1" />
                <Option object_output="obj/Release/" />
                <Option type="0" />
                <Option compiler="gcc" />
                <Option projectLinkerOptionsRelation="2" />
                <Compiler>
                    <Add option="-O2" />
                    <Add directory="C:/wxWidgets-3.1.1/lib/gcc_dll/mswu" />
                </Compiler>
                <ResourceCompiler>
                    <Add directory="C:/wxWidgets-3.1.1/lib/gcc_dll/mswu" />
                </ResourceCompiler>
                <Linker>
                    <Add option="-s" />
                    <Add library="libwxmsw31u.a" />
                    <Add library="libwxpng.a" />
                    <Add library="libwxjpeg.a" />
                    <Add library="libwxtiff.a" />
                    <Add library="libwxzlib.a" />
                    <Add library="libshlwapi" />
                    <Add library="libversion" />
                    <Add library="liboleacc" />
                    <Add library="libUxTheme" />
                    <Add directory="C:/wxWidgets-3.1.1/lib/gcc_dll" />
                </Linker>
            </Target>
        </Build>
        <Compiler>
            <Add option="-pipe" />
            <Add option="-mthreads" />
            <Add option="-D__GNUWIN32__" />
            <Add option="-D__WXMSW__" />
            <Add option="-DwxUSE_UNICODE" />
            <Add option="-Wall" />
            <Add directory="C:/wxWidgets-3.1.1/include" />
        </Compiler>
        <ResourceCompiler>
            <Add directory="C:/wxWidgets-3.1.1/include" />
        </ResourceCompiler>
        <Linker>
            <Add option="-mthreads" />
            <Add library="libkernel32.a" />
            <Add library="libuser32.a" />
            <Add library="libgdi32.a" />
            <Add library="libwinspool.a" />
            <Add library="libcomdlg32.a" />
            <Add library="libadvapi32.a" />
            <Add library="libshell32.a" />
            <Add library="libole32.a" />
            <Add library="liboleaut32.a" />
            <Add library="libuuid.a" />
            <Add library="libcomctl32.a" />
            <Add library="libwsock32.a" />
            <Add library="libodbc32.a" />
            <Add library="libshlwapi.a" />
            <Add library="libversion.a" />
        </Linker>
        <Unit filename="borrawx311App.cpp" />
        <Unit filename="borrawx311App.h" />
        <Unit filename="borrawx311Main.cpp" />
        <Unit filename="borrawx311Main.h" />
        <Unit filename="resource.rc">
            <Option compilerVar="WINDRES" />
        </Unit>
        <Unit filename="wxsmith/borrawx311frame.wxs" />
        <Extensions>
            <code_completion />
            <envvars />
            <debugger />
            <lib_finder disable_auto="1" />
            <wxsmith version="1">
                <gui name="wxWidgets" src="borrawx311App.cpp" main="borrawx311Frame" init_handlers="necessary" language="CPP" />
                <resources>
                    <wxFrame wxs="wxsmith/borrawx311frame.wxs" src="borrawx311Main.cpp" hdr="borrawx311Main.h" fwddecl="0" i18n="1" name="borrawx311Frame" language="CPP" />
                </resources>
            </wxsmith>
        </Extensions>
    </Project>
</CodeBlocks_project_file>



Hasta pronto.
JUAN GALAZ

Bibliografía:
https://www.youtube.com/watch?v=LZacAgSBWa0

martes, 17 de abril de 2018

Arduino - Receptor de sensores de temperatura comerciales 433MHz

Página principal

Arduino

Receptor de sensores de temperatura

comerciales 433MHz

xsetaseta@gmail.com

Había visto hace tiempo un artículo donde se exponía la posibilidad de escuchar los sensores de temperaturas comerciales de las estaciones meteorológicas. Yo tengo un par de estaciones de ese tipo, y como curiosidad descubrí que funcionaban en la misma frecuencia y eran compatibles. Para que funcionasen los dos sensores a la vez debía cambiar el canal en los sensores.



Por suerte las dos estaciones meteorológicas tenían el mismo tipo de sensor y eran compatibles.

Estos sensores funcionan en la frecuencia de 433.xxxMHz , si no es muy selectivo el receptor puede recibir señales en toda la banda.
Tengo dos tipos de receptores, el uno es mas sensible que otro, aunque un poco mas caro lo recomiendo.
En el mercado chino existen numerosos receptores, algunos funcionan a 351MHz, y otros están sintonizados mal.  En la parte de bibliografía pongo el enlace del que me ha funcionado bien (2€).


Recomiendo este por ser mas sensible.


Montado el circuito receptor y alimentado a 5V me puse a estudiar los datos recibidos.

Gráfica de datos recibidos.


Después un estudio interprete las señales de este modo, tuve suerte, acerté.


Estudiando los datos mandados y con bastante trabajo, pude determinar la estructura de los datos.

Los datos emitidos se repiten varias veces, de esta forma podemos asegurarnos que el valor es correcto, no se si tiene verificación vía CRCs.
He de reconocer que tuve suerte, no estaban codificados como en algunos emisores.
También he descubierto que los datos extras son el estado de la batería.


Circuito montado con su antena.


Detalle del circuito, he quitado componentes usados en el desarrollo.

Al usar la interrupción INT0 para decodificar la señal, he configurado el pin D2 como entrada y conectado la salida DATA del receptor al pin D2.

void setup(void)
{
  Serial.begin(9600);
  Serial.println("Int433");
  pinMode(2, INPUT);
  pinMode(IN_READ, INPUT);

  cli();                // Disable INT
  EIMSK |= (1 << INT0);  // Enable external interrupt INT0
  EICRA |= (1 << ISC01); // Trigger INT0   en bajada
  sei();
}


El programa en el arduino se encarga de interpretar la señales y mandar los datos vía serie.
Int433
Canal,2,Grados,202,Extra,15
Canal,2,Grados,202,Extra,15
Canal,2,Grados,202,Extra,15
Canal,2,Grados,202,Extra,15
Canal,2,Grados,202,Extra,15
Canal,2,Grados,202,Extra,15
Canal,2,Grados,202,Extra,15
Canal,2,Grados,202,Extra,15
Canal,1,Grados,216,Extra,18
Canal,1,Grados,216,Extra,2
Canal,1,Grados,216,Extra,2
Canal,1,Grados,216,Extra,2
Canal,1,Grados,104,Extra,1
Canal,1,Grados,216,Extra,2
Canal,1,Grados,216,Extra,2
Canal,1,Grados,216,Extra,2
Canal,1,Grados,216,Extra,2
Datos recibidos vía serie

Para hacer un poco mas vistoso la visión de los datos, realicé en Gambas3 (Visual Basic Linux) un programa.


Las gráficas de la señales están realizadas mediante Osciloscopio Hantek6022BL y PulseView bajo Linux (Debian8_32bits).

PROGRAMAS

Hasta pronto.
JUAN GALAZ

Bibliografía:

setacom.html
hantek.html
https://fetzerch.github.io/2014/11/15/reveng433/
https://es.aliexpress.com/item/1pair-2pcs-433mhz-rf-transmitter-and-receiver-kit-For-Wireless-Power-switch-socket-remote-control-LED/32311933574.html?spm=a2g0s.9042311.0.0.lWlrua

miércoles, 11 de abril de 2018

Arduino - Comunicación Serie por Software - Interrupciones

Página principal


Arduino
Comunicación Serie por Software

Interrupciones
xsetaseta@gmail.com

Debía realizar un análisis de unas señales que transmitían códigos. Para obtener los datos de estas señales debía decodificar los diferentes impulsos de estas señales. El chip decodificador debía ser un arduino, y como nunca había realizado este trabajo, debía experimentar un patron de señales conocidas, y la mas conocida era la comunicación serie.
El estándar serie  es bien conocido, su decodificación normalmente se hace vía hardware, aunque a baja velocidad también se puede decodificar vía Software. Esta es una práctica de decodificación mediante programa de una señal con el protocolo serie, (USART) universal synchronous and asynchronous receiver-transmitter.

Imagen de una señal serie.


Tiempo de la señal Start a una velocidad de 300bps.


Tiempo de la señal Stop a una velocidad de 300bps.

La señal representada corresponde a una señal serie de 8 bits y 1 bits de parada.

Para decodificar esta señal he utilizado dos métodos diferentes:
El primer método cheque continuamente un Pin del arduino, que debemos determinar en el Setup.
El segundo método solo se interrumpe la ejecución del programa si existe un cambio en el Pin2, el cual genera la interrupción 0.

Modo 1.
Creamos una interrupción que continuamente mira el estado del pin que se designa como entrada.
 
  SRetardoStop = SRetardo * 10;

  SRetardoMax = SRetardo * 14;
  // initialize Timer1
  cli();          // disable global interrupts
  TCCR1A = 0;     // set entire TCCR1A register to 0
  TCCR1B = 0;     // same for TCCR1B
  TCCR1B |= (1 << WGM12); // turn on CTC mode:
  TCCR1B |= (1 << CS10);  //sin prescaler
  OCR1A = Scontador;   //contador
  TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt:
  sei();          // enable global interrupts

Vemos como utilizamos el Timer1, le asignamos un valor al contador, cuando el contador llegue a cero produce una interrupción, carga de nuevo el valor del contador, y se ejecuta la rutina de la interrupción.
La rutina de la interrupción es donde se estudia la señal del pin y se llama:
ISR(TIMER1_COMPA_vect)
{
}

Gráfica del chequeo de señal y la toma de valores de la señal.


Modo 2.
Para este caso no existe ninguna temporización, el programa utiliza la interrupción externa Int0 que se encuentra en el Pin 2 del arduino.
El programa solo se interrumpe cuando detecta un cambio de señal en el Pin 2 del arduino.
bool SetupSerie2(unsigned int  baud)
{
  pinMode(2, INPUT);
  digitalWrite(2, HIGH); // Enable pull-up resistor
  cli();                 // Enable global interrupts
  EIMSK |= (1 << INT0);  // Enable external interrupt INT0
  EICRA |= (1 << ISC00); // Trigger INT0 on Change
  sei();
......

La rutina de la interrupción es donde se estudia los tiempos del cambio de señal del Pin 2 del arduino y se llama:
ISR(INT0_vect)
{

}


En los dos casos cuando se ha completado la lectura de un byte,  se pone la variable SDatoEstado = 1; .
En el bucle del programa principal que chequea continuamente el SDatoEstado = 1; , mediante la rutina  SerialAvailable() ,cuando detecta un carácter válido, se obtiene el byte  mediante la rutina SerialGet().
Para esta práctica no he querido crear un buffer que sería lo normal, pues si se entretiene mucho el programa principal pudiera sobrescribirse los datos.
En ambos casos a velocidades superiores a 4800 bps, me producían errores, se mezclaban las interrupciones, no he querido profundizar en su posible solución.

Para entender la interrupciones en el arduino, estuve buscando en internet un tutorial, encontrando este:
https://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/
en plan atrevido, realicé una traducción, espero que no sea muy mala. TRADUCCION

Las gráficas de la señales están realizadas mediante Osciloscopio Hantek6022BL y PulseView bajo Linux (Debian8_32bits).

PROGRAMAS

Hasta pronto.
JUAN GALAZ

Bibliografía:

https://aprendiendoarduino.wordpress.com/2016/11/13/interrupciones/
https://arduinodiy.wordpress.com/2012/02/28/timer-interrupts/
http://www.engblaze.com/we-interrupt-this-program-to-bring-you-a-tutorial-on-arduino-interrupts/