Mostrando entradas con la etiqueta avr. Mostrar todas las entradas
Mostrando entradas con la etiqueta avr. Mostrar todas las entradas

Bienvenido! - Welcome!




Blog News:

NEW              Maqueta de Control Didáctica (VirtualCamp Jul 2011)
NEW              Introducción al Timer 2
NEW              TVout= Arduino + TV
NEW              CAN BUS CON ARDUINO!!
 





Puedes encontrar algunos artículos sobre microcontroladores, y en concreto sobre Arduino y Atmel en general.
Nos enfocaremos en hardware libre y creación de sistemas low cost.

You can find some posts about Arduino and Atmel. 
We´ll focus in open-source hardware and the design of low cost products.





Añadido Twitter al blog!! Últimos comentarios en la barra lateral ó enlaza a:








































































































.

Timer 2: Introducción

.

 


El microcontrolador de las placas Arduino dispone de 3 módulos Contador/Timers (dos de 8 bits y uno de 16 bits). Se trata de hardware independiente al microprocesador que puede ejecutar tareas paralelas sin detener el flujo del programa. Algunas de éstas tareas son contador, medida precisa de tiempos, generador de ondas, .... Estos Timers son usados internamente por el core de Arduino para sus funciones internas, como pueden ser millis, delay, analogWrite,...

Aquí vamos a ver cómo trabajar con el Timer 2, el cual es de 8 Bits. El Timer 2 es usado internamente en el core Arduino para generar el PWM por los pines 3 y 11, por lo que no se podrá usar dicha función en conjunto con el código propuesto más adelante.

Para empezar vamos a ver el funcionamiento de dicho contador en modo Normal (Normal mode).
Se trata del modo más sencillo, en el cual el el contador se incrementa a cada pulso de reloj  hasta llegar a su máximo (8 bits=255) y se reinicia de nuevo desde 0. Es decir 0,1,2,...255 -> 0,1,...,255 -> 0,1,...
En el momento que el contador vuelve a 0 (registro TCNT2), se activa el  flag de  "overflow" (TOV2).  Se puede configurar una interrupción (overflow del timer) cuando ésto ocurre. Dicha interrupcion se encarga de resetear dicho el flag.

Notas:
El flag es un bit que cambia su estado, como si fuera una "alarma" para avisar al programador que un evento ha ocurrido. Dicho bit (TOV2) de overflow se encuentra en el registro TIFR2.
Una interrupción es una señal recibida por el microcontrolador, que interrumpe la ejecución del código actual y cambia a la rutina que atiende dicha interrupción.

Normalmente el cristal usado en la mayoría de las placas Arduino es de 16 MHz (cuidado que algunas como LilyPad van a 8Mhz), lo que significa que la resolución máxima es de 1/16.000.000= 62.5 ns. Es decir, que el contador alimentado por la frecuencia reloj del micro, incrementa en uno su valor cada 62.5 ns, y tendría su overflow cada 256*1/16000000=0.016ms.

Se puede observar que es un tiempo muy pequeño. Para poder tener más rangos, el timer dispone de PRESCALER. Ésto es simplemente un divisor de la frecuencia del reloj que le esta alimentando al timer. Los PRESCALER disponibles son 1,8,32,64,128,256 y 1024.


El lenguaje Arduino no dispone de funciones propias para configurar los timer. Los registros internos del microcontrolador para configurar el Timer2 son TCCR2A, TCCR2B, TNT2, OCR2A,OCR2B, TIMSK2,TIFR2,ASSR y GTCCR. Lo mejor para ampliar conocimientos acerca de todas las posibilidades que existen es el datasheet del propio microcontrolador.

En el registro TCCT2B se disponen los bits CS22,CS21 y CS20 (bit 2,1 y 0). Dichos bits son los encargados de configurar el PRESCALER del timer.
Veamos las combinaciones de CS22 - CS21 - CS20 respectivamente.
  • 0 - 0 - 0 => No Clock
  • 0 - 0 - 1 => No Prescaling  [0.016 ms]
  • 0 - 1 - 0 => Prescaler=8  [0.128 ms]
  • 0 - 1 - 1 => Prescaler=32  [0.512 ms]
  • 1 - 0 - 0  => Prescaler=64  [1.024 ms]
  • 1 - 0 - 1  => Prescaler=128  [2.048 ms]
  • 1 - 1 - 0  => Prescaler=256  [4.096 ms]
  • 1 - 1 - 1  => Prescaler=1024  [16.384 ms]

He preparado un programa, el cual conmuta el Pin 13 de Arduino cada vez que se produce la interrupción de Overflow. He recogido la salida de dicho pin con un Analizador Lógico. Lo que se observa, es una señal cuadrada, es decir el pin esta conmutando de estado ALTO="1" a estado BAJO="0" según la configuración de los bits CS22-CS21-CS20.


(click para agrandar)

Para lograr el máximo rendimiento del código, he usado control directo de los registros del microcontrolador para conmutar el pin 13 y así no meter "retrasos" debido a la ejecución de código. Para entendernos, la instrucción digitalWrite es "lenta".
Los tres registros internos usados por el microcontrolador para el control de los puertos son:
  • DDRx   => Configura los pines del puerto como entrada ("0") o salida ("1").
  • PORTx => Controla si el estado ALTO y BAJO de los pines de dicho puerto.
  • PINx    => Estado de los pines.
siendo x alguno de los tres puertos disponibles en el micro: B,C ó D.
Para saber la equivalencia entre los pines de Arduino con los del micro, visitar: http://www.arduino.cc/en/Reference/PortManipulation
Cómo se puede ver, el pin 13 de Arduino equivale al PB5 (puerto B, bit 5).

Truco => Si escribes sobre el registro PINx cuando esta declarado cómo salida, el pin conmutará.


_BV() usado en el código es un macro definido en avr/sfr_defs.h, el cual se añade indirectamente al incluir avr/io.h.  Para hacerlo fácil, lo puedes usar sin añadir dichos includes, ya que esta incluido en el core de Arduino.
Dicho macro esta definido como: #define _BV( bit ) ( 1<<(bit) )
Lo que hace es poner a "1" el bit definido dentro del paréntesis de la función.

No he usado dicho macro para la configuración de los registros del Timer 2 dentro del setup() para intentar ser más claro y entenderlo mejor mientras se esta leyendo el datasheet del micro.

Queda de ver una cosa.... ¿Cómo configuro las interrupción de overflow del timer 2?
Para "recoger" las interrupciones generadas por el microcontrolador, nuestro código debe disponer de la siguiente estructura:


#include <avr/interrupt.h>

ISR(TIMER2_OVF_vect)
{
// código a ejecutar cuando se activa la interrupción
}

ISR(int) define la función que se ejecutará cuando se active la interrupción int, en este caso concreto, la interrupción de overflow del Timer 2 (TIMER2_OV_vect). Existen más interrupciones cómo por ejemplo: INT0_vect, USART_RX_vect, ...
Para ampliar información, visitar http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html .




Código del sketch:

#include <avr/interrupt.h>

//-----------------------------------------------------
// Rutina de Interrupcion [TIMER2_OVF_vect es la rutina que se ejecuta cuando el Timer2 ->Overflow]
// Arduino tiene un cristal de 16 Mhz
// Por lo que tenemos una interrupcion cada => 1/ ((16000000 / PRESCALER) / 256)
ISR(TIMER2_OVF_vect) 
{
  PINB |=_BV(PB5);
}



void setup() 
{
  DDRB=_BV(PB5);   // Pin 13 Arduino equivale a PB5

  // NORMAL MODE
  TCCR2A = (1<<COM2A1) | (0<<COM2A0) | (0<<COM2B1)| (0<<COM2B0) | (0<<3) | (0<<2) | (0<<WGM21) | (0<<WGM20);  

  TCCR2B = (0<<FOC2A) | (0<<FOC2B) | (0<<5) | (0<<4) | (0<<WGM22) | (1<<CS22) | (0<<CS21) | (0<<CS20); 
  
  // Activo Timer2 Overflow Interrupt
  TIMSK2 =(0<<7) | (0<<6) | (0<<5) | (0<<4) | (0<<3) | (0<<OCIE2B) | (0<<OCIE2A) | (1<<TOIE2);  
  
  // Oscilador interno
  ASSR = (0<<7) | (0<<EXCLK) | (0<<AS2) | (0<<TCN2UB) | (0<<OCR2AUB) | (0<<OCR2BUB) | (0<<TCR2AUB) | (0<<TCR2BUB) ;
  
  //Activo interrupciones globales.
  sei();

}


void loop() 
{
  

}







Veámos ahora un ejemplo de cómo usar el Timer2 para controlar diferentes tareas. En este ejemplo, conmutaremos el estado de dos pines (pin 13 y pin 1 de Arduino) a dos frecuencias diferentes. Es decir, haremos que el led conectado al pin 13 parpadee cada 10 ms y que el pin 1 cada 25 ms.
Para ello configuramos nuestro Timer2 para que active la interrupción cada 1ms. Dentro de la interrupción aumentará una variable llamada ticks. Dicha variable será la base para controlar la ejecución del resto de mi programa.
Por lo que el flujo de mi programa vendrá controlado basado en unidades de 1ms (variable ticks). Esto es la base de cómo hacer "tareas multiples" con un microcontrolador.



(click para agrandar)



Código del sketch 2:

#include <avr/interrupt.h>

//DECLARACION DE VARIABLES GLOBALES
volatile unsigned long ticks;
unsigned long Tarea1;
unsigned long Tarea2;

//-----------------------------------------------------
// Rutina de Interrupcion [TIMER2_OVF_vect es la rutina que se ejecuta cuando el Timer2 ->Overflow]
// Arduino tiene un cristal de 16 Mhz
// Por lo que tenemos una interrupcion cada => 1/ ((16000000 / PRESCALER) / 256)
ISR(TIMER2_OVF_vect) 
{
  ticks++;
}



void setup() 
{
  DDRB=_BV(PB5);   // Pin 13 Arduino equivale a PB5
  DDRD=_BV(PD1);   // Pin 2 Arduino equivale a PD1

  // NORMAL MODE
  TCCR2A = (1<<COM2A1) | (0<<COM2A0) | (0<<COM2B1)| (0<<COM2B0) | (0<<3) | (0<<2) | (0<<WGM21) | (0<<WGM20);  
 
  TCCR2B = (0<<FOC2A) | (0<<FOC2B) | (0<<5) | (0<<4) | (0<<WGM22) | (1<<CS22) | (0<<CS21) | (0<<CS20); 
  //Configurado a 1.024 ms
  
  // Activo Timer2 Overflow Interrupt
  TIMSK2 =(0<<7) | (0<<6) | (0<<5) | (0<<4) | (0<<3) | (0<<OCIE2B) | (0<<OCIE2A) | (1<<TOIE2);  
  
  
  // Oscilador interno
  ASSR = (0<<7) | (0<<EXCLK) | (0<<AS2) | (0<<TCN2UB) | (0<<OCR2AUB) | (0<<OCR2BUB) | (0<<TCR2AUB) | (0<<TCR2BUB) ;

  // Inicializo variables
  Tarea1=10;
  Tarea2=25;  
  
  //Activo interrupciones globales.
  sei();


}


void loop() 
{
   
  
  if (ticks>=Tarea1)
  {
    PINB |=_BV(PB5);   //Conmuto pin 13
    Tarea1+=10;        //Configuro para que se ejecute de nuevo la Tarea1 dentro de 10 ticks
  }
  
  if (ticks>=Tarea2)
  {
    PIND |=_BV(PD1);  //Conmuto pin 2
    Tarea2+=25;       //Configuro para que se ejecute de nuevo la Tarea2 dentro de 25 ticks
  }
  
  
}



Espero que ésto ayude y no dudes en contactar conmigo si encuentras algun error.




