Pines
=====
Transmisor:
VCC -> +5v
GND -> gnd
ATAD -> pin 0 del ATtiny85
Receptor:
VCC -> +5v
GND -> gnd
SIGNAL -> al pin que esta al lado de gnd
Configuracion del software:
===========================
1. Utilizar Arduino 1.0.5 (también funciona con la versión 0022)
2. Copiar a la carpeta libraries de arduino, la carpeta MANCHESTER
3. Copiar tiny (bajarlo de google drive) dentro de la carpeta hardware (ver en config de arduino, generalmente está en: C:\Documents and Settings\Administrador\Mis documentos\Arduino\hardware)
4. Debe aparecer en la lista de tarjetas del arduino esta:
ATtiny85 @ 8 Mhz (Internal oscilator; BOD disabled)
4. Cargar los siguientes sketches (el del TX en el ATiny85 y el del RX en el Arduino UNO)
Tx:
#include <MANCHESTER.h>
void setup() {
MANCHESTER.SetTxPin(0);
}
unsigned int transmit_data = 0;
void loop() {
transmit_data = 12345;
MANCHESTER.Transmit(transmit_data);
//transmit_data += 1;
delay(250);
}
Rx:
#include <MANCHESTER.h>
#define RxPin 11
void setup() {
Serial.begin(9600);
// Set digital TX pin
MANRX_SetRxPin(11);
// Prepare interrupts
MANRX_SetupReceive();
// Begin receiving data
MANRX_BeginReceive();
pinMode(0, OUTPUT);
Serial.println("OK!");
}
unsigned int last_data;
void loop() {
if (MANRX_ReceiveComplete()) {
Serial.println("Recibi!");
unsigned int data = MANRX_GetMessage();
MANRX_BeginReceive();
// Handle data...
if (data == last_data + 1) {
PINB = 1; // toggle pin 0
}
last_data = data;
Serial.println(data);
}
}
_________________________________________________________________________
Librería VirtualWire:
http://www.airspayce.com/mikem/arduino/VirtualWire/
Notas:
Cada dispositivo tiene un emisor y un receptor de IR (receptor para configurarlo, y emisor para activar los equipos). Siempre que me refiero a "Servidor", es el arduino con el ethernet shield que está conectado al Router.
Cada dispositivo debe poseer un ID único (GUID por ej)
Para configurar botones:
1. Click en botón "configurar control remoto" en pagina web. El servidor deja seteado el modo config = ON (el botón cambia el texto a "detener configuración", y si lo presiona, queda config=OFF)
2. Apunto el control remoto hacia uno de los dispositivos IR.
3. El dispositivo detecta la secuencia y al terminar consulta al servidor si está en modo config=ON. Si no está, no hace nada. Si está, envia un request al servidor, con su ID y el código y el tipo de dispositivo (el código que interpreta esto tiene que estar en el dispositivo que lee IR, usando la biblioteca IRremote).
4. El servidor redirige a la página de configuración de dispositivos.
5. En un combo se puede elegir a qué dispositivo pertenece ese código (ej TV del living)
6. Aparece un texto donde se puede escribir un nombre para la acción (ej, Subir volumen)
7. Además de estos datos, se guarda el ID del dispositivo que realizará la acción
7. Cuando el usuario guarda, el modo config queda en OFF
Desde cualquier lugar, el usuario puede acceder a la página de sus dispositivos, y presionar el botón "Subir volumen" del "TV del living". Entonces, el servidor transmite estos datos:
-Acción (ej COMANDO_IR)
-ID (para saber qué receptor debe responder)
-String con la acción (Esta es la secuencia de IR que debe enviar el dispositivo... ver como codificarlo para que no quede muy extenso)
El dispositivo, al detectar que llegó un COMANDO_IR (siempre fijandose antes si el requerimiento es para su ID), envía la secuencia por el emisor IR
A LA CAJA DEL EMISOR, PONERLE EL PLASTICO ROJO QUE EVITA LA INTERFERENCIA DE LA LUZ COMÚN.
----------------------------------------------------------------------------------------------------
Sketch:
1. Configuración del router
La única configuración que se necesita hacer en el router es que todo el tráfico que provenga de internet, se derive a la dir. ip de Arduino. En este caso se especificó que todo el tráfico proveniente de internet se derive a la ip 192.168.0.200, al puerto 93
La ip que se le especifique en arduino debe estar fuera del rango de DHCP, para ello ver en esta pantalla el rango que dispone el router, y elegir una dir. que esté fuera (en este caso elegí la 192.168.0.200)
2. Configuración del proveedor de DynDNS
Registrarse en no-ip.com
Crear un DynDNS con el nombre del host (en este caso crusso.no-ip.org) y que redirija a cualquier dir (esto lo va a manejar Arduino mediante el api de no-ip.com, por lo cual no importa ahora qué dirección asignarle)
1.ServidorTransmisor
#include <SPI.h>
#include <Ethernet.h>
#include <VirtualWire.h>
//--- PARA RF
const int led_pin = 11;
const int transmit_pin = 12;
const int receive_pin = 2;
const int transmit_en_pin = 3;
//
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //mac address
byte ip[] = { 192,168,0,200 }; //dirección ip del arduino
byte serv_dynupdate[] = {8,23,224,120}; //dynupdate.no-ip.com
boolean detener = false;
boolean actualizar = true;
boolean encendido = false;
const TIEMPO_RENOVACION_IP = 30000;
EthernetClient client;
EthernetServer server(93);
unsigned long tiempo_fin;
byte count = 1;
void setup() {
Serial.begin(9600);
Ethernet.begin(mac, ip);
tiempo_fin = millis() + TIEMPO_RENOVACION_IP;
//---- PARA RF
vw_set_tx_pin(transmit_pin);
vw_set_rx_pin(receive_pin);
vw_set_ptt_pin(transmit_en_pin);
vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2000); // Bits per sec
//----
}
void actualizar_IP()
{
actualizar = true;
detener = false;
delay(1000);
Serial.println("Conectando...");
if (client.connect(serv_dynupdate, 80)) {
Serial.println("Conexión establecida");
client.println("GET /nic/update?hostname=crusso.no-ip.org HTTP/1.0");
client.println("Host: dynupdate.no-ip.com");
client.println("Authorization: Basic Y2FybG9zLnJ1c3NvQGdtYWlsLmNvbTphYmMxMjM="); //es el mail:password de no-ip, codificado en base64
//para codificarlo: http://www.ludegljive.com/functions/Encode-string-to-base64.aspx
client.println("User-Agent: arduino_ethernet/1.0 carlos.russo@gmail.com");
client.println();
}
else
{
Serial.println("Error, no se puede conectar");
}
while (!detener)
{
if (client.available()) {
char c = client.read();
Serial.print(c);
}
if (!client.connected()) {
Serial.println();
Serial.println("Desconectado");
client.stop();
detener = true;
}
}
}
void enviar_rf(String s)
{
char msg_encender[8] = {'e','n','c','e','n', 'd', 'e', 'r'};
char msg_apagar[6] = {'a','p','a','g','a', 'r'};
if (s == "encender")
{
vw_send((uint8_t *)msg_encender, 8);
vw_wait_tx(); // Esperar hasta que la totalidad del mensaje se haya enviado.
}
if (s == "apagar")
{
vw_send((uint8_t *)msg_apagar, 6);
vw_wait_tx(); // Esperar hasta que la totalidad del mensaje se haya enviado.
}
}
void loop()
{
//for (;;);
//ojo con el tema del reset de los millis() tener en cuenta que puede estar encendido 50 dias, luego se resetea
if (millis() > tiempo_fin)
{
Serial.println("Actualizando IP");
actualizar_IP();
tiempo_fin = millis() + TIEMPO_RENOVACION_IP;
}
EthernetClient cli = server.available();
if (cli) {
Serial.println("Nuevo cliente...");
//un requerimiento http finaliza con una linea en blanco
boolean currentLineIsBlank = true;
boolean parametros_llegando = false;
String str = "";
while (cli.connected()) {
if (cli.available()) {
char c = cli.read();
Serial.write(c);
str += c;
//si se llegó al final de la línea (si se recibe un caracter de newline) y la linea es vacia, el request http finalizó, por lo cual se puede enviar la respuesta
if (c == '\n' && currentLineIsBlank) {
//standard http response header
cli.println("HTTP/1.1 200 OK");
cli.println("Content-Type: text/html");
cli.println("Connnection: close");
cli.println();
cli.println("<!DOCTYPE HTML>");
cli.println("<html>");
cli.println("<form>");
//esto puede ser util... refresca la página automáticamente cada 5 segundos...
// cli.println("<meta http-equiv=\"refresh\" content=\"5\">");
if (encendido)
{
cli.println("ENCENDIDO");
enviar_rf("encender");
}
else
{
cli.println("APAGADO");
enviar_rf("apagar");
}
cli.println("</html>");
break;
}
if (c == '\n') {
//iniciando una nueva línea...
if (str.indexOf("GET /$") >= 0)
{
str = str.substring( str.indexOf('$') + 1);
str = str.substring( 0, str.indexOf(' ') );
Serial.print("PARAMETROS: ");
Serial.println(str);
if (str == "abc=1")
encendido = true;
else if (str == "abc=2")
encendido = false;
}
str = "";
currentLineIsBlank = true;
}
else if (c != '\r') {
//hay algún caracter en la línea...
currentLineIsBlank = false;
}
}
}
//delay para darle tiempo al browser que reciba los datos
delay(1);
cli.stop();
Serial.println("Cliente desconectado.");
}
}
2. Receptor
//------- RECEPTOR ---------
#include <VirtualWire.h>
const int led_pin = 6;
const int transmit_pin = 12;
const int receive_pin = 11;
const int transmit_en_pin = 3;
String str = "";
void setup()
{
delay(1000);
Serial.begin(9600); // Debugging only
Serial.println("setup");
pinMode(2, OUTPUT);
// Initialise the IO and ISR
vw_set_tx_pin(transmit_pin);
vw_set_rx_pin(receive_pin);
vw_set_ptt_pin(transmit_en_pin);
vw_set_ptt_inverted(true); // Required for DR3100
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
int i;
digitalWrite(led_pin, HIGH); // Flash a light to show received good message
// Message with a good checksum received, print it.
Serial.print("Got: ");
str = "";
for (i = 0; i < buflen; i++)
{
Serial.print(buf[i], HEX);
str += char(buf[i]);;
Serial.print(' ');
}
Serial.println("Texto recibido: " + str);
if (str.indexOf("encender") >= 0)
{
digitalWrite(2, HIGH);
}
if (str.indexOf("apagar") >= 0)
{
digitalWrite(2, LOW);
}
}
}
3. Conexiones:
Conectar la placa Ethernet Shield al arduino (la que sirve es la que tiene el chip W5100)
Se precisan 2 arduinos, uno para el emisor y otro para el receptor.
Emisor (el que tiene tres pines)
GND -> tierra de arduino
VCC -> 3V3 de arduino (o 5v) [se pueden aplicar hasta 12v, a mayor voltaje, mayor la intensidad de la señal]
ATAD -> digital pin 12 de arduino
Receptor (el que tiene 4 pines)
GND -> tierra de arduino
VCC -> 5v de arduino
Datos (pin que esta al lado de GND) -> digital pin 11 de arduino
Emisor (el que tiene tres pines)
GND -> tierra de arduino
VCC -> 3V3 de arduino (o 5v) [se pueden aplicar hasta 12v, a mayor voltaje, mayor la intensidad de la señal]
ATAD -> digital pin 12 de arduino
Receptor (el que tiene 4 pines)
GND -> tierra de arduino
VCC -> 5v de arduino
Datos (pin que esta al lado de GND) -> digital pin 11 de arduino
Led conectado a digital pin 2 con una resistencia de 4.7K
Agregar un cable de aprox 20cm al pinhole de la antena en el transmisor (esto es imprescindible y mejora notoriamente la señal)
00. Forma de acceso para realizar el test
Ingresar a un browser (en la LAN o en internet, con un celular, etc), a esta dirección:
Para encender el led:
http://crusso.no-ip.org:93/$abc=1
Para apagar el led:
http://crusso.no-ip.org:93/$abc=2
http://crusso.no-ip.org:93/$abc=2
00. Tips
1. MAC ADDRESS: Ver este link para generarla aleatoriamente:
https://nicegear.co.nz/blog/autogenerated-random-persistent-mac-address-for-arduino-ethernet/
https://nicegear.co.nz/blog/autogenerated-random-persistent-mac-address-for-arduino-ethernet/
2. Para que virtualwire funcione en la version 1.0.1 de Arduiono IDE:
en VirtualWire.h
sustituir:
#include <stdlib.h>
#include <wiring.h>
por esto:
#include <stdlib.h>
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <wiring.h>
#endif
-----------------------------------------------------
En virtualwire.cpp
reemplazar
#include "WProgram.h"
por
#include "Arduino.h"
en VirtualWire.h
sustituir:
#include <stdlib.h>
#include <wiring.h>
por esto:
#include <stdlib.h>
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <wiring.h>
#endif
-----------------------------------------------------
En virtualwire.cpp
reemplazar
#include "WProgram.h"
por
#include "Arduino.h"
00. Funcionalidad para detectar IR y enviar con arduino
Url:
http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
http://www.pjrc.com/teensy/td_libs_IRremote.html
Libreria: bajarla de github para la versión 1.0 de arduino:
https://github.com/shirriff/Arduino-IRremote
Código:
Para recibir
#include <IRremote.h>
const int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
irrecv.blink13(true);
}
void loop() {
if (irrecv.decode(&results)) {
if (results.decode_type == NEC) {
Serial.print("NEC: ");
} else if (results.decode_type == SONY) {
Serial.print("SONY: ");
} else if (results.decode_type == RC5) {
Serial.print("RC5: ");
} else if (results.decode_type == RC6) {
Serial.print("RC6: ");
} else if (results.decode_type == UNKNOWN) {
Serial.print("UNKNOWN: ");
}
Serial.println(results.value, HEX);
irrecv.resume(); // Receive the next value
}
}
Para enviar
(Este ejemplo baja y sube el volumen del televisor SONY)
#include <IRremote.h>
IRsend irsend;
void setup() {
}
void loop() {
irsend.sendSony(0xC90, 12);
delay(100);
irsend.sendSony(0xC90, 12);
delay(100);
irsend.sendSony(0xC90, 12);
delay(2000);
irsend.sendSony(0x490, 12);
delay(100);
irsend.sendSony(0x490, 12);
delay(100);
irsend.sendSony(0x490, 12);
delay(2000);
}
Para recibir y luego enviar al presionar un botón:
/*
* IRrecord: record and play back IR signals as a minimal
* An IR detector/demodulator must be connected to the input RECV_PIN.
* An IR LED must be connected to the output PWM pin 3.
* A button must be connected to the input BUTTON_PIN; this is the
* send button.
* A visible LED can be connected to STATUS_PIN to provide status.
*
* The logic is:
* If the button is pressed, send the IR code.
* If an IR code is received, record it.
*
* Version 0.11 September, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
*/
#include <IRremote.h>
int RECV_PIN = 11;
int BUTTON_PIN = 12;
int STATUS_PIN = 13;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
pinMode(BUTTON_PIN, INPUT);
pinMode(STATUS_PIN, OUTPUT);
}
// Storage for the recorded code
int codeType = -1; // The type of code
unsigned long codeValue; // The code value if not raw
unsigned int rawCodes[RAWBUF]; // The durations if raw
int codeLen; // The length of the code
int toggle = 0; // The RC5/6 toggle state
// Stores the code for later playback
// Most of this code is just logging
void storeCode(decode_results *results) {
codeType = results->decode_type;
int count = results->rawlen;
if (codeType == UNKNOWN) {
Serial.println("Received unknown code, saving as raw");
codeLen = results->rawlen - 1;
// To store raw codes:
// Drop first value (gap)
// Convert from ticks to microseconds
// Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
for (int i = 1; i <= codeLen; i++) {
if (i % 2) {
// Mark
rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS;
Serial.print(" m");
}
else {
// Space
rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS;
Serial.print(" s");
}
Serial.print(rawCodes[i - 1], DEC);
}
Serial.println("");
}
else {
if (codeType == NEC) {
Serial.print("Received NEC: ");
if (results->value == REPEAT) {
// Don't record a NEC repeat value as that's useless.
Serial.println("repeat; ignoring.");
return;
}
}
else if (codeType == SONY) {
Serial.print("Received SONY: ");
}
else if (codeType == RC5) {
Serial.print("Received RC5: ");
}
else if (codeType == RC6) {
Serial.print("Received RC6: ");
}
else {
Serial.print("Unexpected codeType ");
Serial.print(codeType, DEC);
Serial.println("");
}
Serial.println(results->value, HEX);
codeValue = results->value;
codeLen = results->bits;
}
}
void sendCode(int repeat) {
if (codeType == NEC) {
if (repeat) {
irsend.sendNEC(REPEAT, codeLen);
Serial.println("Sent NEC repeat");
}
else {
irsend.sendNEC(codeValue, codeLen);
Serial.print("Sent NEC ");
Serial.println(codeValue, HEX);
}
}
else if (codeType == SONY) {
irsend.sendSony(codeValue, codeLen);
Serial.print("Sent Sony ");
Serial.println(codeValue, HEX);
}
else if (codeType == RC5 || codeType == RC6) {
if (!repeat) {
// Flip the toggle bit for a new button press
toggle = 1 - toggle;
}
// Put the toggle bit into the code to send
codeValue = codeValue & ~(1 << (codeLen - 1));
codeValue = codeValue | (toggle << (codeLen - 1));
if (codeType == RC5) {
Serial.print("Sent RC5 ");
Serial.println(codeValue, HEX);
irsend.sendRC5(codeValue, codeLen);
}
else {
irsend.sendRC6(codeValue, codeLen);
Serial.print("Sent RC6 ");
Serial.println(codeValue, HEX);
}
}
else if (codeType == UNKNOWN /* i.e. raw */) {
// Assume 38 KHz
irsend.sendRaw(rawCodes, codeLen, 38);
Serial.println("Sent raw");
}
}
int lastButtonState;
void loop() {
// If button pressed, send the code.
int buttonState = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && buttonState == LOW) {
Serial.println("Released");
irrecv.enableIRIn(); // Re-enable receiver
}
if (buttonState) {
Serial.println("Pressed, sending");
digitalWrite(STATUS_PIN, HIGH);
sendCode(lastButtonState == buttonState);
digitalWrite(STATUS_PIN, LOW);
delay(50); // Wait a bit between retransmissions
}
else if (irrecv.decode(&results)) {
digitalWrite(STATUS_PIN, HIGH);
storeCode(&results);
irrecv.resume(); // resume receiver
digitalWrite(STATUS_PIN, LOW);
}
lastButtonState = buttonState;
}
00. Especificaciones técnicas
Módulos RF:
TX Technical Specifications:
A. Working voltage: 3V~12V
B. Working current: max≤40mA (12V), min≤9mA(3V)
C. Resonance mode: sound wave resonance (SAW)
D. Modulation mode: ASK /OOK
E. Working frequency: 315MHz-433.92MHz, customized frequency is available.
F. Transmission power: 25mW (315MHz at 12V)
G. Frequency error: +150kHz (max)
H. Velocity: ≤10Kbps
I. Self-owned codes: negative
RX Technical Specifications:
A. Working voltage: 5.0VDC +0.5V
B. Working current:≤5.5mA (5.0VDC)
C. Working principle: single chip superregeneration receiving
D. Working method: OOK/ASK
E. Working frequency: 315MHz-433.92MHz, customized frequency is available.
F. Bandwidth: 2MHz (315MHz, having result from testing at lowing the sensitivity 3dBm)
G. Sensitivity: excel –100dBm (50Ω)
H. Transmitting velocity: <9.6Kbps (at 315MHz and -95dBm)


No hay comentarios:
Publicar un comentario