WiFi IR Remote

Postings related to the second version of the WiShield

Re: WiFi IR Remote

Postby dlevans » Mon Sep 20, 2010 11:01 am

Awesome! Glad to hear it. :) I work 3-11 pm then I'm off for two days. Hope to dive head first into this stuff.
dlevans
 
Posts: 13
Joined: Wed Sep 15, 2010 10:05 pm

Re: WiFi IR Remote

Postby dlevans » Tue Sep 21, 2010 5:37 pm

I tried you receive code and keep getting an Overflowed timeIO buffer error. I'll keep messing around with it, though. I'm using a Phillips tv/remote.
dlevans
 
Posts: 13
Joined: Wed Sep 15, 2010 10:05 pm

Re: WiFi IR Remote

Postby GregEigsti » Tue Sep 21, 2010 5:59 pm

Try increasing the receive buffer size - could be that your remote is sending longer codes that min is or that you are holding the button down for a long time and generating long spurts of IR.

Greg
Check out the wiki!
uIP Stack Docs
Compatible Access Point List
WiShield user contrib branch - DNS, DHCP, AP Scanning, bug fixes, etc.
SlackLab.org - My geek projects blog.
User avatar
GregEigsti
 
Posts: 1067
Joined: Sun Aug 02, 2009 5:23 pm
Location: Sammamish WA USA (near Seattle)
  • Website

Re: WiFi IR Remote

Postby dlevans » Tue Sep 21, 2010 6:16 pm

Yeah... I was holding it down to long lol. Seems to work if you just push it. :D
dlevans
 
Posts: 13
Joined: Wed Sep 15, 2010 10:05 pm

Re: WiFi IR Remote

Postby GregEigsti » Sun Sep 26, 2010 9:59 pm

Here is my latest code - by no means a completed project - but it shows that an Arduino can drive a WiShield and also receive IR commands. So it should all be very doable on an Arduino/WiShield... I finally have all the parts needed to finish off another "long term" project (so I want to get to that) and am itching to start a different project. Bought a 2011 Subaru WRX a couple days ago and am wanting to add some instrumentation to measure its perf (Radar/Laser/RTC/GPS/Accelerometer/Gyro data logging) before and after I start adding perf parts (@265 horse now, will be taking it up over 300 with new exhaust and intake) :D Sweet car BTW and it hauls a$$ and handles like its on rails - AWD and four door so its a "family car" :lol: Adhering to the break in period got much more difficult when I pushed it and found the massive power delivered between 3.5K RPMs and 6+K RPMs... (supposed to stay below 4K for a while). Went out for a rally late night last night and damn near got in big trouble - but officer friendly was and I drove away unscathed! :o

For the code below you start the Arduino running the sketch, then start the python code - you should see that the WiShield receives data from the python code over the net. Then learn an IR command and the sketch should send some data back to the python code (which then exits). You will also want to remove the jumper which allows the LED on pin 9 to act as the WFi network connection indicator - that was the easiest tradeoff to get it all working together on the I/O challenged Duemilanove. Oh yeah, also need to get the TimerOne lib to achieve that 38khz PWM (well I am anyway). The sketch is pretty messy but as I said this, initially, is just a proof of concept for me.

Python code that interacts with the WiShield (from a PC/Mac/Linux machine)
Code: Select all
#!/usr/bin/python
import sys
from socket import *
serverHost = '192.168.1.18'         # servername is localhost
serverPort = 8456                   # use arbitrary port > 1024
s = socket(AF_INET, SOCK_STREAM)    # create a TCP socket
s.connect((serverHost, serverPort)) # connect to server on the port
s.send('Hello world')               # send the data
data = s.recv(1024)                 # receive up to 1K bytes
print data


Sketch
Code: Select all

#include <TimerOne.h>
#include <WiShield.h>
extern "C" {
   #include "uip.h"
}

// ----------------------------------------------------------------------------
// --
// --  Wireless configuration parameters
// --
unsigned char local_ip[]       = {192,168,1,18};  // IP address of WiShield
unsigned char gateway_ip[]     = {192,168,1,1};   // router or gateway IP address
unsigned char subnet_mask[]    = {255,255,255,0}; // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"SSID"};  // max 32 bytes
unsigned char security_type    = 0;               // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
const prog_char security_passphrase[] PROGMEM = {"12345678"};   // max 64 characters
prog_uchar wep_keys[] PROGMEM = {
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 0
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 1
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 2
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // Key 3
};
unsigned char wireless_mode = 1; // infra - 1; adhoc - 2
unsigned char ssid_len;
unsigned char security_passphrase_len;