Links recomendados:
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=50106   [Newbie's Guide to AVR Timers]
http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM ó http://arduino.cc/es/Tutorial/SecretsOfArduinoPWM [castellano]
http://www.nongnu.org/avr-libc       [Libreria de C para AVR usada por el core de Arduino]
http://www.tte-systems.com/books/pttes [ Libro Patterns for Time-Triggered Embedded Systems ]







.

Libreria TVout

.

 

.
Se trata de una librería para crear video compuesto con Arduino. Su utilización es muy sencilla y directa.


Tan sólo necesitas un par de diodos y un par de resistencias!!!!



Para un Diecimila (ATMega328P) los pines son:
  • Sync    = pin 9,  Arduino
  • Video  = pin 7,  Arduino
  • GND   = masa, Arduino

Veámos un ejemplo sencillo con dos simples pantallas. En la primera se muestra texto con la temperatura recogida con una NTC y adquirida por Arduino en su entrada 5. Después de un delay, se muestra un bitmap (ver el vídeo del resultado al final de esta entrada).

He utilizado la última versión beta disponible en el momento de escribir esta entrada. Existe una función para mostrar imagenes almacenadas en memoria flash. Para crear imagenes, puedes utilizar el software Image2Code (http://sourceforge.net/projects/image2code/files/).
El software permite abrir directamente una imagen y convertirla a un array en C:


Una vez hecho click sobre Convert, se te abrira el editor de textos con el código de la foto. Usa la función
reemplazar para eliminar "{" y "}".


Ahora ya tienes tu imagen preparada para grabarla en tu Arduino. Lo único que falta es crear un array de char donde guardarás dicha imagen. Para ello hay que crear dos archivos, uno *.h donde estará la declaración de la variable y uno *.cpp donde se guardará el array obtenido con Image2Code.
En mi ejemplo, guardaré la imagen creada en un array llamado ok[] .

Empecemos con el *.h, en mi caso le he llamado bitmap.h.


Para el *.cpp, en mi caso bitmap.cpp. (en la tercera línea, se pone el tamaño de la imagen (74x96).
#include "bitmap.h"
PROGMEM const unsigned char ok[] = {
74,96,
 //pegar aquí el código obtenido con Image2Code
};







Librerías y código:


Código del sketch:

#include <TVout.h>
#include <fontALL.h>
#include "bitmap.h"

TVout TV;
int final=8;
int mydelay=10;
double temperatura=0.0;

void setup()  

{
  TV.start_render(PAL);
  TV.clear_screen();

}

void loop()
{
  
  TV.select_font(font4x6);
  TV.print_str(2,0*8,"Rumbeando con Arduino By IgOrR");
  
  TV.select_font(font8x8);

  temperatura=analogRead(5)*5.0/1023.0;
  TV.set_cursor(2,5*8);
  //Muestro voltage
  TV.print("Analog 5= ");
  TV.print(temperatura,2);
  TV.print("V");
  //Muestro grados
  TV.set_cursor(2,6*8);
  TV.print("Temp    = ");
  temperatura=-27.025*temperatura + 112.95;
  TV.print(temperatura,2);
    
  for (int i=0;i<3;i++)

  {
    for (int i=0;i<final;i++)
    {
      TV.print_str(0,9*8,"                                        ");
      TV.print_str(i*6,9*8,"Toma ya!");
      TV.delay_frame(mydelay);
    }

    for (int i=final;i>0;i--)
    {
      TV.print_str(0,9*8,"                                        ");
      TV.print_str(i*6,9*8,"Toma ya!");
      TV.delay_frame(mydelay);
    }  
  }

  

  TV.clear_screen();
  TV.bitmap(30,0,ok,0,0,0);
  TV.delay_frame(300);
  TV.clear_screen();


}

 




 










Pongo unas fotos,para que se aprecie mejor la calidad:





Links:









.



.

LINKDUINO: DD-WRT + OPTWARE

.


Para poder realizar este tutorial es necesario que dispongas de alguno de estos recursos:
  • Router con gran memoria flash libre
  • SD/MMC mod.
  • Router con USB. 
(Ampliar información visitando el siguiente link.)

Aqui vamos a explicar cómo hacerlo usando el SD/MMC mod. QUIERO DEJAR CLARO QUE TODA LA INFORMACIÓN ESTÁ EXTRAIDA DEL BLOG MATANDO EL TIEMPO (gracias Edu por tan buen documento).

Primer paso: Instalar SD

Puedes encontrar toda la información en: http://nuwiki.openwrt.org/oldwiki/OpenWrtDocs/Customizing/Hardware/MMC?highlight=%28mmc%29


Video explicativo de Lampi:




Y unas fotos (son las mejores que he encontrado. Extraidas de aquí):





 


Segundo paso: Instalar Optware

Como se detallada en Matando el Tiempo:

1) Firmware: DD-WRT v24 sp2 (10/10/09) con mod SD, una tarjeta reconocida (las modernas, por ejemplo HC, no las reconoce) y lista para usar.
Me ha reconocido una de 1 Gb (velocidad x66).
 





2) Montar la partición en la SD

mkdir /mmc/jffs
mount --bind /mmc/jffs /jffs


3) Instalar Optware

mkdir /jffs/opt
mount -o bind /jffs/opt /opt
mkdir /jffs/tmp
cd /jffs/tmp
wget http://www.wlan-sat.com/boleo/optware/optware-install-ddwrt.sh
./optware-install-ddwrt.sh


Adjunto el código de dicho script de instalación:

#!/bin/sh
# Optware pre-installation script, Leon Kos 2006, 2008
# added -verbose_wget to some lines, MrAlvin 2009

REPOSITORY=http://ipkg.nslu2-linux.org/feeds/optware/ddwrt/cross/stable
TMP=/tmp

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/opt/bin:/opt/sbin
unset LD_PRELOAD

unset LD_LIBRARY_PATH

_check_config()
{
    echo "Checking system config ..."
    GATEWAY=$(netstat -rn |
 sed -n 's/^0.0.0.0[ \t]\{1,\}\([0-9.]\{8,\}\).*/\1/p' )

    if [ -n "${GATEWAY}" ]; then
 echo "Using ${GATEWAY} as default gateway."
    else
 echo "Error: No default gateway set!"

 exit 2
    fi
    if [ -s /etc/resolv.conf ]; then
 echo "Using the following nameserver(s):"
 if grep nameserver /etc/resolv.conf ; then
  GATEWAY_SUBNET=$(echo "${GATEWAY}" |

  sed 's/\.[0-9]\{1,3\}\.[0-9]\{1,3\}$//')
     if [ "${GATEWAY_SUBNET}" = "192.168" ]; then
  if grep -q ${GATEWAY} /etc/resolv.conf ; then
      echo "Gateway ${GATEWAY} is also nameserver."

  else
      echo "Warning: local nameserver is different than gateway!"
      echo "Check config or enter:"
      if test -L /etc/resolv.conf ; then
   echo "  sed -i s/192.168.*/${GATEWAY}/ /tmp/resolv.conf"

      else
   echo "  sed -i s/192.168.*/${GATEWAY}/ /etc/resolv.conf"
      fi
      echo "and try again - or wait to see if your download continues anyway."

  fi
     fi
 else
     echo "Error: No nameserver specified in /etc/resolv.conf"
     exit 5
 fi
    else
 echo "Error: Empty or nonexistent /etc/resolv.conf"

 exit 3
    fi

    if mount | grep -q /opt ; then
 [ -d /opt/etc ] && echo "Warning: /opt partition not empty!"

    else
 echo "Error: /opt partition not mounted."
 echo "for running Optware on JFFS (not recommended), Enter"
 echo "    mkdir /jffs/opt"

 echo "    mount -o bind /jffs/opt /opt"
 echo "to correct this."
 exit 4
    fi
}

