Novedoso instrumento “todo en uno “


Para aquellos que quieran o necesiten un laboratorio y tengan un presupuesto ajustado  este nuevo  proyecto financiado por crowsorcing ,Red Pitaya promete ser  la solución.

Se trata de un hardware con todo lo necesario para que uses un PC, una tableta o un smartphone como equipo de investigación común de un laboratorio  profesional ya que con algunos cables para conectarlo y unos clicks podrás comenzar a usar un osciloscopio, un analizador de espectro, un analizador de frecuencia de respuesta, entre otros que vendrá incluidos por US$499 , que comparando con equipos normales los creadores  opinan serian mas de US$1000

 

pitaya

 

EL HARDWARE RED PITAYA

ANALÓGICO
Los canales de entrada de RF : 2
Ancho de banda : 50 MHz ( DC acoplados , 3dB BW)
Frecuencia de muestreo : 125 Msps
Resolución ADC : 14 bits ( LTC ADC )
Impedancia de entrada: 1 MOhm / / 10pF
Entrada de canal de ganancia : FIJO ( rango dinámico mejorado por medio de 14 bit de granularidad )
Por defecto el voltaje máximo de la escala : + -0,6 V (+ -6 V con 10 veces la atenuación de la sonda) . Reconfigurable gran escala por medio de la sustitución de componentes discretos ( +- 15V) .
Protección de sobrecarga : a través de diodos de protección
Tipo de conector : SMA (SMA a BNC adaptadores y sondas disponibles en “Red Pitaya Kit de diagnóstico” )

Caracterización extremo frontal de RF

Canales de salida RF: 2
Ancho de banda : 49 MHz a 3 dB (DC acoplado , 3dB BW definido por el filtro anti- imagen)
Frecuencia de muestreo : 125 Msps
Resolución DAC: 14 bits
Impedancia: 50 Ohm
De energía a escala completa : 10 dBm ( 50 Ohm de carga )
La velocidad de respuesta de la salida: 200 V / us
Protección del cortocircuito: SI
Tipo de conector : SMA ( SMA a BNC adaptadores disponibles en “Kit de diagnóstico Pitaya rojo “)
Canales de entrada analógicos adicionales: 4
Frecuencia de muestreo : 100 ksps
Resolución ADC : 12 bits
Ancho de banda : 50 kHz
Tipo de conector : IDC (conector de desplazamiento de aislamiento )

RF caracterización extremo posterior

Canales de salida analógicos adicionales: 4
Tipo: PWM paso bajo filtrada
Frecuencia de modulación PWM : 250 MHz
Frecuencia de muestreo nominal: 100 ksps
Equivalente resolución PWM : 11.3 bits de
Tipo de conector : IDC (conector de desplazamiento de aislamiento )

DIGITAL
16 GPIO digitales con conectividad FPGA ( ó 8 diferenciales ) Lógica @ 3.3V
4 pares de señales digitales diferenciales que deben utilizarse para fines de sincronización y de transferencia de datos en serie con la capacidad de conexión en cadena de hasta 500 Mbps .
Tipo de conector : 2x conectores “tipo SATA ”
FPGA : Xilinx Zynq 7010 SoC ( 17600 LUT , 28k Celdas lógicas , 80 rebanadas DSP )
Otro conectividad : 100 Mb Ethernet , USB, USB OTG ( 2.0 ) , JTAG , I2C , UART , SPI …

 

 

 

El software para Red Pitaya

Red Pitaya se basa en el sistema operativo GNU / Linux y puede ser personalizado en diferentes niveles de programación. Interfaces de software disponibles son: HDL , C / C + +, los lenguajes de script C , Matlab y las interfaces web basadas en HTML.

La interfaz web permite el acceso de funcionalidad Pitaya rojo de la mayoría de los navegadores por lo que las aplicaciones de Red Pitaya están disponibles en iPhone , iPad, otros teléfonos inteligentes y las tabletas u ordenadores . Es muy simple para desarrollar nuevas plataformas de aplicaciones independientes que se ejecutan tan suave como aplicaciones nativas.

Conjunto inicial de OUT – OF-THE -BOX INSTRUMENTOS

OSCILOSCOPIO : 2 canales @ 125 MS / s digital de 14 bits con capacidad de disparo externo o señal basada

ANALIZADOR DE ESPECTRO : 2 canales con 50 MHz de ancho de banda de la señal con capacidad de diagrama de cascada

ARBITRARIA GENERADOR DE ONDA : 2 canales @ 125 MHz generación de forma de onda arbitraria de 14 bits con capacidad de disparo externo

RESPUESTA DE FRECUENCIA ANALIZADOR : 2 canales con ancho de banda de 60 MHz

Controlador programable 2×2 MIMO PID

pitaya2

 

Fuente aqui

Anuncios

Proyecto alarma casera con Netduino


En este original   proyecto  se trata de proteger una habitación de la bomba de sumidero  potencialmente peligrosa para los niños  asegurándose  de que las estancias quedan las  puertas cerradas y las personas (principalmente niños) no entran  en esta.

Las soluciones “alarma de la puerta” disponibles en el mercado parecen dirigidas a congeladores y simplemente no se adaptan a  necesidades mas complejas del autor   que pensaba mas bien  en una solución  con  Netduino.

La idea  original por tanto era algo que hiciera sonar  una alarma corta cuando se abriera la puerta y luego alertara a intervalos (cada pocos minutos), similar a un detector de humo con una batería que funcionase hasta agotar la batería o  hasta que la puerta se cerrase

esquema_alarma

La unidad controla la puerta a través de un interruptor magnético. Cuando se abre la puerta varias cosas suceden:

  1.  La luz del techo se enciende con un relé que controla una carga de baja  tensión.
  2.  Un servicio web se llama el cual envía un MMS a un teléfono.
  3. Un contador de tiempo que  se activa qeu al concluir  producirá una alerta sonora y hara una  llamada webservice (MMS) si la puerta permanece abierta durante un periodo de tiempo determinado.

Cuando se cierra la puerta a la luz se apaga y el temporizador de la alarma se detiene. El proyecto también incorpora una pantalla LCD de 2 líneas para mensajes, 2 LEDs (1 para la energía, 1 para la indicación de modo de problemas / override) y algunos botones para interactuar con el sistema.

Las funcionalidades de esta alarma de puerta basada en Netduino pues son las siguientes :

  •  Apaga/enciende  la luz : la enciende automáticamente cuando se abre la puerta y la apaga cuando la puerta está cerrada
  •  Alarma del MMS al abrir la puerta (a través de llamadas de servicio web)
  •  Alerta audible y alerta MMS adicional si la puerta se deja abierta más tiempo que  el  valor del temporizador
  •  Alerta que se repiten a intervalos especificados si la puerta sigue dejándose abierta
  • 4 botones :
    •  Botón 1: Manual de luz de encendido / apagado de anulación
    • – Botón 2: Regreso al control de forma automática la luz
    • – Botón 3: mensajes de error Revisión (principalmente para conexiones de red)
    • – Botón 4: Encender / apagar el sensor de la puerta (permite prolongado puerta abierta sin alerta)

Respecto al software para Netduino  se utilizan  cuatro clases :

Una clase para  dar soporte  a la comunicación de red:

public static class Network
{
public static bool NetworkAvail = false;
public static NetworkInterface ni = NetworkInterface.GetAllNetworkInterfaces()[0];

static NoteClass[] networkUpTune = {
new NoteClass(5,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(5,NoteClass.C, NoteClass.ThirtySecond)
};

static NoteClass[] networkDownTune = {
new NoteClass(3,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.C, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.Rest, NoteClass.ThirtySecond),
new NoteClass(3,NoteClass.C, NoteClass.ThirtySecond)
};

static NoteClass[] alertTune = {
new NoteClass(5,NoteClass.C, NoteClass.Eighth),
new NoteClass(6,NoteClass.C, NoteClass.Eighth),
new NoteClass(5,NoteClass.C, NoteClass.Eighth),
new NoteClass(6,NoteClass.C, NoteClass.Eighth)
};

public static void InitNetwork()
{
ParallaxLCD.Print(“Network…”);
int count = 0;
//DHCP can take a few seconds to finish so wait (up to 10 seconds) for it to complete
while (true)
{
count++;
ni = NetworkInterface.GetAllNetworkInterfaces()[0];
//only try for 10 seconds
if (ni.IPAddress != “0.0.0.0” || count > 10) break;
Thread.Sleep(1000);
}
if (ni.IPAddress == “0.0.0.0”)
{
ParallaxLCD.Print(“Network…\rError: Failed”);
}
else
{
ParallaxLCD.Print(“Network… IP:\r” + ni.IPAddress);
NetworkAvail = true;
}
//wire in event handler to keep track of the current network up/down state
NetworkChange.NetworkAvailabilityChanged += new NetworkAvailabilityChangedEventHandler(NetworkChange_NetworkAvailabilityChanged);
}

static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
NetworkAvail = e.IsAvailable;
if (Program.initializing)
return;
if (NetworkAvail)
{
ParallaxLCD.Play(networkUpTune);
}
else
{
ParallaxLCD.Play(networkDownTune);
}
}

public static void SendAlert()
{
if (NetworkAvail)
{
try
{
//HttpWebRequest
HttpWebRequest alertRequest = (HttpWebRequest)WebRequest.Create(Program.AlertWebService);
alertRequest.Method = “GET”;
HttpWebResponse alertResponse = (HttpWebResponse)alertRequest.GetResponse();
if (alertResponse.StatusCode != HttpStatusCode.OK)
{
Program.LastError = “(SendAlert) ” + alertResponse.StatusCode.ToString() + “: ” + alertResponse.StatusDescription;
ParallaxLCD.Play(alertTune);
}
}
catch (Exception e)
{
Program.LastError = “(SendAlert) ” + e.Message;
ParallaxLCD.Play(alertTune);
}
}
else
{
Program.LastError = “(SendAlert) Network unavailable”;
ParallaxLCD.Play(alertTune);
}
}

}
}

La clase  para controlar el display LCD

//Non-visible characters (Decimal ASCII) used by the Parallax LCD as commands
public enum LCD_COMMAND_CHARS
{
PrintCustomChar0 = 0,
PrintCustomChar1 = 1,
PrintCustomChar2 = 2,
PrintCustomChar3 = 3,
PrintCustomChar4 = 4,
PrintCustomChar5 = 5,
PrintCustomChar6 = 6,
PrintCustomChar7 = 7,
Backspace = 8,
Right = 9,
LineFeed = 10,
FormFeed = 12, //clears display and sets cursor to row 0 column 0
CR = 13,
BacklightOn = 17,
BacklightOff = 18,
DisplayOff = 21,
DisplayOn_NoCursor_NoBlink = 22,
DisplayOn_NoCursor_CharBlink = 23,
DisplayOn_Cursor_NoBlink = 24,
DisplayOn_Cursor_CharBlink = 25,
//Sound control
NoteLength_1_64 = 208,
NoteLength_1_32 = 209,
NoteLength_1_16 = 210,
NoteLength_1_8 = 211,
NoteLength_1_4 = 212,
NoteLength_1_2 = 213,
NoteLength_Whole = 214,
NoteScale_3 = 215,
NoteScale_4 = 216,
NoteScale_5 = 217,
NoteScale_6 = 218,
NoteScale_7 = 219,
Note_A = 220,
Note_A_Sharp = 221,
Note_B = 222,
Note_C = 223,
Note_C_Sharp = 224,
Note_D = 225,
Note_D_Sharp = 226,
Note_E = 227,
Note_F = 228,
Note_F_Sharp = 229,
Note_G = 230,
Note_G_Sharp = 231,
Note_Rest = 232,
LoadCustomChar0 = 248,
LoadCustomChar1 = 249,
LoadCustomChar2 = 250,
LoadCustomChar3 = 251,
LoadCustomChar4 = 252,
LoadCustomChar5 = 253,
LoadCustomChar6 = 254,
LoadCustomChar7 = 255
}

//This class assumes the Parallax LCD/speaker combo unit is connected to Netduino Plus Digital I/O PIN 3
//which is reserved for COM2 in the Netduino framework. Also assumes the Parallax LCD has been set to
//9600 baud using it’s onboard dip switches.
public static class ParallaxLCD
{
private static SerialPort LCD_PORT;
private static string COM_PORT = “COM2”; //Netduino Plus Digital I/O PIN 3
private static int COM_BAUD = 9600;

private static bool _LCD_state = false;

public static bool LCD
{
get
{
return _LCD_state;
}
set
{
if (value == _LCD_state)
{
//LCD already in specified state, don’t do anything
return;
}
if (value)
{
LCDOn();
BacklightOn();
}
else
{
BacklightOff();
LCDOff();
}
_LCD_state = value;
}
}
public static void Print(string inputstring)
{
//if the first line is >= 16 characters then remove the line break for a more natural behavior
int cr = inputstring.IndexOf(‘\r’, 0);
if (cr >= 16)
{
inputstring = inputstring.Substring(0, cr) + inputstring.Substring(cr + 1);
}
//this routine assumes all output will be “full screen”, meaning no other data is left on the screen
ClearLCD();
byte[] bytes = UTF8Encoding.UTF8.GetBytes(inputstring);
LCD_PORT.Write(bytes, 0, bytes.Length);
}

public static void StartSerial()
{
LCD_PORT = new SerialPort(COM_PORT, COM_BAUD, Parity.None, 8, StopBits.One);
LCD_PORT.Open();
}

public static void BacklightOn()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.BacklightOn }, 0, 1);
}

public static void BacklightOff()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.BacklightOff }, 0, 1);
}

public static void ClearLCD()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.FormFeed }, 0, 1);
}

public static void LCDOff()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.DisplayOff }, 0, 1);
}

public static void LCDOn()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.DisplayOn_NoCursor_NoBlink }, 0, 1);
}

public static void LCDCR()
{
LCD_PORT.Write(new byte[] { (int)LCD_COMMAND_CHARS.CR }, 0, 1);
}

//Short, high-pitched sound to ack as notification that an action was detected (like a button press)
public static void Acknowledge()
{
Play(new NoteClass(7, NoteClass.A, NoteClass.ThirtySecond));
}

//Sound a traditional computer beep
public static void Beep()
{
Play(new NoteClass(5, NoteClass.A, NoteClass.Quarter));
}

public static void Play(NoteClass note)
{
byte[] sequence = new byte[3];
sequence[0] = (byte)note.ScaleChar;
sequence[1] = (byte)note.LengthChar;
sequence[2] = (byte)note.NoteChar;
LCD_PORT.Write(sequence, 0, 3);
}
public static void Play(NoteClass[] notes)
{
int currentScale = 0;
int currentLength = 0;
int count = 0;
if (notes != null && notes.Length > 0)
{
byte[] sequence = new byte[notes.Length * 3];
foreach (NoteClass note in notes)
{
if (note.ScaleChar != currentScale)
{
currentScale = note.ScaleChar;
sequence[count++] = (byte)currentScale;
}
if (note.LengthChar != currentLength)
{
currentLength = note.LengthChar;
sequence[count++] = (byte)currentLength;
}
sequence[count++] = (byte)note.NoteChar;
}
LCD_PORT.Write(sequence, 0, count);
}
}