// ----------------------------------------------------------------------------
// --
// -- Program defines
// --
#define DEBUG_PRINT
#define INT_RECV_NUMBER  1
#define INT_RECV_PIN     3
#define PWM_CARRIER_PIN  9
#define PWM_DUTY_CYCLE   512
#define PWM_FREQ_MICROS  26
#define IR_TOGGLE_PIN    4
#define RECV_TIMEOUT     3000
#define CNT_TRANSITION   128
#define TCP_PORT         8456

// ----------------------------------------------------------------------------
// --
// -- Program shared global variables
// -- Variables used in the ISR should be marked "volatile"
// --
volatile boolean recvStarted;
volatile boolean recvInProgress;
boolean clientConnected;
boolean sendTCPData;
volatile unsigned long timeIO[CNT_TRANSITION];
volatile unsigned long timeCapture;
volatile unsigned long timeBase;
volatile unsigned char transitions;

// ----------------------------------------------------------------------------
// --
// -- IR receive ISR (Interrupt Service Routine)
// -- IMPORTANT - do as little as possible in any ISR; this ISR grabs a bit of current state data
// --  and sets the "message" variable to signal that further processing is required in loop()
// --
void IRRecvISR()
{
   int state;
   
   // Reverse HIGH/LOW as Radio Shack IR receiver 276-640 reverses
   // HIGH and LOW (for this part 0 == HIGH and 1 == LOW)
   state = !digitalRead(INT_RECV_PIN);
   
   // If recv has just begun set program state and set first transition to 0
   if(0 == transitions) {
      // If state is HIGH set high bit to 1; otherwise set high bit to 0
      //  Indicates if this was a transition HIGH or LOW
      timeIO[transitions++] = 0 + (HIGH == state ? 0x80000000 : 0);
      // Set global to indicate receive has begun
      recvStarted = true;
      recvInProgress = true;
      // Start the capture window (RECV_TIMEOUT milliseconds)
      timeCapture = millis();
   }
   // Guard against overflowing timeIO buffer
   else if(true == recvInProgress && transitions < CNT_TRANSITION) {
      // Capture the timestamp for the current transition
      // Subtract timeBase to get the length between transitions rather than timestamp
      // If state is HIGH set high bit to 1; otherwise set high bit to 0
      //  Indicates if this was a transition HIGH or LOW
      timeIO[transitions++] = (micros() - timeBase) + (HIGH == state ? 0x80000000 : 0);
   }
   else {
#ifdef DEBUG_PRINT
      // DEBUG ONLY!!! Too fat for an ISR!!!
      Serial.println("====== overflowed timeIO buffer!!! ======");
#endif // DEBUG_PRINT
      recvStarted = false;
      recvInProgress = false;
   }

   // Grab timeBase so that we can store time between transitions rather
   //  than just a timestamp
   timeBase = micros();
}

// ----------------------------------------------------------------------------
// --
// -- IR PWM generated 38 khz carrier enable/disable
// --
void enablePWMCarrier(boolean enable)
{
   if(true == enable) {
      pinMode(PWM_CARRIER_PIN, OUTPUT);
      Timer1.initialize(PWM_FREQ_MICROS);
      Timer1.pwm(PWM_CARRIER_PIN, PWM_DUTY_CYCLE);
      Timer1.detachInterrupt();
   }
   else {
      Timer1.disablePwm(PWM_CARRIER_PIN);
   }
}