_install_package()
{
    PACKAGE=$1
    echo "Installing package ${PACKAGE} ..."
 echo "   Some newer versions of DD-WRT does not show download progress bar,"
 echo "   so just be patient - or check STATUS -> BANDWIDTH tab for download"

 echo "   activity in your routers Web-GUI, and then still wait a minute or two."
    wget -O ${TMP}/${PACKAGE} ${REPOSITORY}/${PACKAGE}

    cd  ${TMP}
    tar xzf ${TMP}/${PACKAGE}
    tar xzf ${TMP}/control.tar.gz
    cd /

    if [ -f ${TMP}/preinst ] ; then
 sh ${TMP}/preinst
 rm -f ${TMP}/preints
    fi
    tar xzf ${TMP}/data.tar.gz
    if [ -f ${TMP}/postinst ] ; then
 sh ${TMP}/postinst
 rm -f ${TMP}/postinst
    fi
    rm -f ${TMP}/data.tar.gz
    rm -f ${TMP}/control.tar.gz
    rm -f ${TMP}/control
    rm -f ${TMP}/${PACKAGE}

}

_check_config
_install_package uclibc-opt_0.9.28-13_mipsel.ipk
_install_package ipkg-opt_0.99.163-10_mipsel.ipk
/opt/sbin/ldconfig
/opt/bin/ipkg -verbose_wget update

/opt/bin/ipkg -force-reinstall -verbose_wget install uclibc-opt
/opt/bin/ipkg -force-reinstall -verbose_wget install ipkg-opt

 




¡ Ya podemos instalar paquetes de Optware en nuestro router! Puedes ver una lista resumen aquí y directamente los paquetes aquí.

Para ello, ahora dispones en /opt/bin de la utilidad ipkg-opt para poder instalar paquetes Optware.

4) Tienes que asegurarte que cada vez que se inice el router, se ejecuten las ordenes:

mount --bind /mmc/jffs /jffs
mount -o bind /jffs/opt /opt


Gracias a estos dos comandos, /jffs y /opt apuntan a directorios de la MMC.
Para ello, en el menu ADMINISTRATION / COMANDS, puedes grabar un script con las ordenes a ejecutar (SAVE STARTUP).


Nota: Sólo he detallado lo mínimo para poder empezar a instalar paquetes. Se puede necesitar ampliar los comandos en el script de inicio, si se desea usar otros servicios, como por ejemplo servidor web con php u otros.

Si quieres probar el ejemplo de CONTROLAR LCD A TRAVÉS DE WEB EMBEBIDA, lo he adaptado a PHP (necesitas instalarte los paquetes php y php-thttpd):


Dispones de 3 archivos:
  • form_lcd.html => Principal. Contiene el formulario a enviar.
  • lcd.jpg => Foto que se muestra en la página principal.
  • script.php => Recoge los datos enviados por POST y los envia por puerto serie.



Ahora puedes dejar el servidor que viene con DD-WRT para servir las páginas de configuración del router escuchando en el puerto 80 y añadir nuevo/s servidor/es con mayor capacidad para tus páginas personales. (Por ejemplo, php-thttpd por el puerto 8080). ¡Puedes usar PHP 5!

A continuación, pongo las fotos que he realizado del proceso:




 







Con esta mod al router, ya sólo queda en tu imaginación las aplicaciones que puedes realizar. Ya no perderás nada cuando tu router se reinicie. Repasa los paquetes Optware que puedes descargar, y seguro que se te van ocurriendo ideas.




Notas adicionales:
Tomato dispone de una versión con drivers para manejar SDHC, la he probado con una tarjeta de 4 Gb y ha funcionado perfectamente. Tengo que ver si se pueden usar los paquetes Optware con dicho firmware, ya que el router parece ir más descargado con dicho firmware.
Link: TOMATO firmware with SDHC mod







.

LINKDUINO: Controlar LCD desde web embebida

.


Siguiendo cómo realizar páginas embebidas, las cuales interactuen con Arduino, veremos un ejemplo de cómo usar formularios. (Se debe leer primero el siguiente post)

Nuestro ejemplo se trata del envio de texto a un display lcd 4x20, a través de internet/local via página web embebida en el router.

Para ello, crearemos una página web que contenga un formulario, al cual se enviará la información de 4 controles de tipo INPUT a un script, que sacará dicha información por el puerto serie hacia Arduino.




El código html de dicha página es el siguiente:

form_lcd.html

<html>
<head>

</head>
<div style="text-align:left;">
<img src="/user/lcd.jpg">

</div>
<div style="color:blue;text-align:left;">
<span style="font-size:x-large;">
<p>DATOS A ENVIAR: </p>

<p> </p>
</span></div>
<form action="/user/cgi-bin/lcd.sh" method="POST">
 LCD line 1:

 <input type= "text" name= "L0" size=25 maxlength=20 ><p>
 LCD line 2:
 <input type= "text" name= "L1" size=25 maxlength=20><p>

 LCD line 3:
 <input type= "text" name= "L2" size=25 maxlength=20><p>
 LCD line 4:

 <input type= "text" name= "L3" size=25 maxlength=20><p>
 </br>
 </br>
 <INPUT type="submit" value="ENVIAR">

</form>



</body>
</html>

 




Ahora veamos que hace nuestro script:
lcd.sh

#!/bin/sh
read QUERY_STRING
n_campos=$(echo $QUERY_STRING|awk 'BEGIN {FS="&"} {print NF}')
#------------------------------------------------------------------
echo "<HTML>"

echo "<HEAD>"
echo "Datos POST: "
echo $QUERY_STRING
echo "<br/>"
echo "<br/>"
echo "Has recibido:"
echo $n_campos
echo " campos"

echo "<br/>"
echo "<br/>"
i=1
while [ $i -le $n_campos ]
do
 data=$(echo $QUERY_STRING|cut -f$i -d '&'|sed s/'+'/' '/g)

 echo $data
 echo $data|sed s/'='//g > /dev/cua/1
 echo "<br/>"
 i=`expr $i + 1`
done
# -----FIN ------
echo "<div style='color:blue;text-align:center;'>"