public static byte[] CharsToBytes(char[] Input)
{
byte[] ReturnValue = new byte[Input.Length];

for (int Counter = 0; Counter < Input.Length; ++Counter)
{
ReturnValue[Counter] = (byte)Input[Counter];
}
return ReturnValue;
}

}
public class NoteClass
{
//Helper constants
public const int A = 0;
public const int ASharp = 1;
public const int B = 2;
public const int C = 3;
public const int CSharp = 4;
public const int D = 5;
public const int DSharp = 6;
public const int E = 7;
public const int F = 8;
public const int FSharp = 9;
public const int G = 10;
public const int GSharp = 11;
public const int Rest = 12;

public const int SixtyQuarter = (int)LCD_COMMAND_CHARS.NoteLength_1_64;
public const int ThirtySecond = (int)LCD_COMMAND_CHARS.NoteLength_1_32;
public const int Sixteenth = (int)LCD_COMMAND_CHARS.NoteLength_1_16;
public const int Eighth = (int)LCD_COMMAND_CHARS.NoteLength_1_8;
public const int Quarter = (int)LCD_COMMAND_CHARS.NoteLength_1_4;
public const int Half = (int)LCD_COMMAND_CHARS.NoteLength_1_2;
public const int Whole = (int)LCD_COMMAND_CHARS.NoteLength_Whole;

private int _scale = 5;
private int _note = A;
private int _length = Quarter;

public int Scale
{
get
{
return _scale;
}
set
{
if (value >= 3 && value <= 7)
{
_scale = value;
}
}
}
public int ScaleChar
{
get
{
return ((int)LCD_COMMAND_CHARS.NoteScale_3 – 3) + _scale;
}
}
public int Note
{
get
{
return _note;
}
set
{
if (value >= A && value <= Rest)
{
_note = value;
}
}
}
public int NoteChar
{
get
{
return (int)LCD_COMMAND_CHARS.Note_A + _note;
}
}
public int Length
{
get
{
return _length;
}
set
{
if (value >= SixtyQuarter && value <= Whole)
{
_length = value;
}
}
}
public int LengthChar
{
get
{
return _length;
}
}

public NoteClass(int scale, int note, int length)
{
Scale = scale;
Note = note;
Length = length;
}
}

Una clase para controlar los pulsadores

public static class Utility
{
public static string PadLeft(string val, int maxlen, string padchar)
{
string newval = val;
while (newval.Length < maxlen)
{
newval = padchar + newval;
}
return newval;
}
public static string PadRight(string val, int maxlen, string padchar)
{
string newval = val;
while (newval.Length < maxlen)
{
newval += padchar;
}
return newval;
}
}

Y por último la clase principal:

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoPlus;

