GPS + Edison + Cloud – Fase 1 – Leer el GPS

Descripción

En esta serie de tutoriales estaremos explorando la utilización de un módulo de GPS en un Intel Edison, y la forma de subir los datos generados a la nube.

En esta primera entrega estaremos utilizando un “shield” GPS para ARDUINO, montado sobre un Intel Edison. Leeremos los datos provenientes del GPS utilizando una adaptación de la librería “TinyGPS” que originalmente fue escrita por Mikal Hart (@mikalhart) y luego modificada por nuestro amigo Heiner Alvarado de Intel CR.

Referencias Externas

  1. https://github.com/mikalhart/TinyGPS

Aviso de Responsabilidad Limitada

(!) Antes de seguir estas instrucciones asegúrese de entender las Condiciones de Uso de nuestro sitio.

Resumen

  1. Conecte el Shield de GPS para ARDUINO en la tarjeta “Breakout” del Edison.
  2. Asegúrese de que los “jumpers” de configuración de puerto serial están configurados para que el pin TX del shield conecte con el pin RX del Edison (pin 0) y el pin RX del shield conecte con el TX del Edison (Pin 1) (ver figura 2)
  3. Copie la librería TinyGPS modificada de https://github.com/janunezc/TinyGPS
  4. Desempaque la librería en su carpeta local de librerias de ARDUINO (c:\users\su_usuario\Documents\Arduino\libraries\TinyGPS\)
  5. Cargue el Arduino IDE y abra el ejemplo correspondiente a File > Examples > TinyGPS > edison_basic_gps.ino
  6. Note cómo tarda algunos segundos en conectarse con el sistema GPS; luego de eso emitirá notificaciones en el monitor serial sobre las coordenadas leidas por el GPS.

Edison y GPS
GPS

Figura 1 – Conexiones y Configuraciones por Jumpers

Materiales

Agradecimientos

  • A Heiner Alvarado Fonseca de Intel CR por darse a la tarea de compatibilizar la librería “TinyGPS” con Intel Edison

Lectura Relacionada

  1. GPS + Edison + Cloud – Fase 1 – Leer el GPS
  2. GPS + Edison + Cloud – Fase 2 – Conectar al Cloud
  3. GPS + Edison + Cloud – Fase 3 – Recuperación de fallas

Servo-motores y Resolución Angular

Recientemente estuve jugando con unos servos para un proyecto que requiere hacer que el servo se mueva “grado por grado” desde cero hasta 180 grados.

Descubrí que de los 0º a los 10° no parece ocurrir movimiento alguno, así que por accidente descubrí que los servos comerciales que compré no tienen una resolución menor a 10 grados.

El siguiente sketch de Arduino hace ese barrido desde los  0º a los 180° en cámara lenta, de forma que nos permite ver de manera experimental cual es la resolución de un servo determinado.

En mi caso, al parecer el servo que tengo tiene una resolución de aproximadamente 7°, lo que quiere decir que si le pido una posición que no dista más de 7 grados de la posición actual, el servo no se moverá.


#include  
#include "rgb_lcd.h"
#define trigger    2
#define echo       7
#define led       13
rgb_lcd lcd;
Servo myservo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
 

void setup() 
{ 
  Serial.begin(9600);
  Serial.println("SETUP");
  lcd.begin(16,2); // columns, rows.  use 16,2 for a 16x2 LCD, etc.
  lcd.setRGB(50,50,50);
  pinMode(trigger, OUTPUT);
  pinMode(echo, INPUT);
  pinMode(13,OUTPUT);
  myservo.attach(3);  // attaches the servo on pin 9 to the servo object 
  myservo.write(0);
  Serial.println("SETUP COMPLETE!");
} 
 
 
void loop() 
{ 
  Serial.println("BEGINING SCAN...");
  blinkEffect(3,500);
  Serial.println("SCANNING...");
  for(int i=0; i<=180; i++){
    Serial.print("ANGLE: ");
    Serial.println(i);
    lcd.setCursor(0,0);
    lcd.print("ANGLE: ");
    lcd.print(i);
    lcd.print("    ");
    myservo.write(i);
    delay(1000);
  }
} 


void blinkEffect(int times, int duration){
  for(int i=0; i<3; i++){
    digitalWrite(led,HIGH);
    delay(duration);
    digitalWrite(led,LOW);
    delay(duration);
  }
}