echo "<p><span style='font-size:50px;'>SE HAN ENVIADO LOS DATOS</span></p>"
echo "</div>"
echo "<META HTTP-EQUIV=Refresh CONTENT=3;URL=/user/form_lcd.html>"

echo "</HEAD><BODY>"
echo "</BODY></HTML>"
 


En el script, recojo los datos recibidos por método POST (variable $QUERY_STRING). Para saber cuantos campos recibo, hago un awk separando campos por el caracter delimitador '&'.
La variable $QUERY_STRING dispone los datos separados por '&' y los espacios con el carácter '+'.
La variable NF es interna de awk, y son el número de campos de entradas (en nuestro caso, se ha especificado que el separador de campos es '&').
Con la ayuda de cut y sed, se ha modificado la cadena recibida para obtener formato deseado.

Un buen tutorial  acerca "Linux Shell Scripting" :

Recordad que dicho script tiene que tener permisos de ejecución (chmod +x lcd.sh)

Ahora nos toca el código de Arduino:

// Linkduino: LCD controlado por serie
// By Igor Real
// 03-Enero-2010
// http://real2electronics.blogspot.com/


#include <LiquidCrystal.h>


LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
int byte_received;

void setup() {

  lcd.begin(20, 4);
  delay(100);
  Serial.begin(9600);
  Serial.println("Empezamos...");



}

void loop() {

  while (Serial.available()>0){
    byte_received=Serial.read();

    if (byte_received=='L'){

      Serial.println("Dentro de l");
      byte_received=Serial.read();
      switch (byte_received){
        case '0':
        {
          byte cont1=0;
          byte data[20];
          while (Serial.available()>0){

            byte_received=Serial.read();  
            if ( (byte_received>31) &&(byte_received<127) ){
              data[cont1]=byte_received;
              cont1=cont1+1;
              delay(1);
              if (cont1==20)  break;
            }

          }  
          lcd.setCursor(0,0);
          for (int i=0;i<cont1;i++)    lcd.print(data[i]);
          for (int i=cont1;i<20;i++)   lcd.print(" ");
          break;
        }        
        case '1':

        {
          byte cont1=0;
          byte data[20];
          while (Serial.available()>0){
            byte_received=Serial.read();      
            if ( (byte_received>31) &&(byte_received<127) ){

              data[cont1]=byte_received;
              cont1=cont1+1;
              delay(1);
              if (cont1==20)  break;
            }
          }  
          lcd.setCursor(0,1);
          for (int i=0;i<cont1;i++)    lcd.print(data[i]);
          for (int i=cont1;i<20;i++)   lcd.print(" ");
          break;
        }      
        case '2':

        {
          byte cont1=0;
          byte data[20];
          while (Serial.available()>0){
            byte_received=Serial.read();      
            if ( (byte_received>31) &&(byte_received<127) ){

              data[cont1]=byte_received;
              cont1=cont1+1;
              delay(1);
              if (cont1==20)  break;
            }
          }  
          lcd.setCursor(0,2);
          for (int i=0;i<cont1;i++)    lcd.print(data[i]);
          for (int i=cont1;i<20;i++)   lcd.print(" ");
          break;
        }

        case '3':
        {
          byte cont1=0;
          byte data[20];
          while (Serial.available()>0){
            byte_received=Serial.read();      
            if ( (byte_received>31) &&(byte_received<127) ){

              data[cont1]=byte_received;
              cont1=cont1+1;
              delay(1);
              if (cont1==20)  break;
            }
          }  
          lcd.setCursor(0,3);
          for (int i=0;i<cont1;i++)    lcd.print(data[i]);
          for (int i=cont1;i<20;i++)   lcd.print(" ");
          break;
        }            
      }

    }
  }
}


 



El programa es sencillo,utiliza la libreria LiquidCrsytal para el control del lcd basado en HD44780 y se debe recibir las siguientes "tramas" para escribir en cada línea:
L0lo_que_quiero_escribir_en_la_primera_linea
L1lo_que_quiero_escribir_en_la_segunda_linea
L2lo_que_quiero_escribir_en_la_tercera_linea
L3lo_que_quiero_escribir_en_la_cuarta_linea

El conexionado de mi LCD (comprado en Sure Electronics por ebay) ha sido:
  • pin 1 Vss     => Unido a masa
  • pin 2 Vdd    => Unido a +5 voltios
  • pin 3 Vo      => Poti de 10 Kohm (los otros dos extremos del poti a +5V y GND respectivamente)
  • pin 4 RS      => Unido a pin 8 Arduino
  • pin 5 R/W   => Unido a masa (no uso la opción de crear carácter)
  • pin 6  E       => Unido a pin 9 Arduino
  • pin 7   DB0 => No conectado (control 4 bits)
  • pin 8   DB1 => No conectado (control 4 bits)
  • pin 9   DB2 => No conectado (control 4 bits)
  • pin 10 DB3 => No conectado (control 4 bits) 
  • pin 11 DB4 => Unido a pin 10 Arduino
  • pin 12 DB5 => Unido a pin 11 Arduino
  • pin 13 DB6 => Unido a pin 12 Arduino
  • pin 14 DB7 => Unido a pin 13 Arduino
  • pin 15 A      => Unido +5V a través de R=120 ohm
  • pin 16 K      => Unido GND




Lo mejor es ver un video de funcionamiento:









Con este ejemplo, se ha visto cómo funcionan los formularios y cómo tratar los datos recibidos mediante POST al script para su posterior tratamiento. En html, los formularios disponen de diversos tipos de controles: text, radio, textarea, select , ...  En este ejemplo, para no introducir demasiados conceptos, se han usado los controles de tipo texto, pero el funcionamiento es similar para el resto.
Gracias al programa de Arduino, ahora es sencillo pasar al display información de Twitter, páginas web,...








 












  

LINKDUINO: SOFTWARE PARA TELEMETRIA

.



Veamos una nueva aplicación, desarrollada en Real2Electronics, para la adquisición de datos en "tiempo real" creada para la plataforma LINKDUINO. Gracias a este software, el usuario dispone de una herramienta sencilla y básica para la adquisición y visualización de datos via serie ó ethernet, pudiendo usar conectividad WIFI para disponer de TELEMETRÍA.
Nunca fueron tan fáciles y baratas tus pruebas "Hardware-in-the-loop" gracias a LINKDUINO.


Se han utilizado los siguientes controles para la realización de esta aplicación:



Veamos una captura de pantalla para ver el aspecto final de la aplicación:




Gracias a éste programa podremos:

  • Salvar datos a CSV (para poder exportar datos a Excel, Matlab, ...)
  • Salvar gráfico como *.jpg, *.gif, ...
  • Copiar
  • Imprimir
  • Ver valores de los puntos
  • Zoom
  • Moverse por la gráfica 
  • Autoescala según se reciben datos




Por la parte Arduino, se debe enviar la información al puerto serie de la siguiente manera:
EValorX;ValorYF

siendo:


  • E: Caracter E (empiece) char(0x45)
  • Valor X del punto enviado. (float i.e. 3,5)
  • ; (Punto y coma) Usado como delimitador entre X e Y. char(0x3B)
  • Valor Y del punto enviado. (float i.e 4509,334)
  • F: Caracter F (fin) char(0x46)

Ejemplos de tramas validas.


E45,67;32,67F
E65.56;89009.56F
...


Tanto '.' como ',' son admitidos como carácter de delimitador decimal.


Quick Start Guide
1) Descargar aplicación 
2) Descargar e instalar .NET Framework 3.5. (normalmente ya lo tendrás instalado).
3) Descomprimir el fichero .rar donde quieras que resida. Ej. C:\Real2Electronics\LINKDUINO 
4) Ejecuta LINKDUINO INTERFACE
5) Elegir método de adquisición de la información mediante las pestañas del tabControl: 
     -Serial Port Config: Te permitirá visualizar la configuración existente del puerto serie, además de comenzar la comunicación, cerrarla y limpiar el buffer de los datos recibidos hasta el momento.
      Si se desea configurar los parámetros del puerto serie, vaya al menú superior y haga click sobre Config Serial Port. Esto abrirá una nueva ventana de configuración.

     -TCP/IP: Te permite configurar fácilmente la direccion IP del servidor Telnet (en nuestro caso el router Linksys, ej. 192.168.0.1), el nombre de usuario, contraseña y puerto. Además proporciona el control de conexión/desconexión y limpieza del buffer.
6) Una vez elegido el método de conexión, deberemos de pulsar Connect/Open Port, y automáticamente, la aplicación comenzará a plottear sobre el gráfico los datos adquiridos.(Cuando se realiza la conexión mediante Telnet, ésta tarda unos segundos en estar activa)

Veamos ahora un programa de ejemplo para el Arduino:

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  static float i = 0;
  static float result =0;
  result = analogRead(0);
  result = (result * 100.0) / 1023.0;
  Serial.print("E");
  Serial.print(i);
  Serial.print(";");
  Serial.print(result);
  Serial.println("F");
  i = i + 1;

}
 

Este programa simplemente lee el valor de la entrada ADC0 y nos envía mediante serie la trama:
EindiceMuestra;ValorMuestraF 
siendo ValorMuestra, el valor en tanto por cien. Si quieres enviar tiempo, recuerda la función millis de Arduino.


Veamos un video de ejemplo:























¿Necesitas un software a medida para tu aplicación? Ponte en contacto.





Aritz R












.

LINKDUINO: Embedded Web Server

.



Vamos a ver cómo aprovecharnos del pequeño httpd server que trae el router para nuestras propias páginas web. (Este server es el utilizado para alojar las páginas de configuración del router).

Las rutas para guardar las páginas web dentro de nuestro router són:
  • Estáticas       => /tmp/www/
  • Dinámicas     => /tmp/www/cgi-bin/
(Recordad que el script debe tener los permisos adecuados chmod +x /tmp/www/cgi-bin/yourscript.sh)
PARA PODER USAR CGI SCRIPTS, DEBES TENER UNA VERSIÓN DE DD-WRT ANTERIOR A DD-WRT V24 pre SP2 (svn 12533+), YA QUE HA SIDO INHABILITADO POR MOTIVO DE FALLO DE VULNERABILIDAD. TEN CUIDADO SI VAS A DAR CONECTIVIDAD AL EXTERIOR.

He subido las versiones de firmware que he utilizado:
Recuerda que si no tienes una versión DD-WRT en el router, primero se debe enviar el firmware de la versión mini y posteriormente cualquiera de las versiones mayores.



Linksys dispone de la siguiente utilidad soft para flashear el equipo LINKSYS TFTP



Todas las páginas alojadas en /tmp/ se encuentrar en la SDRAM , por lo que se perderán ante un reboot ó perdida de corriente del router. Para tenerlo de forma permanente, tendrás que tener el mod de SD ó tener un router con USB.


El CGI (Common Gateway Interface) define una manera para que un servidor web pueda delegar la generación de páginas web a una aplicación de consola. Es el método más simple de disponer contenido dinámico en un sitio web. Es decir, si ingresamos la URL http://ip_router/user/cgi-bin/test.sh, el servidor de nuestro router intentará ejecutar el archivo /tmp/www/cgi-bin/test.sh y retornará la salida de dicho script.

Veamos un ejemplo sencillo que muestra Hola Mundo!! y la fecha (obtenida del router). Creamos nuesto script en /tmp/www/cgi-bin/test.sh

#!/bin/sh
echo "<html><head><title>Test CGI"
echo "</title></head><body>"
echo "<h1>Hola Mundo</h1>"
echo "Hoy es $(date)"
echo "</body></html>"

Otorgamos permiso de ejecución  /tmp/www/cgi-bin # chmod +x test.sh
Abrimos nuestro Navegador http://ip_router/user/cgi-bin/test.sh

(Lo más rápido y sencillo es trabajar con WinSCP)






Ahora, veamos el ejemplo que siempre ponemos de encender/apagar un led, ya visto anteriormente aqui.
1) Crearemos una página web (html)


Código

<html>
<head>

</head>
<body link=red vlink=red alink=red>
<div style="text-align:center;">
<img src="/user/logo.jpg">

</div>
<br/>

<div style="text-align:center;">
<span style="font-size:x-large;">
<a href="/user/cgi-bin/led_on.sh">LED ON</a>

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="/user/cgi-bin/led_off.sh">LED OFF</a>

</span>
</div>
<br/><br/><br/><br/>
<div style="color:blue;text-align:center;">
<span style="font-size:x-large;">
http://real2electronics.blogspot.com

</span></div>
</body>
</html>

Contiene una foto del logo y un par de links que apuntan a los scripts led_on.sh y led_off.sh


2) Crear el script: led_on.sh
#!/bin/sh
echo "S1F" > /dev/cua/1
echo "<HTML>"
echo "<HEAD>"
echo "<META HTTP-EQUIV=Refresh CONTENT=0;URL=/user/control.html>"
echo "</HEAD><BODY>"
echo "</BODY></HTML>"

