IrDA Enabling a PC or Microcontroller


This all started as a spin-off project for the Twitter to PSP project.

The final setup, in which the PSP is talking to an Arduino through the IR link (using IrDA protocol)

It turns out the “easiest” way of interfacing the PSP with a microcontroller is through the IR port.

There is actually only one other “resonable” option, through the PSP Volume Remote Controller, which is based on a serial line (normal RS232 protocol, but with different voltage). But given that this requires cutting of the cable and also creating a device to shift the voltage from [0,+2.5V] (to [0, 5V] for TTL or [-12,+12V] for “normal” UART) I, from the beginning, preferred to look into the IrDA communication, which had also the advantage of one less cable hanging…:)

If every you want to go down the volume remote controller road, here’s a very good ressouce : http://nil.rpc1.org/psp/remote.html

After some unsuccessful attempts to use directly a simple IR receiver (transistor) and to time the signals received, I turned to using a proper IrDA destined IR transceiver AND an IrDA controller, able to transform IrDA signals into normal UART, that a MCU is able to understand:

IRDA vs TTL serial protocols

Components:

  1. VISHAY SEMICONDUCTOR – TFDU4300-TT1 – TRANSCEIVER MODULE, IRDA, INFRARED
  2. MICROCHIP – MCP2120-I/P – IRDA CONTROLLER, 2120, DIP14
  3. CRYSTAL, 7.3728 MHz, 18PF CL, HC49/U
  4. 2 x 18pF CAPACITORs for the crystal

The components, freshly received from Farnell (which I highly recommend for their promptness and free delivery)

And here’s the schema I used:

Diagram

Actually in the documentation, they recommend some extra resistor(s) and capacitor(s) for the TFDU4300, but it’s not mandatory (it might be in order to improve it’s effective distance, which indeed during my testing seemed to be more in the 20-30cm than 70-100cm as per their documentation…):

TFDU 4300 suggested diagram from the documentation (note the extra resistor and capacitor)

So that’s it! Except a VEEEERY painful soldering of the IR transceiver (it’s meant to be surface soldered by robots…) things are pretty simple and straight forward.

Here are the results :


RESUTS

Final version with extra capacitors and resistors. NOT really necessary, except the big resistor between VLogic and VCC which lowers the Vlogic and makes the transceiver more sensitive.


And here’s the code used to test

Arduino

Using interrupts so that the MCU can do other stuff while waiting for IrDA communication!

#include <SoftwareSerial.h>
#include <WString.h>

#define rxPin 2
#define txPin 3

#define READ_TIMEOUT 300000 //nb of clocks. ROUGHLY equivalent to 500 millisecs
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);
char mData[100];
byte mPos = 0;
//SoftwareSerial.available() doesn't work, so use this + an interrupt
volatile boolean mSerialDataAvailable = false;

void setup()  {
 // define pin modes for tx, rx, led pins:
 pinMode(rxPin, INPUT);
 pinMode(txPin, OUTPUT);
 // set the data rate for the SoftwareSerial port
 mySerial.begin(9600);

 Serial.begin(115200);

 interrupts(); //enabled by default anyway, but just to be pedantic...
 attachInterrupt(0, dataInterrupt, CHANGE); // on pin 2
}

void loop() {
 Serial.println(millis());

 if(mSerialDataAvailable){
 detachInterrupt(0);
 for(byte i=0; i<mPos; i++) mData[i] = 0;
 mPos = 0;

 // listen for new serial coming in:
 int someChar = mySerial.read(READ_TIMEOUT);
 while(someChar != '#' && someChar >= 0){
 mData[mPos] = someChar;
 mPos++;
 someChar = mySerial.read(READ_TIMEOUT);
 }

 // print out the character:
 Serial.println(mData);

 mSerialDataAvailable = false;
 attachInterrupt(0, dataInterrupt, CHANGE);
 }
}

void dataInterrupt(){
 mSerialDataAvailable = true;
}

PSP

#include <pspkernel.h>
#include <pspdebug.h>
#include <pspctrl.h>

#include <stdlib.h>
#include <unistd.h>

#include <string>
#include <sstream>
using namespace std;

/* Define the module info section */
PSP_MODULE_INFO("IRDA Example", 0, 1, 1);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER);

/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
 sceKernelExitGame();
 return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
 int cbid;

 cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
 sceKernelRegisterExitCallback(cbid);

 sceKernelSleepThreadCB();

 return 0;
}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
 int thid = 0;

 thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
 if (thid >= 0) {
 sceKernelStartThread(thid, 0, 0);
 }

 return thid;
}

/** MY CODE **/

#define printf pspDebugScreenPrintf

SceUID mSceUID;

int IR_Init( )
{
 return (mSceUID = sceIoOpen("irda0:", PSP_O_RDWR, 0));
}

void IR_Write(string data)
{
 //sceIoWrite(mSceUID, "test#", 5);

 data.append("#"); // tell the micro controller the end !
 if(sceIoWrite(mSceUID, data.c_str(), data.length()) != data.length()){
 printf("ERROR could NOT write  %s", data.c_str());
 }
}

int main(void)
{
 SceCtrlData pad;
 pspDebugScreenInit( );
 printf("\nIRDA Test Application\n");
 IR_Init( );

 string msg = "Wow: ";

 while(1){
 for (int i=0; i<255; i++)
 {
 pspDebugScreenSetXY(0,3);
 ostringstream tmpBuff;
 tmpBuff << i;
 printf("Sending  %s", (msg + tmpBuff.str()).c_str());
 IR_Write(msg + tmpBuff.str());

 sleep(1);

 // Refresh the PSP Button States
 sceCtrlReadBufferPositive(&pad, 1);
 // If Circle is pressed exit the Application
 if(pad.Buttons & PSP_CTRL_CIRCLE){
 sceKernelExitGame( );
 }
 }
 }
}

2 Responses to IrDA Enabling a PC or Microcontroller

  1. Pingback: Lightweight software UART -> custom serial « Robotics / Electronics / Physical Computing

  2. Pingback: Twitter – PSP (java) – Arduino (Peggy2) « Robotics / Electronics / Computer Science

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 57 other followers