Softserial (base on digital pins) + IR

Is there anyone who tried to do the following experiment?

Based on the IR library by Mikal Hart (http://sundial.org/arduino/index.php/newsoftserial/)

And serial to IR converter (like this Build a PC to IR Interface - the CIR-II)

Would it be possible to build an IR serial using 2 digital pin, a high efficient IR LED and an IR detector?

I may give it a try ...

Cheers~

In theory it should work. In reality there seems to be lots of sources of IR 'noise' in the real world that could limit range and reliability of such a direct serial IR data link. It's worth experimenting with.

What is mostly used in the real world of IR remote links is to send a serial data stream but modulating it onto a 38khz 'carrier' frequency. Then using standard 38khz IR demodulator modules as shown in the below link.

This demodulator has discrimination circuitry and automatic gain controls that filter random IR noise sources and bad effects from direct sunlight, etc. However the 38khz carrier would place a limit on how high a serial baud rate you could run through it. Most likely 1200 or 2400 baud but only experimentation would prove out the max baud rate that could be used.

Lefty

Thanks, will try it out and report~

Oh, btw, how to send a serial data stream and modulate it onto a 38Khz 'carrier' frequency?

Opps, simple googling should solve the case...

Oh, btw, how to send a serial data stream and modulate it onto a 38Khz 'carrier' frequency?

Well it can be done by ANDing a 38,000hz square wave (maybe from a 555 timer chip) with the serial transmit output pin.

A possible minimum component solution (it would depend on the current requrement of the IR emitter) would be to wire the cathode of the emitter to the serial output pin of the ARduino the other end of the emitter to a series current limiting resistor and the other end of the resistor to a Arduino output pin that is programmed to output a continous 38,000 square wave. You have to size the resistor such that the current is limited to 40ma or less.

Lefty

A possible minimum component solution (it would depend on the current requrement of the IR emitter) would be to wire the cathode of the emitter to the serial output pin of the ARduino the other end of the emitter to a series current limiting resistor and the other end of the resistor to a Arduino output pin that is programmed to output a continous 38,000 square wave. You have to size the resistor such that the current is limited to 40ma or less.

this works! :smiley:
check this link for a demo video and setup/schematic pics: dirt cheap wireless | CHEAP, FAT and OPEN
thanks retrolefty!

code as follows:
TX

//dirt cheap wireless TX
//generates 38kHz carrier wave on pin 9 and 10
//sends data via TX every 500ms
void setup()
{
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);

  // Clear Timer on Compare Match (CTC) Mode
  bitWrite(TCCR1A, WGM10, 0);
  bitWrite(TCCR1A, WGM11, 0);
  bitWrite(TCCR1B, WGM12, 1);
  bitWrite(TCCR1B, WGM13, 0);

  // Toggle OC1A and OC1B on Compare Match.
  bitWrite(TCCR1A, COM1A0, 1);
  bitWrite(TCCR1A, COM1A1, 0);
  bitWrite(TCCR1A, COM1B0, 1);
  bitWrite(TCCR1A, COM1B1, 0);

  // No prescaling
  bitWrite(TCCR1B, CS10, 1);
  bitWrite(TCCR1B, CS11, 0);
  bitWrite(TCCR1B, CS12, 0);

  OCR1A = 210;
  OCR1B = 210;
  
  Serial.begin(2400);
}

void loop()
{
  Serial.println("testing testing testing");
  delay(500);
}

RX

//dirt cheap wireless TX
void setup()
{
  Serial.begin(2400);
  pinMode(13, OUTPUT);
}

void loop()
{
  // if incoming serial
  if (Serial.available()) {
    readSerial();
    digitalWrite(13, HIGH);
  } else {
    digitalWrite(13, LOW);
  }
  delay(10);
} 

void readSerial() {
  char val = Serial.read();
  Serial.print(val);
}

Great work with that jabstarr! My next question is, can this be done to send and receive on the same arduino so that one can have two-way communication.

Any Ideas?
-Jeremy

Hey Jeremy, I've got to agree, this is AWESOME!

As far as getting the two arduinos to talk, it should be fairly easy with the sketch he's provided!

Just upload the sketch to each arduino, and you can use the Serial.print and Serial.read commands, just as if it were a real serial connection.