El script envia la orden de encender por el puerto serie y redirecciona a la página principal (control.html).

3) Crear el script: led_off.sh
#!/bin/sh
echo "S0F" > /dev/cua/1
echo "<HTML>"
echo "<HEAD>"
echo "<META HTTP-EQUIV=Refresh CONTENT=0;URL=/user/control.html>"
echo "</HEAD><BODY>"
echo "</BODY></HTML>"

El script envia la orden de apagar por el puerto serie y redirecciona a la página principal (control.html).

4) Otorgamos permisos de ejecución a dichos scripts.

5) Deberíamos tener una estructura asi:



Veamos el resultado final con un video:









Ahora ya sólo imaginación.... ¿qué tal subir/bajar la puerta del garage mediante Wifi y un móvil?  Ya he probado a conectarme con mi nokia n85 y va perfecto!! ...je,je,je








.

LINKDUINO: Twitter

.



Primero, poner el link de mi fuente de inspiración http://www.themagicclock.com/

Veamos un sencillo ejemplo de cómo sacarle más partido a éste hardware. (Asumimos que tienes instalado DD-WRT,  con el hack del puerto serie e interfaz apropiada para cambiar niveles 3v3 a 5 voltios y tu router tiene conexión a internet).

Crearemos un script sencillo en el bash del router, el cual se conecta a la página xml de una cuenta Twitter y obtiene el "status" actual de dicho usuario. Una vez obtenido, enviará dicho status a nuestro Arduino por puerto serie.
Para ello, nuestro Arduino contendrá el programa de ejemplo explicado anteriormente aqui (mini protocolo serie).

En este caso concreto, según el status del usuario:
  • Si status = S1F, entonces activará el pin 13.
  • Si status = S0F, entonces desactivará el pin 13.
En el ejemplo, uso la cuenta Twitter de éste blog => http://twitter.com/users/show/real2electronic.xml
Podemos ver, que el status actual se encuentra entre las etiquetas text.

El código de nuestro script es:

#!/bin/sh
while true
do
 ping www.google.es -c 4
 URL="http://twitter.com/users/show/real2electronic.xml"

 contenido=`wget -q -O - $URL|grep \<text|sed -e s/\<text\>//g -e s:\</text\>::g`

 echo $contenido
 echo $contenido > /dev/cua/1
 for i in 1 2 3 4 5
 do
  gpio disable 7
  sleep 1
  gpio enable 7
  sleep 1
 done
done




1) Es script realiza un ping para forzar conexión con internet.
2) Obtiene la página, y extrae la linea que se encuentra entre <text> y </text>
3) Muestra y envia por puerto serie dicha cadena
4) Realiza un bucle de encendido/apagado del led de DMZ del router.

Para escribir dicho script, puedes hacerlo mediante vi (conectandote por telnet al router), o bien enviarlo usando WinSCP. Para usar este último,sigue instrucciones de http://www.dd-wrt.com/wiki/index.php/WinSCP




Algo curioso que he descubierto haciendo el script, es que no se pueden realizar más de 150 peticiones a la hora a la página xml de Twitter, asi que se debe modificar dicho script con un sleep de mayor duración. No lo he modificado, para que no sea pesado a la hora de probarlo.


Copia ó crealo con vi dicho script en el directorio /tmp/, el cual tiene permisos de escritura.
Dale permisos de ejecución al archivo: chmod 755 script_name, por ejemplo chmod 755 twitter.sh.
Para ejecutar en segundo plano: root@DD-WRT:/tmp# ./twitter.sh &
 
Recuerda, que dicha estructura de carpetas es RAM y perderás el script cuando reinicie el router.
Si quieres que permanezca en memoria => http://www.dd-wrt.com/wiki/index.php/Startup_Scripts#NVRAM_Method



A continuación, un video tutorial de todo el proceso:







Ahora ya puedes abrir/cerrar una puerta, encender/apagar una caldera, activar una bocina para asustar a tu pareja ... lo que se te ocurra desde Twitter !!!









.

Graficar con Kst

.





Veamos la forma más sencilla (que he encontrado hasta ahora) de graficar datos recibidos de nuestro Arduino en "real time". Tiene la ventaja sobre excel, que está preparado para trabajar con gran cantidad de datos, ya que excel está limitado a 32.000 puntos en gráficos 2D.
Otra gran ventaja... es gratuito!! Se encuentra disponible para entorno Windows y Linux.

Para ello nos ayudaremos de dos softwares gratuitos:
Si se trabaja con linux, no se necesita Realterm, ya que se puede capturar directamente todo lo recibido por el puerto serie a un archivo.

 
Según la propia web: " Kst es la herramienta más rápida para graficar gran volumen de datos en real-time y con funcionalidades básicas para el análisis."
Gracias a KST, dispondremos de posibilidad de disponer varias vetanas, múltiples gráficas, PSD, zoom, histogramas, ...
Ejemplo demo de pantalla (extraido de la web de Kst):





La idea es:
1) Usar Realterm para capturar todo lo recibido por el puerto serie a un archivo de texto.
2) Plotear dicho archivo de texto con la ayuda de KST.

En Realterm sólo tenemos que abrir el puerto serie correnspondiente a nuestro Arduino.
Mi programa de ejemplo de Arduino, esta preparado para enviar datos de forma continua, cuando se recibe una "C" y detener el envio, cuando se recibe una "F".
 
 
--------- CÓDIGO ARDUINO ---------

extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long tiempo;
byte serialByte;

void setup() {

   Serial.begin(9600);
   Serial.println("Empezamos...");
}

void loop() 
{

  while (Serial.available()>0){  
    serialByte=Serial.read();
    if (serialByte=='C'){        
      while(1){
        analog0=analogRead(0);
        // Convierto a milivoltios
        fanalog0=(analog0)*(5000.0/1023);
        // Recojo ticks del timer0 => 1 tick cada 4 us (usado en millis )
        tiempo=(timer0_overflow_count << 8) + TCNT0;
        // Convierto a us
        tiempo=tiempo*4;
        //Lo envio para simular archivo tipo *.csv
        Serial.print(tiempo);
        Serial.print(';',BYTE);
        Serial.println(fanalog0,DEC);
        if (Serial.available()>0){
          serialByte=Serial.read();
          if (serialByte=='F')  break;
        }
      }
    }
  }
}


--------- FIN DEL CODIGO ---------