Cifrado de contraseñas

El tema de seguridad informática adquiere una relevancia exponencial en el advenimiento de la Internet de las Cosas, y de la cultura Maker; especialmente conforme comenzamos a desarrollar sistemas que realizan actividades más y más relevantes para el bienestar humano.

No son pocas las referencias de incidentes de seguridad de empresas de alto nivel tales como Sony, Linkedin y otros, que han sido víctimas del robo de datos de credenciales de usuarios; con el agravante de que, en numerosas ocasiones esas credenciales son utilizadas por los usuarios en multiples dominios; por ejemplo, el uso de una misma clave para varios sistemas (Facebook, Email, etc)

Este artículo tiene como objetivo explicar algunos procedimientos de uso común para el almacenamiento de contraseñas afin de reducir el riesgo de robo de credenciales para sus usuarios en sus aplicaciones IoT.

1. Teoría de “Hashing”

La palabra del Inglés “Hash” se traduce en español como “Picadillo”.

Este es el nombre de un procedimiento ampliamente usado para cifrar contraseñas que se deban almacenarse en los sistemas. Consiste en ejecutar un algoritmo matemático para convertir una contraseña (o cualquier texto legible) en otro cifrado que sea prácticamente único para esa contraseña.

Dentro de los algoritmos más confiables en la actualidad están el SHA1 o el SHA256. La característica principal de estos algoritmos es que para un texto legible dado (por ejemplo “mi contraseña”) al ejecutar el algoritmo para dicho texto, siempre va a resultar en un mismo texto cifrado, y que la mínima modificación del texto origen (por ejemplo “mi contrasena”) el resultado del algoritmo es extremadamente diferente. La otra caracterísitca importante es que el algoritmo descompone el texto legible inicial de forma tal que no hay forma matemática para re-componer el texto legible a partir del hash resultante.

Ejemplo:

SHA1("mi contraseña") ==> "823b57eb35f4e42e06a365d2af3cb6ebd6f9e89e"
SHA1("mi contrasena") ==> "6347b04dd43af8911075fc585d72f2fed320b264"

La forma en que se utiliza un mecanismo de hashing para almacenar contraseñas es que, en el sistema no se almacena la contraseña legible, sino su versión “hash”, y a la hora de autenticar un usuario, se toma la contraseña legible que este usuario suministra y se hace pasar por el proceso de hashing, luego se compara el hash almacenado con el hash de la contraseña suministrada para decidir si el usuario ingresó la contraseña correcta.

1.1 Debilidades

Si bien se ha mencionado que no existe forma matemática de re-componer un texto legible a partir de un hash, sí existen formas de conseguir:

(Caso a) el valor de la contraseña original si esta es demasiado simple, o

(Caso b) un valor que, pasado por el proceso de hashing, dé como resultado un valor hash predeterminado. A este proceso (caso b) se le llama “Colisión de hash” o “Hash Collision” que consiste en qué tan facil es encontrar dos valores que den como resultado un valor hash predeterminado. Para contrarrestar la debilidad  se debe utilizar un algoritmo de hashing suficientemente robusto respecto de la capacidad computacional actual. Por ejemplo, el algoritmo MD5 no se considera seguro por que es relativamente fácil con la capacidad computacional actual, encontrar colisiones para valores predeterminados de hash.

Cuando una contraseña es demasiado simple o predecible (caso a), puede encontrarse su valor de hash en tablas que se conocen como “rainbow tables”. A manera de ejemplo, basta con buscar en google el hash “7110eda4d09e062aa5e4a390b0a572ac0d2c0220” para ver los numerosos sitios de Internet que son capaces de determinar que corresponde a la clave “1234” usando el algoritmo SHA1

La siguiente figura explica el proceso de creacion de un hash.

hash_1b

2. Agregando algo de Sal

Para contrarrestar la existencia de tablas “rainbow” descritas anteriormente (caso a) se utiliza un mecanismo de seguridad adicional que se llama adición de sal  que consiste en agregar un valor aleatorio para cada contraseña a fin de que el valor hash resultante no coincida con ninguno en una tabla “rainbow”

En la siguiente sección explicamos el proceso de almacenamiento de “hash salados” y el proceso de comparación de una contraseña legible con estos hash a fin de determinar si la contraseña es correcta.