I haven't experimented with back and fourth communication, but I did try the sketch between two and was amazed at how.. well.. easy and awesome it was!!

I just wish I could figure out how to calculate all the timers to produce the 38KHZ signal!

But anyways, you'll need to set your Serial.read to an integer;

int serialdata = 0;
serialdata = Serial.read();

// then simply use it to compare incoming information!
if (Serial.available() > 0) {
if (serialdata == 'testing testing testing') {
digitalWrite(ledpin, HIGH);
delay(500);
digitalWrite(ledpin, LOW);
delay(500);
}
}

You'd just need to compare information coming in to what you want, then have it send out what you need! Something like if (serialdata == 'send me data'){
Serial.print(analogValue);
}

to send the value from an analogSensor of sorts.
Keep in mind, this was all just typed up, haven't tested so, hope it works!!
I'll see if I can come up with a simple sketch for communicating between the two when I get home:D

Captain Obvious,
To compare the incoming data with what you think it should be denotes that you know what the data should be. I don't want to care about what the data is or previously know what it should be.

Here is what I did. Using the same concept as jabstarr, I made a crosstalk between two serial ports. One port is the hardware serial, the other is a NewSoftSerial (http://arduiniana.org/libraries/newsoftserial/). Works great. Each side echos what is typed locally. Below is the code:

//dirt cheap wireless TX
//generates 38kHz carrier wave on pin 9 and 10
//sends data via TX every 500ms
//Echos data sent locally
//Sends/recieves data through IR through a newsoftserial port
#include <NewSoftSerial.h>

#define rxPin 2
#define txPin 3

NewSoftSerial mySerial(rxPin, txPin);

void setup()
{
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(13,OUTPUT);

  // Clear Timer on Compare Match (CTC) Mode
  bitWrite(TCCR1A, WGM10, 0);
  bitWrite(TCCR1A, WGM11, 0);
  bitWrite(TCCR1B, WGM12, 1);
  bitWrite(TCCR1B, WGM13, 0);

  // Toggle OC1A and OC1B on Compare Match.
  bitWrite(TCCR1A, COM1A0, 1);
  bitWrite(TCCR1A, COM1A1, 0);
  bitWrite(TCCR1A, COM1B0, 1);
  bitWrite(TCCR1A, COM1B1, 0);

  // No prescaling
  bitWrite(TCCR1B, CS10, 1);
  bitWrite(TCCR1B, CS11, 0);
  bitWrite(TCCR1B, CS12, 0);

  OCR1A = 210;
  OCR1B = 210;
  
  mySerial.begin(1200);
  Serial.begin(1200);
}

void loop()
{
  //Serial.println("testing testing testing");
  if(Serial.available())
  {
    char dataIn = Serial.read();
    Serial.print(dataIn);
    mySerial.print(dataIn);
    digitalWrite(13,HIGH);
  }
  else
  {
    digitalWrite(13,LOW);
  }
  if(mySerial.available())
    Serial.print((char)mySerial.read());
  delay(10);
}

On a side note: I didn't even realize the original author had a link to the NewSoftSerial library. I found it through google. lol.

I have been trying to use jeremyvnc's code but i keep getting garbage back i set baud at 1200 on both my arduino and boarduino and the monitor.It stops when i unplug the boarduino so i know its coming from there and not just noise. I only have a usbtinyisp for programming the boarduino so it just sends

void loop()
{
      mySerial.println("testing");
}

my arduino has a 328 would that mess up the carrier wave and if so how would i fix it

Can you tell me more about the hardware you are using in terms of the IR emitter and reciever? I used an Arduino Pro Mini 8MHz with a 168. When I used radioshack parts, I got a distance of 3-4 inches for receiving and about 12 inches with sending. However, when I bought some vishay parts, I was able to easily get 3 feet with a good angle.

I don't think the code is any different for the 328.

i'm using a diecimila that i swapped out the 168 with a 328 connected though usb with a radioshack 38khz receiver (276-640) attached to pin 2 and for the transmitter i have a boarduino connected though my USBtinyISP with the Phototransistor (from radioshack 276-142) connected through a 50ohm to pin 9 and directly to Tx(pin3)

What distances have you tried? The radioshack parts have a bit of a sweet spot. If you move it too close, it won't communicate well. Same as if you move it far away. Are you getting garbage and that's it no matter the distance?

-Jeremy

its about 14in apart i have tried both closer and farther i get the same type of junk at any distance

Can you post your code? I'm assuming you get no good data?

this is on the reciever(arduino)

//dirt cheap wireless TX
//generates 38kHz carrier wave on pin 9 and 10
//sends data via TX every 500ms
//Echos data sent locally
//Sends/recieves data through IR through a newsoftserial port
#include <NewSoftSerial.h>

#define rxPin 2
#define txPin 3

NewSoftSerial mySerial(rxPin, txPin);

void setup()
{
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(13,OUTPUT);

  // Clear Timer on Compare Match (CTC) Mode
  bitWrite(TCCR1A, WGM10, 0);
  bitWrite(TCCR1A, WGM11, 0);
  bitWrite(TCCR1B, WGM12, 1);
  bitWrite(TCCR1B, WGM13, 0);

  // Toggle OC1A and OC1B on Compare Match.
  bitWrite(TCCR1A, COM1A0, 1);
  bitWrite(TCCR1A, COM1A1, 0);
  bitWrite(TCCR1A, COM1B0, 1);
  bitWrite(TCCR1A, COM1B1, 0);

  // No prescaling
  bitWrite(TCCR1B, CS10, 1);
  bitWrite(TCCR1B, CS11, 0);
  bitWrite(TCCR1B, CS12, 0);

  OCR1A = 210;
  OCR1B = 210;
  
  mySerial.begin(1200);
  Serial.begin(1200);
}

void loop()
{
  //Serial.println("testing testing testing");
  if(Serial.available())
  {
    char dataIn = Serial.read();
    Serial.print(dataIn);
    mySerial.print(dataIn);
    digitalWrite(13,HIGH);
  }
  else
  {
    digitalWrite(13,LOW);
  }
  if(mySerial.available())
    Serial.print((char)mySerial.read());
  delay(10);
}

and the transmitter (boarduino)

//dirt cheap wireless TX
//generates 38kHz carrier wave on pin 9 and 10
//sends data via TX every 500ms
//Echos data sent locally
//Sends/recieves data through IR through a newsoftserial port
#include <NewSoftSerial.h>

#define rxPin 2
#define txPin 3

NewSoftSerial mySerial(rxPin, txPin);

void setup()
{
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(13,OUTPUT);

  // Clear Timer on Compare Match (CTC) Mode
  bitWrite(TCCR1A, WGM10, 0);
  bitWrite(TCCR1A, WGM11, 0);
  bitWrite(TCCR1B, WGM12, 1);
  bitWrite(TCCR1B, WGM13, 0);

  // Toggle OC1A and OC1B on Compare Match.
  bitWrite(TCCR1A, COM1A0, 1);
  bitWrite(TCCR1A, COM1A1, 0);
  bitWrite(TCCR1A, COM1B0, 1);
  bitWrite(TCCR1A, COM1B1, 0);

  // No prescaling
  bitWrite(TCCR1B, CS10, 1);
  bitWrite(TCCR1B, CS11, 0);
  bitWrite(TCCR1B, CS12, 0);

  OCR1A = 210;
  OCR1B = 210;
  
  mySerial.begin(1200);
  Serial.begin(1200);
}

void loop()
{
  mySerial.println("testing testing testing");
//  if(Serial.available())
//  {
//    char dataIn = Serial.read();
//    Serial.print(dataIn);
//    mySerial.print(dataIn);
//    digitalWrite(13,HIGH);
//  }
//  else
//  {
//    digitalWrite(13,LOW);
//  }
//  if(mySerial.available())
//    Serial.print((char)mySerial.read());
//  delay(10);
}

i took a picture of the boards in case its a connection i messed up


the orange and green wires in the second image got to a led on 13(orange) and a button on a0 (green)
the orange on the first image goes to pin3
and this is the output im getting

i tried putting the 168 in the arduino and the 328 in the boarduino and it made no difference at this point i have no idea if its sending the data wrong or receiving it wrong but i would think that if the 328 had anything to do with it the output would have been different after reversing them

Well, if I remember right, the LED pin should be attached to the TX line (pin 0) for one leg and the other be attached to the TIMER pin (pin 9) and the Receiver be attached to pin 2 (rxpin).

Try that and let me know what happens.