Por lo que en la pestaña Send, le enviaremos el caracter ASCII => C
Veremos como empezamos a ver en la parte superior los datos recibidos.
Después en la pestaña Capture, seleccionar la ruta del archivo donde se capturan los datos y pulsamos Start Overwrite. Si Direct Capture está seleccionado, dejaremos de ver los datos recibidos (acelera el proceso).



(click sobre la imagen para ver en tamaño completo)


Ahora con el archivo creado y actualizandose con los datos recibidos, sólo nos queda irnos a Kst.
Alli, pulsamos sobre Data Wizard y elegimos la ruta donde se encuentra nuestro archivo.
En Configure, elegimos cual es nuestro limitador de columnas, en mi ejemplo " ; ".



(click sobre la imagen para ver en tamaño completo)

En las siguientes pantallas, configuramos que queremos crear una gráfica siendo X la primera columna (tiempo en us) e Y la segunda columna (mV entrada analógica 0).


Ya tenemos nuestro gráfico!!!  el cual se irá actualizando a la medida que se vayan recibiendo nuevos datos (hay un pequeño retraso, no es instantaneo).
A continuación, un ejemplo de una señal capturada de un potenciómetro, para realizar este pequeño tutorial.



(click sobre la imagen para ver en tamaño completo)


Podremos usar Kst para ver los datos en real-time ó abrir datos grabados anteriormente.
Veamos un video demostrativo:








Espero que sea de utilidad este mini-tutorial.


.

LINKDUINO


Rapid Prototyping Hardware



.










Como ingenieros de sistemas, conocemos perfectamente lo valioso que es el tiempo y lo exigente que es la industria privada cuando se requiere una solución.

El tiempo es dinero, y el poder poner en práctica lo que tienes en mente, sin tener que pasar horas buscando una plataforma adecuada, hace que al final, tu solución no sea competitiva.

Además, es muy importante que el tiempo de aprendizaje necesario para poder obtener resultados tangibles, sea corto.

Una de las cosas que más importancia tiene a la hora de elección, es el hecho de disponer soporte técnico y ejemplos de aplicación.

Por todas estas razones, ofrecemos una plataforma basada en hardware/software libre, en la que existe una gran comunidad por detrás, y en la que hay multitud de recursos en la red.


Los requisitos que hemos exigido son:

  • Open hardware.
  • Sin licencias software.
  • Low cost.
  • Rápida línea de aprendizaje en su uso.
  • Documentación.
  • Comunicaciones: CAN, RS232, RS485, Ethernet, Wifi, Internet.
  • Todos los componentes, por si solos, deben tener una comunidad por detrás.
  • Programación en alto nivel.
  • Posibilidad de almacenaje de datos.
  • Interface con los principales software: Matlab/Simulink, Excel, Labview, PHP, MySQL, Scilab,… (Todas ellas marcas registradas).
  • No debe ser motivo de obsesión, ser la herramienta hardware más potente del mercado, ya que su objetivo no es el mismo.
  • Lo más abierta posible, buscando abarcar el máximo de sectores industriales.
  • Librerías y/o ejemplos básicos, para que en la mayoría de aplicaciones, el usuario tenga el 80% del trabajo realizado.
  • Posibilidad de profundizar y exprimir al máximo posible en caso de necesitarlo.



LINKDUINO
  • Router WRT54GL con mod para SD/MMC ó similar.
  • ATMega1280 (basado en proyecto Arduino).
  • Hardware para disponer de RS485 y bus CAN.
  • Posibilidad de expandir con gps, lcd, glcd, ...
De ésta unión, conseguimos disponer de un dispositivo de altísima potencia, del que nos podemos aprovechar de la cantidad de recursos existentes:

  • DD-WRT: Eleva con este firmware las características del router a niveles profesionales.
  • Arduino IDE
  • Putty
  • RealTerm
  • WinSCP: Facilita la transferencia segura de archivos entre dos sistemas informáticos, el local y uno remoto que ofrezca servicios SSH. Descarga drag&drop archivos grabados en tu router.
  • NetCom OCX
  • Ostrosoft Winsock Component
  • ... y muchos más.

Combina la potencia de tener un sistema operativo Linux, junto a la programación en "bajo nivel" del micro ATmega. Tus ideas quedarán rápidamente materializadas. Siempre buscando la sencillez, para alcanzar el objetivo marcado.

- Configura tu red Ethernet/Wifi gracias a la potente interface web. Sin necesidad de conocimiento de comandos unix.
- Olvídate de bajos niveles de programación TCP/IP ó de red.
- Crea web embebida en tu dispositivo, usando html,php,ajax,...
- Vuelca datos en SD/MMC,en la memoria de tu router ó en un equipo de tu red.
- Añade hardware necesario para cubrir tus necesidades gracias a las múltiples I/O, entradas analógicas, SPI, I2C, uarts,...
- Conecta con los aparatos industriales gracias a RS232, RS485 ó CAN.
- Amplia cobertura wireless, añadiendo otros routers (WDS).
- Utiliza la multitud de librerias y ejemplos que existen por la red.



Algunos ámbitos de uso, podrían ser:
- Realización de software para el control, configuración y monitorización de variadores de potencia, analizadores eléctricos, maquinas frigoríficas, ventiladores, ...
- Sistema domóticos, de riego, alarmas, ...
- Telemetría para bancos de ensayos.
- Monitorización de procesos.
- Control de flotas.
- Obtención de datos de procesos industriales y almacenaje en bases de datos en red (SQL).
- Estaciones meteorológicas remotas.
- Creación de simuladores para el testeo de maquinas, centralitas,...
- Añade conectividad a tus proyectos.
- Tests automoción
- etc...







¿Quieres que te ayudemos para comenzar en tu proyecto con este hardware?
¿No dispones de tiempo para crear el hardware por ti mismo y deseas que te lo proporcionemos listo para empezar?
¿Tienes ideas para mejorar el sistema?  => Publica tu comentario (evitar Anónimo).
¿Quieres contarnos tus experiencias?    => Publica tu comentario (evitar Anónimo).
¿Quieres expresarnos ánimo para seguir adelante con la idea? => Publica tu comentario (evitar Anónimo).
¿Quieres mostrar el proyecto que has realizado con LINKDUINO ó similar?

CONTACTA POR EMAIL



Se irán añadiendo periódicamente ejemplos creados con LINKDUINO, prevaleciendo la sencillez y rapidez para la puesta en marcha. Usa el menu izquierdo para navegar por el contenido de la web.


















Síguenos con Twitter