2.1 Almacenando contraseñas con hash salados

En el anterior apartado titulado “Teoría de Hashing” explicamos como el uso de una funcion SHA1 (u otro algoritmo de hashing) puede ser utilizado para generar códigos hash a partir de contraseñas legibles que se puedan almacenar, con ciertas limitaciones o debilidades inherentes a contraseñas demasiado sencillas o algoritmos demasiado fáciles de “hackear”.

El procedimiento de crear un “hash salado” a partir de una contraseña legible se puede enumerar en los siguientes pasos:

  1. Crear un hash simple a partir de la contraseña legible (   hash = sha1("1234");   )
  2. Generar un código aleatorio (sal) apto para criptografía*  (   sal = random_int(100000,999999);   )
  3. Concatenar la sal con el hash simple (  codigoSalado = sal + hash; )
  4. Generar un hash con base en los valores concatenados (   hashRobusto = sha1(codigoSalado);   )
  5. Concatenar nuevamente la sal con el nuevo hash para ser almacenado (   codigoParaAlmacenar = sal + hashRobusto; )
  6. Almacenar el valor del hash robusto con la sal  (   guardar (hashParaAlmacenar);

En la siguiente figura se ilustra el flujo de datos y procesos relacionados con el almacenamiento de contraseñas a través de hash salados.

hash_2d

2.2 Autenticación, comparando contraseñas legibles on hash salados almacenados

El procedimiento para autenticar un usuario respecto de una contraseña almacenada en la forma de un hash salado se puede describir como sigue:

  1. Generar un hash simple a partir de la contraseña suministrada  (   hash = sha1(contraseña);   )
  2. Obtener de la base de datos el hashRobusto y la sal correspondientes (   hashGuardado = obtenerHash (usuario);   )
  3. Descomponer la sal del hash robusto  (   sal = substr(hashGuardado, 0, 6);   hashRobustoAlmacenado = substr(hashGuardado,6);   )
  4. Concatenar la sal junto con el hash simple generado a partir de la contraseña suministrsada (   salYHash = sal + hash;   )
  5. Generar un hash robusto para la comparacion a partir de la concatenacion anterior (   hashParaComparar = sha1(salYHash);   )
  6. Realizar la comparacion de hashes (contraseñaValida =  hashParaComparar == hashRobustoAlmacenado; //comparación veradero/falso )

En la siguiente figura se ilustra el flujo de datos y procesos para la comparacion de contraseñas en un proceso de autenticación.

hash_2e

Conclusiones

Es imperativo no almacenar contraseñas legibles en los sistemas de informáticos, incluyendo IoT.

El uso de hash salados en el almacenamiento de contraseñas es una técnica ampliamente utilizada para minimizar los riesgos de robo de credenciales, el procedimiento es extremadamente sencillo y permite incrementar de manera significativa la seguridad de los sistemas.

¡No hay razón para hacerlo mal!


(*) Un valor aleatorio apto para criptografía es un número dificil de predecir. En general los números aleatorios generados por software se basan en listas predefinidas, que pueden ser más o menos predecibles.

Arduino 101 – Tutorial

Bienvenido al tutorial introductorio de la placa Arduino 101; sin duda una tarjeta especial para aprender y para prototipar usando conceptos de movimiento (aceleración, rotación) y sistemas de comunicación de red de área personal (PAN) para el desarrollo de ideas de tecnología vestible.

Al momento de escribir este tutorial, el Arduino 101 tenia un costo de $30, mientras que el Arduino UNO convencional un costo de $25.


(!) Antes de seguir estas instrucciones asegúrese de entender las Condiciones de Uso de nuestro sitio.


Contenido:

  1. ¿Qué es el Arduino 101 y qué es Intel Curie?
  2. Ejercicios:
    1. Acelerómetro y Giroscopio
    2. Acelerómetro y BLE: Contador de Pasos
    3. Bluetooth Low Energy (BLE): Monitor de Batería
    4. RTC / EEPROM
  3. ¿Dónde encontrar más información?

¿Qué es un Arduino 101 y qué es un Intel Curie?

El Arduino 101 es una de las más recientes creaciones de la familia de placas Arduino. Es una placa para prototipado y aprendizaje que implementa el nuevo chip SoC (Sistema en un solo chip) de Intel denominado Intel Curie(r)

¿Intel Curie?

Se trata del sistema en un solo chip más reciente de Intel, orientado al “mercado maker” que tiene como objetivo traer mayores capacidades computacionales y de sensado y comunicación al mundo maker y el mercado de la computación vestible y embebida.

Dentro de las especificaciones y funcionalidades de Intel Curie encontramos:

  • Voltaje de operación de 3.3V
  • Memoria Flash (no volatil) de 384Kb
  • Memoria SRAM (volatil) de 80Kb
  • Sistema on-chip QUARK-SE
  • Capacidad de comunicación Bluetooth Low Energy (BLE)
  • Combo integrado de sensores: acelerómetro + giroscópio 6 ejes.

Al implementar Intel Curie, el Arduino 101 presenta las siguientes ventajas comparativas con respecto del Arduino UNO

  • 196 Kb de memoria no volatil (flash). 6 veces más memoria que el Arduino UNO que trae 32Kb.
  • 24 Kb de memoria volatil (SRAM). 12 veces más memoria que el Arduino UNO que trae 2Kb.
  • 32MHz de velocidad de reloj; lo que representa el doble de los 16MHz del Arduino UNO
  • Alimentación (barril) de 7-12V
  • Sistema Operativo de Tiempo Real (RTOS) instalado en el Curie
  • Reloj de tiempo real (RTC)
  • Corriente por pin: 20mA
  • Sensores de Movimiento de 6 ejes: Acelerómetro (x,y,z) y giroscopio (roll, jaw, pitch)

La siguiente imagen ilustra los 6 ejes de movimiento sensables:

ejes_acc_gyro

Figura 1 – Ejes detectables de movimiento.


EJERCICIOS

En estos cuatro ejercicios exploraremos las diferentes funciones del Arduino 101, en lo referente a sensores de movimiento, comunicación Bluetooth BLE y uso de la memoria no volatil del sistema.

Para todos los ejercicios utilizaremos este programa base:

/*
 Copyright (c) 2015 Intel Corporation. All rights reserved.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

 Modified by Jose Nunez @ intel corporation on April 2 2016

 https://www.arduino.cc/en/Tutorial/Genuino101CurieBLEHeartRateMonitor
 
*/

/*
 This sketch example demonstrates how the BMI160 on the
 Intel(R) Curie(TM) module can be used to read accelerometer data
*/

#include "CurieIMU.h"
#include <CurieBLE.h>

int EXERCISE = 1;


/****************** BLE HEARTRATE GLOBALS **************************/
BLEPeripheral blePeripheral; // BLE Peripheral Device (the board you're programming)
BLEService heartRateService("180D"); // BLE Heart Rate Service

// BLE Heart Rate Measurement Characteristic"
BLECharacteristic heartRateChar("2A37", // standard 16-bit characteristic UUID
 BLERead | BLENotify, 2); // remote clients will be able to get notifications if this characteristic changes
 // the characteristic is 2 bytes long as the first field needs to be "Flags" as per BLE specifications
 // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml

int oldHeartRate = 0; // last heart rate reading from analog input
long previousMillis = 0; // last time the heart rate was checked, in ms
/****************** END OF BLE HEARTRATE GLOBALS **************************/

void setup() {
 delay(3000);
 Serial.begin(9600); // initialize Serial communication
 pinMode(13, OUTPUT); // initialize the LED on pin 13 to indicate when a central is connected
 while (!Serial); // wait for the serial port to open
 Serial.println("SETUP...");
 // initialize device
 Serial.println("Initializing IMU device...");
 CurieIMU.begin();

 // Set the accelerometer range to 2G
 CurieIMU.setAccelerometerRange(2);

/****************** BLE HEARTRATE SETUP **************************/
 /* Set a local name for the BLE device
 This name will appear in advertising packets
 and can be used by remote devices to identify this BLE device
 The name can be changed but maybe be truncated based on space left in advertisement packet */
 blePeripheral.setLocalName("HeartRateSketch");
 blePeripheral.setAdvertisedServiceUuid(heartRateService.uuid()); // add the service UUID
 blePeripheral.addAttribute(heartRateService); // Add the BLE Heart Rate service
 blePeripheral.addAttribute(heartRateChar); // add the Heart Rate Measurement characteristic

 /* Now activate the BLE device. It will start continuously transmitting BLE
 advertising packets and will be visible to remote BLE central devices
 until it receives a new connection */
 blePeripheral.begin();
 Serial.println("Bluetooth device active, waiting for connections...");
/****************** END OF BLE HEARTRATE SETUP **************************/

 Serial.println("SETUP COMPLETE");
 
}

void loop() {
 switch(EXERCISE){
 case 1: 
 readAndReportAccelerometer();
 break;
 case 2:
 readAndReportGyroscope();
 break;
 case 3:
 monitorHeartRate();
 break;
 }
}

float pax, pay, paz, dax, dayy, daz;
void readAndReportAccelerometer(){
 int axRaw, ayRaw, azRaw; // raw accelerometer values
 float ax, ay, az;

 // read raw accelerometer measurements from device
 CurieIMU.readAccelerometer(axRaw, ayRaw, azRaw);

 // convert the raw accelerometer data to G's
 ax = convertRawAcceleration(axRaw);
 ay = convertRawAcceleration(ayRaw);
 az = convertRawAcceleration(azRaw);

 dax = abs(ax-pax);
 dayy = abs(ay-pay);
 daz = abs(az-paz);
 
 if(dax>0.02 || dayy>0.02 || daz>0.02){

 // display tab-separated accelerometer x/y/z values
 Serial.print("a:\t");
 Serial.print(ax);
 Serial.print("\t");
 Serial.print(ay);
 Serial.print("\t");
 Serial.print(az);
 Serial.println();

 pax = ax;
 pay = ay;
 paz = az;
 } 
}

float prev_gx, prev_gy, prev_gz, diff_gx, diff_gy, diff_gz;
float relevancyTrigger = 0.3;
void readAndReportGyroscope() {
 int gxRaw, gyRaw, gzRaw; // raw gyro values
 float gx, gy, gz;

 // read raw gyro measurements from device
 CurieIMU.readGyro(gxRaw, gyRaw, gzRaw);

 // convert the raw gyro data to degrees/second
 gx = convertRawGyro(gxRaw);
 gy = convertRawGyro(gyRaw);
 gz = convertRawGyro(gzRaw);

 diff_gx = abs(prev_gx-gx);
 diff_gy = abs(prev_gy-gy);
 diff_gz = abs(prev_gz-gz);

 if(diff_gx>relevancyTrigger || diff_gy>relevancyTrigger || diff_gz>relevancyTrigger){

 // display tab-separated gyro x/y/z values
 Serial.print("g: \t");
 Serial.print(gx);
 Serial.print("\t");
 Serial.print(gy);
 Serial.print("\t");
 Serial.print(gz);
 Serial.println( "");

 prev_gx = gx;
 prev_gy = gy;
 prev_gz = gz;
 }

}

void monitorHeartRate(){
 // listen for BLE peripherals to connect:
 BLECentral central = blePeripheral.central();

 // if a central is connected to peripheral:
 if (central) {
 Serial.print("Connected to central: ");
 // print the central's MAC address:
 Serial.println(central.address());
 // turn on the LED to indicate the connection:
 digitalWrite(13, HIGH);

 // check the heart rate measurement every 200ms
 // as long as the central is still connected:
 while (central.connected()) {
 long currentMillis = millis();
 // if 200ms have passed, check the heart rate measurement:
 if (currentMillis - previousMillis >= 200) {
 previousMillis = currentMillis;
 updateHeartRate();
 }
 }
 // when the central disconnects, turn off the LED:
 digitalWrite(13, LOW);
 Serial.print("Disconnected from central: ");
 Serial.println(central.address());
 }
}

void updateHeartRate() {
 /* Read the current voltage level on the A0 analog input pin.
 This is used here to simulate the heart rate's measurement.
 */
 int heartRateMeasurement = analogRead(A0);
 int heartRate = map(heartRateMeasurement, 0, 1023, 0, 100);
 if (heartRate != oldHeartRate) { // if the heart rate has changed
 Serial.print("Heart Rate is now: "); // print it
 Serial.println(heartRate);
 const unsigned char heartRateCharArray[2] = { 0, (char)heartRate };
 heartRateChar.setValue(heartRateCharArray, 2); // and update the heart rate measurement characteristic
 oldHeartRate = heartRate; // save the level for next comparison
 }
}

float convertRawAcceleration(int aRaw) {
 // since we are using 2G range
 // -2g maps to a raw value of -32768
 // +2g maps to a raw value of 32767
 
 float a = (aRaw * 2.0) / 32768.0;

 return a;
}

float convertRawGyro(int gRaw) {
 // since we are using 250 degrees/seconds range
 // -250 maps to a raw value of -32768
 // +250 maps to a raw value of 32767
 
 float g = (gRaw * 250.0) / 32768.0;

 return g;
}

 

EJERCICIOS #1 y 2 – ACELERÓMETRO Y GIROSCOPIO

En este ejercicio realizaremos lecturas del acelerómetro y del giroscopio y mostraremos el resultado en el monitor serial.

A su vez, implementamos una lógica de detección de cambios relevantes que nos permitirá observar con mayor claridad los cambios ocurridos en las medidas de los sensores.

PASO 1 – Cargue el programa del tutorial en su Arduino 101

PASO 2 – Utilizando la Figura 1 como guía, verifique en el Monitor Serial del IDE ARDUINO si los ejes mencionados son correctos para el acelerómetro (x,y,z)

PASO 3 – Modifique el programa, comentando la línea 32 para darle el valor de 2 a la variable EXERCISE.

ex02

PASO 4 – Cargue el programa modificado al Arduino 101 y verifique  los ejes de giro tal y como se ilustran en la Figura 1

PASO 5 – Preste atención a las líneas de la 110 a la 114; esta es la lógica de detección de cambios relevantes. Trate de explicarla.

110-114

PASO 6 – Ahora preste atención a las líneas de la 145 a la 149, es una implementación más limpia / autoexplicable de la lógica de detección de cambios relevantes. Trate de explicarla.

145-149

PASO 7 – Reto: Modifique la lógica de detección de  cambios relevantes para que detecte cualquier cambio.


EJERCICIO #3 – SIMULACION DE BLE HEARTBEAT SERVICE

En este ejercicio vamos a utilizar la comunicación Bluetooth/BLE para simular un mecanismo de detección de ritmo cardiaco y graficarlo en el celular.

Para esto necesitaremos un celular con capacidad BLE. En este descargaremos una aplicación llamada “nRF Toolbox” la cual hace una implementación de varios esquemas de servicio BLE. Utilizaremos entonces el servicio “HRM” (Heart Rate Monitor) para graficar datos provenientes del Arduino 101.

PASO 1 – Instale nRF Toolbox en su celular

PASO 2 – Re-configure el sketch base de este tutorial para ejecutar el ejercicio 3. En la línea 32 modifique la variable EXERCISE para que tenga un valor de 3.

arduino101_ex3

 

PASO 3 – Descargue el programa hacia la placa Arduino 101

PASO 4 – Abra el Monitor Serial (SHIFT + CTRL + M)

PASO 5 – En su celular, abra la aplicación “nRF Toolbox” y abra el servicio HRM. Allí pulse el botón “Connect” y elija “HeartRateSketch”

4 screens

PASO 6 – Observe cómo se grafican los datos

PASO 7 – Explicación

Esta simulación toma el valor de uno de los puertos analógicos del Arduino 101 (A0) y envia los datos a través de un servicio BLE estandard de tipo “Heart Rate Service”. Si se deja el pin A0 de la placa sin conexion, este tendrá valores “aleatorios” que serán graficados igual.

 


Recursos Adicionales

https://www.arduino.cc/en/Guide/Arduino101

http://www.intel.com/content/www/us/en/wearables/wearable-soc.html

 

ARDUINO DAY 2016 – Nuestro Grano de Arena

Ya estamos a las puertas del ARDUINO DAY.

Nosotros estaremos brindando un par de talleres, uno de ARDUINO 101, y otro de Intel Edison, que esperamos inspiren a muchos a “buscar qué hacer

AGENDA: http://genuinodaycr.cc/

  1. ARDUINO 101 por Jose Nunez, Yaser Castillo y Jonathan Guevara @ 10am-12md @ LAB 14
  2. Intel Edison IoT por Jonathan Guevara y Jose Nunez @ 1:30pm-3:30pm @ Aula 06.

Adicionalmente estaremos colaborando en conjunto con profesionales del Laboratorio de Innovación Tecnológica (LIT) de UNED en una charla denominada “Huella Sónica, un Proyecto de Investigación al Estilo Maker” a las 4:10pm 

¡Nos vemos!

arduino_day_2016_afiche