namespace DoorManager
{
public enum LightModes { Auto, ManualOn, ManualOff }

public class Program
{
#region User Settings & Constants
public static Cpu.Pin DoorSensorPin = Pins.GPIO_PIN_D11; //Magnetic switch to monitor door open/close state
public static Cpu.Pin LEDPin = Pins.GPIO_PIN_D13; //Status indicator (blinks if error or override on)
public static Cpu.Pin LightPin = Pins.GPIO_PIN_D12; //Connection to high voltage relay to control room light
public static Cpu.Pin Button1Pin = Pins.GPIO_PIN_D7; //Manually turns light on/off
public static Cpu.Pin Button2Pin = Pins.GPIO_PIN_D6; //Returns light control to automatic
public static Cpu.Pin Button3Pin = Pins.GPIO_PIN_D5; //Display error messages
public static Cpu.Pin Button4Pin = Pins.GPIO_PIN_D4; //Toggles door sensor (when off, no alerts are created)
public const int InitialDoorOpenAlertDelay = 30; //in minutes
public const int OngoingDoorOpenSoundAlertDelay = 1; //in minutes
public const int OngoingDoorOpenMessageAlertDelay = 30; //in minutes
public const int LCDOffDelay = 10; //in seconds
public const string AlertWebService = “http://192.168.1.2/WS/SendAlert.aspx?a=Door+Manager&e=Door+Opened&#8221;;
#endregion

#region Fields
public static string LastError = “”;
public static InterruptPort DoorSensor;
public static OutputPort LED;
public static OutputPort Light;
public static InterruptPort Button1;
public static InterruptPort Button2;
public static InterruptPort Button3;
public static InterruptPort Button4;
private static bool IsDoorSensorProcessing = false;
private static bool IsDoorSensorIgnored = false;
public static bool IsDoorOpen = false;
private static bool _LightState = false;
public static bool initializing = true;
public static bool IgnoreButtons = true;
public static bool IgnoreAlerts = false;
public static bool AlertScheduled = false;
public static Timer DoorTimer = new Timer(new TimerCallback(DoorTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer LCDTimer = new Timer(new TimerCallback(LCDTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer LEDTimer = new Timer(new TimerCallback(LEDTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer ButtonTimer = new Timer(new TimerCallback(ButtonTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer SendAlertTimer = new Timer(new TimerCallback(SendAlertTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static Timer DoorCloseTimer = new Timer(new TimerCallback(DoorCloseTimerHandler), null, Timeout.Infinite, Timeout.Infinite);
public static int CurrentMessageAlertDelayTimeout = 0;
public static int CurrentSoundAlertDelayTimeout = 0;
public static int CurrentAlertDelayTime = 0;
public static int CurrentLCDDelayTime = 0;
public static LightModes LightMode = LightModes.Auto;
private static int _LEDBlinkCount = 0;
public static bool _LEDBlink = false;

static NoteClass[] initTune = {
new NoteClass(5,NoteClass.C, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.D, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.E, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.F, NoteClass.Sixteenth),
new NoteClass(5,NoteClass.G, NoteClass.Sixteenth),
new NoteClass(6,NoteClass.A, NoteClass.Sixteenth),
new NoteClass(6,NoteClass.B, NoteClass.Sixteenth),
new NoteClass(6,NoteClass.C, NoteClass.Sixteenth)
};
#endregion

#region Properties
public static bool LEDBlink
{
set
{
if (value)
_LEDBlinkCount++;
else
_LEDBlinkCount–;
if (_LEDBlinkCount > 0 && !_LEDBlink)
{
_LEDBlink = true;
LEDTimer.Change(250, Timeout.Infinite); //start timer
}
else if (_LEDBlinkCount == 0 && _LEDBlink)
{
LEDTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
_LEDBlink = false;
LED.Write(false);
}
}
}
#endregion

#region Program Start
public static void Main()
{
Initialize();
ShowDoorSensorState();

Thread.Sleep(Timeout.Infinite); //keep running forever
}
#endregion

#region Methods
static void IgnoreButton()
{
IgnoreButtons = true;
ButtonTimer.Change(500, Timeout.Infinite); //restart timer
}

public static bool SetLightState()
{
bool expectedState = IsDoorOpen;
switch (LightMode)
{
case LightModes.ManualOn:
expectedState = true;
break;
case LightModes.ManualOff:
expectedState = false;
break;
}
if (expectedState != _LightState)
{
_LightState = expectedState;
Light.Write(expectedState);
}
return _LightState;
}

public static void SetIgnoreDoorSensor(bool ignore)
{
if (ignore != IsDoorSensorIgnored)
{
IsDoorSensorIgnored = ignore;
if (ignore)
{
LEDBlink = true;
//stop door sensor
DoorTimer.Change(Timeout.Infinite, Timeout.Infinite);
ParallaxLCD.LCD = true;
ParallaxLCD.Print(“Door Sensor\rDisabled”);
SetLCDOffTimer();
}
else
{
LEDBlink = false;
ParallaxLCD.LCD = true;
ParallaxLCD.Print(“Door Sensor\rEnabled”);
Thread.Sleep(2000);
//Check door
ShowDoorSensorState();
}
}
}

static void ShowDoorSensorState()
{
if (IsDoorSensorIgnored)
return;
ParallaxLCD.LCD = true; //ensure LCD is on
ParallaxLCD.Print(“Door ” + (IsDoorOpen ? “Open” : “Closed”));
if (IsDoorOpen)
{
//start door timer
CurrentSoundAlertDelayTimeout = InitialDoorOpenAlertDelay * 60 * 1000; //convert minutes to milliseconds
CurrentAlertDelayTime = 0;
DoorTimer.Change(0, Timeout.Infinite);
}
else
{
//clear door timer
DoorTimer.Change(Timeout.Infinite, Timeout.Infinite);
//set LCD timer
SetLCDOffTimer();
}
SetLightState();
}

static void SetLCDOffTimer()
{
CurrentLCDDelayTime = LCDOffDelay * 1000;
LCDTimer.Change(1000, Timeout.Infinite);
}

static void Initialize()
{
ParallaxLCD.StartSerial();
ParallaxLCD.LCD = true;
ParallaxLCD.ClearLCD();
Thread.Sleep(1000);
ParallaxLCD.Print(“Initializing…”);
ParallaxLCD.Beep();
Thread.Sleep(1000);

//set LED
LED = new OutputPort(LEDPin, false);
LEDBlink = true;

//setup door sensor
DoorSensor = new InterruptPort(DoorSensorPin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
DoorSensor.OnInterrupt += new NativeEventHandler(DoorSensor_OnInterrupt);
IsDoorOpen = DoorSensor.Read();

//setup light control
Light = new OutputPort(LightPin, false);
Light.Write(_LightState);

//setup buttons
Button1 = new InterruptPort(Button1Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button1.OnInterrupt += new NativeEventHandler(Button1_OnInterrupt);
Button2 = new InterruptPort(Button2Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button2.OnInterrupt += new NativeEventHandler(Button2_OnInterrupt);
Button3 = new InterruptPort(Button3Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button3.OnInterrupt += new NativeEventHandler(Button3_OnInterrupt);
Button4 = new InterruptPort(Button4Pin, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
Button4.OnInterrupt += new NativeEventHandler(Button4_OnInterrupt);

//setup network
Network.InitNetwork();

Thread.Sleep(5000);

ParallaxLCD.Print(“Ready”);
ParallaxLCD.Play(initTune);

Thread.Sleep(2000);

LEDBlink = false;

initializing = false;
IgnoreButtons = false;
}
#endregion

#region Timer Handlers
static void DoorCloseTimerHandler(object sender)
{
//this timer turns off sending alerts for a period of time after the door has been closed; this is another “bounce” preventative measure
DoorCloseTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
IgnoreAlerts = false;
}

static void SendAlertTimerHandler(object sender)
{
//performing this in a timer ensures switch “bounce” doesn’t send multiple alerts
SendAlertTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
Network.SendAlert();
AlertScheduled = false;
}

static void ButtonTimerHandler(object sender)
{
//this routine is to delay reaction to button presses to eliminate “bounce” and false presses
ButtonTimer.Change(Timeout.Infinite, Timeout.Infinite); //cancel timer
IgnoreButtons = false;
}

static void LEDTimerHandler(object sender)
{
if (_LEDBlink)
{
LED.Write(!LED.Read());
LEDTimer.Change(250, Timeout.Infinite); //restart timer
}
else
{
LED.Write(false);
}
}

static void LCDTimerHandler(object sender)
{
if (!IsDoorOpen || IsDoorSensorIgnored)
{
CurrentLCDDelayTime -= 1000;
if (CurrentLCDDelayTime <= 0)
{
CurrentLCDDelayTime = 0;
ParallaxLCD.LCD = false; //turn off LCD
//clear LCD timer
LCDTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
else
{
LCDTimer.Change(1000, Timeout.Infinite);
}
}
else
{
//clear LCD timer
LCDTimer.Change(Timeout.Infinite, Timeout.Infinite);
}
}

static void DoorTimerHandler(object sender)
{
if (IsDoorOpen && !IsDoorSensorIgnored)
{
if (CurrentSoundAlertDelayTimeout > 0)
{
CurrentSoundAlertDelayTimeout -= CurrentAlertDelayTime;
}
if (CurrentMessageAlertDelayTimeout > 0)
{
CurrentMessageAlertDelayTimeout -= CurrentAlertDelayTime;
}
if (CurrentMessageAlertDelayTimeout <= 0)
{
//alert
SendAlertTimer.Change(5000, Timeout.Infinite); //send alert after 5 seconds
//restart delay
CurrentMessageAlertDelayTimeout = OngoingDoorOpenMessageAlertDelay * 60 * 1000; //convert minutes to milliseconds
}
if (CurrentSoundAlertDelayTimeout > 0)
{
int mins = CurrentSoundAlertDelayTimeout / 60000;
int secs = (CurrentSoundAlertDelayTimeout – (mins * 60000)) / 1000;
ParallaxLCD.Print(“Door Open\rAlert in ” + (mins > 1 ? mins.ToString() + ” min” : secs.ToString() + ” sec”));
if (mins > 1)
{
CurrentAlertDelayTime = 60000;
}
else
{
CurrentAlertDelayTime = 1000;
}
}
else
{
//alert
ParallaxLCD.Play(new NoteClass(7, NoteClass.A, NoteClass.Half));
//restart delay
CurrentSoundAlertDelayTimeout = OngoingDoorOpenSoundAlertDelay * 60 * 1000; //convert minutes to milliseconds
CurrentAlertDelayTime = 0;
}
DoorTimer.Change(CurrentAlertDelayTime, Timeout.Infinite);
}
}
#endregion

#region Event Handlers
static void DoorSensor_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing || IsDoorSensorProcessing)
return;
IsDoorSensorProcessing = true;
//magnetic switch wired to normally open / onboard switch normally high
//therefore when the door is closed (magnetic switch open) the onboard switch (normally high) is on
IsDoorOpen = (data2 == 1);
if (IsDoorOpen && !IgnoreAlerts)
{
AlertScheduled = true;
SendAlertTimer.Change(5000, Timeout.Infinite); //send alert after 5 seconds
}
else if (!IsDoorOpen && !AlertScheduled)
{
IgnoreAlerts = true;
DoorCloseTimer.Change(5000, Timeout.Infinite); //prevent alerts for 5 seconds
}
ShowDoorSensorState();
IsDoorSensorProcessing = false;
}

/// <summary>
/// Button 1 turns the light on/off manually.
/// </summary>
static void Button1_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons)
{
IgnoreButtons = true;
ParallaxLCD.Acknowledge();
LightModes oldMode = LightMode;
if (_LightState)
LightMode = LightModes.ManualOff;
else
LightMode = LightModes.ManualOn;
SetLightState();
//if we’re moving off auto mode start the led blinking for awareness
if (oldMode == LightModes.Auto)
LEDBlink = true;
IgnoreButton();
}
}

/// <summary>
/// Button 2 sets the light back to automatic (door sensor controlled).
/// </summary>
static void Button2_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons)
{
IgnoreButtons = true;
if (LightMode != LightModes.Auto)
{
ParallaxLCD.Acknowledge();
LightMode = LightModes.Auto;
SetLightState();
LEDBlink = false;
}
IgnoreButton();
}
}

static void Button3_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons && (!IsDoorOpen || IsDoorSensorIgnored))
{
IgnoreButtons = true;
ParallaxLCD.Acknowledge();
if (LastError != null && LastError.Length > 0)
{
string msg = LastError;
//show error in byte size pieces
ParallaxLCD.LCD = true;
while (msg.Length > 0)
{
if (msg.Length > 32)
{
ParallaxLCD.Print(msg.Substring(0,32));
msg = msg.Substring(32);
}
else
{
ParallaxLCD.Print(msg);
msg = “”;
}
Thread.Sleep(5000);
}
ParallaxLCD.Acknowledge();
SetLCDOffTimer();
}
else
{
ParallaxLCD.LCD = true;
ParallaxLCD.Print(“No Errors”);
SetLCDOffTimer();
}
IgnoreButton();
}
}

/// <summary>
/// Button 4 disables/re-enables the door sensor.
/// </summary>
static void Button4_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (initializing)
return;
if (!IgnoreButtons)
{
IgnoreButtons = true;
ParallaxLCD.Acknowledge();
SetIgnoreDoorSensor(!IsDoorSensorIgnored);
IgnoreButton();
}
}
#endregion
}
}

Lista de componentes :

  • 2 LED, 4 interruptores momentáneos, tornillos diverso, caja de proyecto
  • Opcional: Kit Protoshield para Ardiono – $ 9.90  http://www.seeedstud…uino-p-318.html
  • Este kit incluye una placa de circuito de prototipos, conectores, resistencias, los LED (no caja montable en proyecto), conmutadores (no caja montable proyecto) y otras piezas misceláneas que puede ayudar a un iniciado a empezar.

Fuente  aqui

Domótica con Netduino y Kinect


Introducción

Hay un montón de mediocre  tecnología sobre el tema de la domotica  en el mercado siendo ademas  los productos  demasiado caros, así que el autor Dan Thyer  decidió construir su  propio sistema domótico. El autor empezó con el microcontrolador Arduino, pero el código rápidamente se convirtió en difícil de mantener porque la programación en Arduino   no esta orientada a objetos,  no puede  hacer multithreading  asi como tampoco permite depuración real con puntos de interrupción tal como se puede hacer con Netduino .Refactorizó entones  su  código para C # y  NET Micro Framework eligiendo  Netduino plus, http://www.netduino.com/netduinoplus/specs.htm , para el microcontrolador  (la versión Plus incluye  un adaptador de Ethernet para la comunicación de red).

Netduino controlado Pistola de agua

El primer proyecto  era una pistola de agua servo controlada para la piscina. El código  para la Netduino controla los servos para rociar el arma de fuego en diferentes patrones en la piscina. Entonces construyo una interfaz de Windows Phone 7 para apuntar los servos a la posición de la pantalla donde se toca. El  autor solía usar IIS Smooth Streaming para transmitir vídeo en el teléfono así que intento apuntar de forma remota a los niños en la piscina desde cualquier lugar. Así consiguió  resultados mixtos con la pieza de video  pero el autor reconoce  que necesitaría perfeccionar lo reduciendo el tiempo de almacenamiento en búfer para que sea más tiempo real.

NetduinoHomeAutomation/LogicalDan_002.jpg

Jardín

El próximo proyecto era controlar el riego del jardín habilitando los  horarios a través  de código los tiempos para regar el jardín y controlar la duración del riego.

NetduinoHomeAutomation/LogicalDan_004.jpg

Kinect

Muchas personas usan  para a hacer proyectos con el Kinect de Microsoft, que tiene una rica SDK completo con los controladores, APIs y un montón de buen código de ejemplo. El Kinect tiene un montón de sensores, incluyendo una cámara RGB, un sensor de profundidad y un micrófono de múltiples matrices. Con Kinect, usted es el controlador! de modo  que el autor tuvo  la idea de usar el Kinect para el controlador de la pistola de agua en la piscina de modo que puede puede apuntar el arma apuntando a donde usted quiera para disparar. El disparador se controla doblando su otro brazo para que la mano está por encima de la articulación del codo. La conexión del Kinect al  controlador fue  muy simple debido a la rica API Kinect y porque el autor había escrito los niveles de back-end para comunicarse con el microcontrolador Netduino.

NetduinoHomeAutomation / VideoSquirtGun.JPG
Vea este vídeo de la pistola de

Reconocimiento de voz en el Kinect

Otra de las características en el Kinect es el micrófono de múltiples matrices con reconocimiento de voz de modo que se puede jugar un poco con los comandos de voz para controlar la pistola de agua y para abrir el garaje.

Vea este vídeo de Simon Says Kinect

Android Puerta de cochera

Es autor ademas   escribio   una aplicación nativa para Android para llamar a un servicio web REST (WCF) que se comunica con el Netduino para abrir el garaje.

Poniendo todo junto

La imagen siguiente muestra la comunicación entre los componentes

NetduinoHomeAutomation/LogicalDan_005.jpg

La imagen de abajo muestra los dispositivos que controla el Netduino

NetduinoHomeAutomation/LogicalDan_006.jpg

NetduinoHomeAutomation / VideoAll.JPG
Vea este vídeo para ver cómo se organiza todo esto

Comunicación Ethernet

La comunicación Ethernet con el Netduino fue la parte más difícil del proyecto.

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
using Microsoft.SPOT.Net.NetworkInformation;
using System.Threading;

namespace Netduino.Controller
{
    public delegate void MessageEventHandler(string Message);

    class EthernetCommunication
    {
        #region Private Variables
        private string _hostAddress = null;
        private int _port = 80;
        private string _netduinoStaticIPAddress = null;
        private string _subnetMask = null;
        private string _gatewayAddress = null;
        private Thread _listeningThread;
        private Socket _clientSocket = null;
        private static EthernetCommunication _ethernetCommunication;
        #endregion

        #region Constructors
        //This keeps other classes from creating an instance
        private EthernetCommunication()
        {
        }
        #endregion

        #region Public Properties
        public string HostAddress
        {
            set { _hostAddress = value; }
            get { return _hostAddress; }
        }
        public int Port
        {
            set { _port = value; }
            get { return _port; }
        }
        public string NetduinoStaticIPAddress
        {
            set 
            { 
                _netduinoStaticIPAddress = value;
                SetNetduinoStaticIPConfiguration();
            }
            get { return _netduinoStaticIPAddress; }
        }
        public string SubnetMask
        {
            set
            {
                _subnetMask = value;
                SetNetduinoStaticIPConfiguration();
            }
            get { return _subnetMask; }
        }
        public string GatewayAddress
        {
            set 
            {
                _gatewayAddress = value;
                SetNetduinoStaticIPConfiguration();
            }
            get { return _gatewayAddress; }
        }
        #endregion

        #region Events
        public static event MessageEventHandler EventHandlerMessageReceived;
        #endregion

        #region Public Methods

        private void StartListening()
        {
            _listeningThread = new Thread(new ThreadStart(ReceiveSocketsInListeningThread));
            _listeningThread.Start();
        }

        private void InitializeConfiguration()
        {
            if (_netduinoStaticIPAddress == null)
                throw new Exception("The netduino Static IP Address nust be set!");

            if (_subnetMask == null)
                throw new Exception("The Subnet Mask must be set!");

            if (_gatewayAddress == null)
                throw new Exception("The Gateway address must be set.");

            SetNetduinoStaticIPConfiguration();
            NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces()[0];

            if (_netduinoStaticIPAddress != networkInterface.IPAddress)
                throw new Exception("Problem setting the static IP.");

            if (_subnetMask != networkInterface.SubnetMask)
                throw new Exception("Problem setting the subnet mask.");

            if (_gatewayAddress != networkInterface.GatewayAddress)
                throw new Exception("Problem setting the gateway address.");
        }
        #endregion

        #region Public Static Methods
        public static EthernetCommunication GetInstance()
        {
            if (_ethernetCommunication == null)
            {
                _ethernetCommunication = new EthernetCommunication();
                _ethernetCommunication.HostAddress = Config.HostAddress;
                _ethernetCommunication.Port = Config.Port;
                _ethernetCommunication.NetduinoStaticIPAddress = Config.NetduinoStaticIPAddress;
                _ethernetCommunication.SubnetMask = Config.SubnetMask;
                _ethernetCommunication.GatewayAddress = Config.GatewayAddress;
                _ethernetCommunication.InitializeConfiguration();
                _ethernetCommunication.StartListening();
            }
            return _ethernetCommunication;
        }

        public static void SendMessage(string message)
        {
            GetInstance().SendEthernetMessage(message);
        }
        #endregion

        #region Private Methods
        private bool IsSocketConnected(Socket socket)
        {
            bool connectionNotClosedResetOrTerminated = !socket.Poll(1000, SelectMode.SelectRead);
            bool socketHasDataAvailableToRead = (socket.Available != 0);
            return (connectionNotClosedResetOrTerminated || socketHasDataAvailableToRead);
        }

        private void ReceiveSocketsInListeningThread()
        {
            string receiveMessage = "";
            bool exitProgram = false;

            using (System.Net.Sockets.Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
            {
                socket.Bind(new IPEndPoint(IPAddress.Any, _port));
                socket.Listen(10);

                while (!exitProgram)
                {
                    Debug.Print("Waiting for connection...");
                    _clientSocket = socket.Accept();  //This call is "blocking" and will will wait for a connection, which also means the thread hangs around
                    Debug.Print( "Connection Accepted!");

                    using (_clientSocket)
                    {
                        while (IsSocketConnected(_clientSocket))
                        {
                            int availablebytes = _clientSocket.Available;
                            byte[] buffer = new byte[availablebytes];
                            _clientSocket.Receive(buffer);
                            if (buffer.Length > 0)
                            {
                                receiveMessage = new string(Encoding.UTF8.GetChars(buffer));
                                RaiseMessageReceivedEvent(receiveMessage);
                                if (receiveMessage.ToUpper() == "EXIT")
                                {
                                    exitProgram = true;
                                }
                            }

                        }
                    }
                }
            }
        }

        private void RaiseMessageReceivedEvent(string message)
        {
            // Event will be null if there are no subscribers
            if (EventHandlerMessageReceived != null)
            {
                EventHandlerMessageReceived(message);
            }
        }

        private void SetNetduinoStaticIPConfiguration()
        {
            //Exit if not all of the configuration properties are set
            if (_netduinoStaticIPAddress == null || _subnetMask == null || _gatewayAddress == null)
                return;

            NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces()[0];

            bool _ipAddressAlreadySet = _netduinoStaticIPAddress == networkInterface.IPAddress;
            bool _subnetMaskAlreadySet = _subnetMask == networkInterface.SubnetMask;
            bool _gatewayAlreadySet = _gatewayAddress == networkInterface.GatewayAddress;

            if (_ipAddressAlreadySet && _subnetMaskAlreadySet && _gatewayAlreadySet)
                return;

            // Set our IP address to a new value
            // This will be saved in the config sector of the netduino and will survive reboots 
            networkInterface.EnableStaticIP(_netduinoStaticIPAddress, _subnetMask, _gatewayAddress);
        }

        private void SendEthernetMessage(string message)
        {
            if (_hostAddress != null && _port > 0)
            {
                using (System.Net.Sockets.Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                {
                    IPHostEntry entry = Dns.GetHostEntry(_hostAddress);
                    IPAddress address = entry.AddressList[0];
                    IPEndPoint endpoint = new IPEndPoint(address, _port);

                    try
                    {
                        socket.Connect(endpoint);
                        socket.Send(Encoding.UTF8.GetBytes(message));
                        socket.Close();
                        Debug.Print(message);
                    }
                    catch (SocketException se)
                    {
                        Debug.Print("Socket Exception!  Probably no server or bad ip?");
                        Debug.Print(se.StackTrace);
                    }
                }
            }
        }
        #endregion
    }
}

Si desea ver un ejemplo de cómo hablar con una aplicación de escritorio, descargue el código fuente y  estudie  el proyecto Netduino.Desktop.Messenger.

Comunicación Servo

Los servos era divertido para programar. Yo escribí una clase servo que ajuste el ángulo y el Mínimo y Máximo grados. He añadido la propiedad invertida para invertir el ángulo porque  el autor tenia  una versión de interior de la pistola de agua que se monta en el suelo mientras la versión de exterior está montada al revés.

using System;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;

namespace Netduino.Controller
{
    public class Servo : IDisposable
    {
        #region Private Variables
        private PWM _servo;
        private bool _invertAngle = false;
        private int _degreeMin = Config.DegreeMinDefault;
        private int _degreeMax = Config.DegreeMaxDefault;
        private uint _durationMin = Config.DurationMinDefault;
        private uint _durationMax = Config.DurationMaxDefault;
        private uint _angle = Config.HomeDefaultAngle;
        private uint _period = Config.PeriodDefault;
        #endregion

        #region Constructors
        public Servo(Cpu.Pin pin)
        {
            _servo = new PWM(pin);
            _servo.SetDutyCycle(0);
        }
        #endregion

        #region Public Methods
        public void Dispose()
        {
            DisengageServo();
            _servo.Dispose();
        }

        /// <summary> 
        /// Disengage the servo.  
        /// The servo motor will stop trying to maintain an angle 
        ///  
        public void DisengageServo()
        {
            _servo.SetDutyCycle(0);
        }

        public void EngageServo()
        {
            SetPulse();
        }
        #endregion

        #region Private Methods
        private void SetPulse()
        {
            uint angle = _invertAngle ? 180 - _angle: _angle;
            uint duration = (angle) * (_durationMax - _durationMin) / 180 + _durationMin;
            _servo.SetPulse(period: _period, duration: duration);  
        }
        #endregion

        #region Public Properties
        public int Angle
        {
            set
            {
                if (value > _degreeMax)
                    value = _degreeMax;

                if (value < _degreeMin)
                    value = _degreeMin;

                if (value < 0)
                    value = 0;

                _angle = (uint)value;
                SetPulse();
            }
            get
            {
                return (int)_angle;
            }
        }

        public bool InvertAngle
        {
            set {_invertAngle = value;}
            get { return _invertAngle; }
        }

        public int DegreeMin
        {
            set {_degreeMin  = value;}
            get { return _degreeMin; }
        }

        public int DegreeMax
        {
            set { _degreeMax = value; }
            get { return _degreeMax; }
        }

        public uint durationMin
        {
            set { _durationMin = value; }
            get { return _durationMin; }
        }

        public uint durationMax
        {
            set { _durationMax = value; }
            get { return _durationMax; }
        }

        public uint period
        {
            set { _period = value; }
            get { return _period; }
        }
        #endregion
    }
}

Controlar el Jardín

El autor ademas  escribiió  una biblioteca de comandos de tiempo para el NET Micro Framework. Tenga en cuenta que el. NET Micro Framework es muy rico, pero no tiene los genéricos.

using System;
using System.Threading;
using System.Collections;
using Microsoft.SPOT;

namespace Netduino.Controller
{
    public delegate void AlarmCallback();

    class AlarmData
    {
        public int Key { get; set; }
        public ExtendedTimer ExtendedTimer { get; set; }
        public bool RemoveAfterRun { get; set; }
        public AlarmCallback Callback { get; set; }
    }

    class Time
    {
        #region Private Variables
        private static Hashtable _alarmHashtable;
        private static int _key;
        #endregion

        #region Constructors
        //This keeps other classes from creating an instance
        private Time()
        {
        }
        #endregion

        #region Public Static Methods
        public static void SetTime(int year, int month, int day, int hour,int minute, int second, int millisecond )
        {
            DateTime presentTime = new DateTime( year, month, day, hour, minute, second, millisecond);
            Microsoft.SPOT.Hardware.Utility.SetLocalTime(presentTime);
        }

        public static void RunDaily(AlarmCallback alarmCallback, int hour, int minute, int second)
        {
            DateTime alarmTime = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, hour, minute, second, 0);

            //If we already missed today then tomorrow is the first day to run
            if(alarmTime<DateTime.Now)
            {
                alarmTime = alarmTime.AddDays(1);
            }

            TimeSpan dailyTimeSpan = new TimeSpan(24, 0, 0);
            CreateAlarm(alarmCallback, alarmTime, dailyTimeSpan, false);
        }

        public static void RunOnDelay(AlarmCallback alarmCallback, int runInMilliseconds)
        {
            DateTime alarmTime = DateTime.Now.AddMilliseconds(runInMilliseconds);
            CreateAlarm(alarmCallback, alarmTime, TimeSpan.Zero, true);
        }

        public static void RunRepetitively(AlarmCallback alarmCallback, int repeatMilliseconds)
        {
            DateTime alarmTime = DateTime.Now.AddMilliseconds(repeatMilliseconds);
            TimeSpan repeatTimeSpan = new TimeSpan(0, 0, 0, 0, repeatMilliseconds);
            CreateAlarm(alarmCallback, alarmTime, repeatTimeSpan, false);
        }
        #endregion

        #region Private Methods
        private static void CreateAlarm(AlarmCallback alarmCallback, DateTime alarmTime, TimeSpan timeSpan, bool removeAfterRun)
        {
            if (_alarmHashtable == null)
                _alarmHashtable = new Hashtable();

            _key=_key+1;

            AlarmData alarmData = new AlarmData();
            alarmData.Key = _key;
            alarmData.Callback = alarmCallback;
            alarmData.ExtendedTimer = new ExtendedTimer(OnExecuteAlarm, alarmData, alarmTime, timeSpan);
            alarmData.RemoveAfterRun = removeAfterRun;

            _alarmHashtable.Add(_key, alarmData);
        }

        private static void OnExecuteAlarm(object target)
        {
            AlarmData alarmData = (AlarmData)target;

            if (alarmData.RemoveAfterRun)
                _alarmHashtable.Remove(alarmData.Key);

            alarmData.Callback.Invoke();
        }
        #endregion
    }
}

El Programa Principal. NET Micro Framework

Hay un controlador de eventos para la comunicación Ethernet que se ejecuta cuando se recibe un mensaje.

EthernetCommunication.EventHandlerMessageReceived += new MessageEventHandler(OnMessageReceived);
El método OnMessageReceived analiza el mensaje y llama a los métodos para ejecutar los comandos. El siguiente fragmento de código es sólo parcial, pero la fuente completa está disponible para su descarga aqui (necesita previamente darse de alta en en el site de  code project si no lo estaba con anterioridad)
private static void OnMessageReceived(string message)
        {
            string[] parts = message.Split(' ');
            switch(parts[0].ToUpper()) 
            {
                case "M":
                case "MOVE":
                    if (parts.Length != 3)
                    {
                        EthernetCommunication.SendMessage("The move command takes 3 arguments.");
                        break;
                    }
                    int leftRightAngle = int.Parse(parts[1]);
                    int upDownAngle = int.Parse(parts[2]);
                    _squirtGun.MoveToPosition(leftRightAngle, upDownAngle);
                    break;

                case "U":
                case "UP":
                    int upDelta = parts.Length > 1 ? int.Parse(parts[1]) : 1;
                    _squirtGun.UpDownAngle = _squirtGun.UpDownAngle + upDelta;
                    break;
Fuente aqui

Demo de alarma con 11Netduinos


Mike Linnen   ha creado un ingenioso sistema de Alarma con 11 dispositivos Netduino simulando los componentes de un sistema de seguridad para el hogar ,donde todos ellos están  conectados  entre  si   gracias a servicios en la nube alojados en Windows Azure.

Este  prototipo  fue creado como una presentación para un grupo local de usuarios .net explicándoles  los conceptos de Internet de las cosas  o M2M (machine to machine).

Todos los dispositivos de comunicación al servicio de nube van  sobre un bus de mensajes de MQTT.

El servicio en la nube es el cerebro del sistema y toma las decisiones sobre cómo el sistema reacciona a varias entradas.

Gracias a un panel de control que puede verse mediante un navegador web  se puede interactuar  con el sistema  y las  actualizaciones  se envían en tiempo real a los navegadores vía signalr.

Sobre las famosas lentillas medidoras del nivel de glucosa de Google


Usted probablemente habrá  escuchado que la diabetes es un enorme y creciente problema que afectan a una de cada 19 personas en el planeta,pero es posible que no esté familiarizado con la lucha diaria que muchas personas con diabetes se enfrentan al tratar de mantener sus niveles de azúcar en la sangre bajo control.

Sin control de azúcar en la sangre ,esto pone a las personas en situación de riesgo para una serie de complicaciones peligrosas, algunos a corto plazo y otros a largo plazo, incluyendo el daños a los ojos, los riñones y el corazón (un triste ejemplo una  madre,que una vez se desmayó por una bajada de azúcar y condujo su coche fuera de la carretera).

De hecho mucha gente que padece esta enfermedad dicen que controlar su diabetes es como tener un trabajo a tiempo parcial,pues los niveles de glucosa cambian con frecuencia con la actividad normal como el ejercicio o comer o incluso el sudorde modo que picos repentinos o gotas precipitadas son peligrosos y no es poco común, que requiere un control la vuelta al reloj.  Aunque algunas personas usan los monitores de glucosa, con un sensor de glucosa incrustado debajo de la piel, todas las personas con diabetes todavía deben pincharse el dedo y las gotas de la prueba de sangre durante el día.  Es perturbador, y es doloroso y  como resultado, muchas personas con diabetes chequean su glucosa en sangre con menos frecuencia de lo que deberían.

Con los años, muchos científicos han investigado diversos fluidos corporales-como las lágrimas-en la esperanza de encontrar una forma más fácil para la gente para realizar un seguimiento de sus niveles de glucosa. Pero como se puede imaginar, las lágrimas son difíciles de recopilar y estudiar.. En Google [x], se  han  preguntado si miniaturizando la  electrónica podrian  conseguirlo  mediante  chips y sensores tan pequeños que se ven como pedacitos de brillo, y una antena más delgadas que un cabello humano-podría ser una manera de descifrar el misterio de la glucosa lacrimógenos y medirlo con una mayor precisión.

Ahora de hecho estab  probando un lente de contacto inteligente que está construido para medir los niveles de glucosa en las lágrimas utilizando un diminuto chip inalámbrico y sensor de glucosa en miniatura que se encajan entre dos capas de material para lentes de contacto blandas.

Los  prototipos que estan probando pueden generar una lectura de una vez por segundo.

También estan investigando la posibilidad de que esto servirá como una alerta temprana para el usuario, por lo que estan explorando la integración de pequeñas luces LED que podrían iluminar indicar que los niveles de glucosa han cruzado por encima o por debajo de ciertos umbrales.  Todavía es pronto para esta tecnología, pero han  completado múltiples estudios de investigación clínica que están ayudando a refinar el prototipo y esperan que esto podría algún día conducir a una nueva forma para que las personas con diabetes para controlar su enfermedad.

De hecho estan en conversaciones con la FDA, pero aún queda mucho trabajo por hacer para convertir esta tecnología en un sistema que la gente puede usar.  No vana hacer esto por sí solo pues tienen  la intención de buscar socios que sean expertos en la oferta de productos que hay en el mercado.  Estos socios utilizarían nuestra tecnología para una lente de contacto inteligente y desarrollarían  aplicaciones que harían las mediciones disponibles para el usuario y su médico.

Desde google    dicen que  buscan proyectos  desafiantes   y en momentos en que la Federación Internacional de Diabetes (PDF) está declarando que el mundo está “perdiendo la batalla” contra la diabetes, piensan  que este proyecto merece  la pena intentarlo.

Fuente  aqui

Herramientas para construir twitter walls


A la hora de asistir a un evento, muchas veces nos encontramos con pantallas especiales dedicadas a mostrarnos lo que está sucediendo en Twitter  conocidas como Twitter walls o tweet walls, que  dependiendo del presupuesto asignado, a veces tienen detrás todo un software especialmente desarrollado para la ocasión. En el caso de los eventos más normales  como pueden ser conferencias,clases, seminarios, etc que, por desgracia  carecen de sponsors, podemos usar varias utilidades que nos permitiran proyectar un hashtag de dicho evento:

Visible Tweets

Para usar  Visible Tweets no necesitamos nada más que un hashtag y un proyector para poder trabajar con esta herramienta. Usando todos los términos de búsqueda que podemos encontrar en el buscador de Twitter, podemos crear un tweet wall en apenas unos minutos, sin demasiados problemas. Cuando ingresamos a la herramienta, nos encontraremos con una barra central donde tenemos que insertar nuestra palabra clave, y luego, nada más sentarnos a ver cómo funciona.

No es necesario crear una cuenta para poder usar Visible Tweets, y como nos podemos imaginar para proyectar un hashtag en un evento nada más tenemos que conectar un PC a un proyector o TV. No será lo más avanzado del mercado, pero ciertamente funciona. Si queremos hacer algunas limitaciones, podemos seleccionar nada más los tweets de una determinada cuenta, pero también seguir palabras claves, hashtags y más. Es una herramienta de visualización de tweets muy efectiva, ideal para aquellos que no tienen mucho presupuesto para dedicar a esta cuestión.

hashtags

Twitter Fontana

Twitter Fontana también es una herramienta muy sencilla que nos permite proyectar un hashtag en un evento sin demasiados problemas pero sí nos pedirá que iniciemos sesión con Twitter para poder comenzar a usarla.

Una vez que tenemos creada la selección de tweets, vamos a poder pausar, personalizar, y ver como presentación Esto último es muy importante dado que será lo que nos permita trabajar con un proyector o TV en un evento . Así como Visible Tweets, no necesitaremos nada adicional, y podremos configurar el estilo de transición entre diferentes tweets, el estilo en general que tendrá la presentación, y mucho más. En poco tiempo podemos tener configurado un tweet wall con los colores de una marca, por ejemplo.

Tweet Fontana

Tint

Tint es una herramienta empresarial que, además de permitirnos proyectar un hashtag en un evento, también es una solución apropiada para poder embeber todas las redes de Social Media en varios canales de marketing que pueda tener una marca. Tint es básicamente un tablero donde podemos sincronizar todas las redes sociales, y comenzar a trabajar desde allí. Además de cuentas, también se puede monitorear hashtags específicos, y esto es lo que particularmente nos interesa.

Tint cuenta con una buena cantidad de clientes de renombre, entre los que podemos mencionar a bandas como Kiss y The Lumineers, equipos como los Dallas Cowboys, y marcas como Sony y Bacardi. Claramente, para poder usar Tint tendremos que dedicar parte del presupuesto del evento para poder hacer esto, dado que no es una herramienta gratuita. Pero sí es una de las herramientas más poderosas, dado que además de proyectar un hashtag en un evento nos permite aprovechar otros canales como Facebook y YouTube.

 

TweetBeam

TweetBeam es una herramienta específicas para poder proyectar un hashtag permitiendo  crear un tweet wall rápidamente y con la sola asistencia de un proyector o TV. TweetBeam es, en principio, una herramienta gratuita siempre y cuando esté destinada a proyectos no comerciales. Sin embargo, si nos interesa usarlo para negocios, podemos contactarnos con su equipo para recibir un presupuesto de uso.

Conectándonos con nuestra cuenta de Twitter, podemos acceder a un tablero especial donde podemos ir creando “shows” en base a eventos y ocasiones especiales, también hashtags. La actualización es automática, pero gracias a este tablero podremos trabajar en algunas cuestiones básicas de edición. También puede ser interesante para conferencias y presentaciones. Entre algunos de sus clientes, se cuentan Disney y Cisco.

TweetBeam

Twijector

Twijector,  cuenta con herramientas de moderación que permiten, entre otras cosas, crear un filtro de groserías, o de palabras que no queremos que sean destacadas, así como también bloquear a los spammers. Fundamentalmente, tiene una herramienta de pre-moderación para que solamente los tweets seleccionados por nosotros aparezcan proyectados.

Twijector tiene otras funcionalidades atractivas,como por ejemplo nos permite guardar todos los tweets que se han recibido sobre un determinado evento en un archivo especial para poder accederlo en el futuro ,asi como  tambien  nos permite generar una “audiencia” con todas las personas que interactuar con el hashtag del evento( para obtener algo así como una base de datos personal de los usuarios de Twitter a los que les interesa nuestra marca o evento).

Fuente  aqui

Rasberry como terminal ligero


Tener un PC en casa para navegar solo a Internet o usar aplicaciones en red no es tan difícil como antes ya que podemos disponer por menos de 40€ de un dispositivo personalizable incluso en diseño por muy poco dinero que se conectará a nuestra TV o televisor y en el cual podremos instalar un sistema operativo adaptado al uso que vayamos a hacer del mismo.

No se trata de un ordenador por supuesto muy potente pero aún así podremos instalar Linux (varias distribuciones disponibles) e incluso utilizar en el la aplicación Teamviewer para acceder a una maquina virtual con sistema operativo Windows u otro de forma remota sin tener que comprar un PC adicional.

Pero además, gracias a Inasset podremos incluso alojar pagando solo 10€ de alta, el dispositivo en el centro de datos, con una IP incluida en el precio e instalar dentro del miniPC una pequeña web (el modelo de 8GB cuesta 40€ y puede ser suficiente para una pequeña web) y todo ello sin pagar luego una cuota mensual. ¡Genial! (dispone de 1MB de linea pero que puede ampliarse a los MB que necesitemos a 1€/MB al mes adicional).

Existen para él adaptadores para incluirlos en el propio monitor o tv e incluso carcasas personalizables al gusto de cada cual incluso a medida desde 15€ para negocios siempre y cuando se pidan al menos 20 unidades. (como siempre el precio se reduce cuantas más compras…)

Fuente  aqui