// ----------------------------------------------------------------------------
// --
// -- setup() - program initialization happens here
// --
void setup()
{
#ifdef DEBUG_PRINT
   // Enable serial output for debugging
   Serial.begin(57600);
   Serial.println("setup() begin");
#endif // DEBUG_PRINT

   // Set initial program state
   recvStarted = false;
   timeBase = 0;
   transitions = 0;
   recvInProgress = false;
   clientConnected = false;
   sendTCPData = false;
   
   // Attach the IR receive interrupt with the mode of "CHANGE".  We are interested in both rising and
   //  falling changes from the IR receiver.
   pinMode(INT_RECV_PIN, INPUT);
   attachInterrupt(INT_RECV_NUMBER, IRRecvISR, CHANGE);

   // Setup the pin that turns on/off the IR LED (ANDed with the 38khz carrier)
   // TODO: should stop and start as needed...
   pinMode(IR_TOGGLE_PIN, OUTPUT);
   digitalWrite(IR_TOGGLE_PIN, HIGH);
   // digitalWrite(IR_TOGGLE_PIN, LOW);

   // Start 38khz PWM/carrier
   // TODO: should stop and start as needed...
   enablePWMCarrier(true);

   // Start the WiShield
   WiFi.init();
     
#ifdef DEBUG_PRINT
   Serial.println("setup() end");
#endif // DEBUG_PRINT
}

// ----------------------------------------------------------------------------
// --
// -- loop() - program's run loop
// --
void loop()
{
   int i;
   
   // Print out debugging statement indicating capture window has started
   if(true == recvStarted && true == recvInProgress && millis() <= (timeCapture + RECV_TIMEOUT)) {
#ifdef DEBUG_PRINT
      Serial.println("");
      Serial.println("capture window started");
#endif // DEBUG_PRINT
      recvStarted = false;
   }
   // Take action when capture window has expired
   else if(true == recvInProgress && millis() > (timeCapture + RECV_TIMEOUT)) {
#ifdef DEBUG_PRINT
      // Print some data about the recv
      Serial.println("capture window expired");     
      Serial.print("  transition count: ");     
      Serial.println(transitions, DEC);     
      for(i = 0; i < transitions; i++) {
         Serial.print("    ");
         Serial.print(i, DEC);
         Serial.print((timeIO[i] & 0x80000000) ? " HIGH for " : " LOW for ");
         // No need to print duration of last transition (nor is it captured)
         if((i + 1) != transitions) {
            Serial.print(timeIO[i + 1] & 0x7FFFFFFF, DEC);
            Serial.println(" microseconds");
         }
         else {
            Serial.println("duration");
         }
      }

      Serial.println("capture window ended");
#endif // DEBUG_PRINT
     
      // TODO: send data...
      // Send data over the connected TCP socket
      if(true == clientConnected) {
#ifdef DEBUG_PRINT
         Serial.println("sending data...");
#endif // DEBUG_PRINT
         sendTCPData = true;
      }
       
      // Reset program state
      recvInProgress = false;
      recvStarted = false;
      transitions = 0;
   }
   
   // Service the WiShield
   WiFi.run();
}


extern "C" {
   void socket_app_init(void)
   {
      uip_listen(HTONS(TCP_PORT));
   }

   void socket_app_appcall(void)
   {
      if(uip_poll()) {
         if(true == sendTCPData) {
            sendTCPData = false;
            uip_send("received IR data", 16);
         }
      }
      if(uip_newdata()) {
#ifdef DEBUG_PRINT
         Serial.print("TCP: received ");
         Serial.print(uip_datalen(), DEC);
         Serial.println(" bytes data...");
#endif // DEBUG_PRINT
      }

      else if(uip_connected()) {
#ifdef DEBUG_PRINT
         Serial.println("TCP: remote client connected...");
#endif // DEBUG_PRINT
         clientConnected = true;
      }

      else if(uip_acked()) {
#ifdef DEBUG_PRINT
         Serial.println("TCP: received ack...");
#endif // DEBUG_PRINT
      }

      else if(uip_aborted() || uip_closed() || uip_timedout()) {
#ifdef DEBUG_PRINT
         Serial.println("TCP: remote client disconnected/disconnecting...");
#endif // DEBUG_PRINT
         clientConnected = false;
      }
   }
}


Greg
Check out the wiki!
uIP Stack Docs
Compatible Access Point List
WiShield user contrib branch - DNS, DHCP, AP Scanning, bug fixes, etc.
SlackLab.org - My geek projects blog.
User avatar
GregEigsti
 
Posts: 1067
Joined: Sun Aug 02, 2009 5:23 pm
Location: Sammamish WA USA (near Seattle)
  • Website

Previous

Return to WiShield 2.0

Who is online

Users browsing this forum: No registered users and 1 guest