Wireless communication has become a key feature in our projects nowadays and talking about wireless, the first thing that comes to my mind is Wi-Fi or BT, but handling the Wi-Fi or BT communication protocols is not an easy task and consumes a lot of MCU resources, leaving small space for coding my application. Therefore, I usually opt for an external Wi-Fi/BT module serially connected to the microcontroller in order to split the roles and gain higher freedom.
However, sometimes Wi-Fi and BT are “overkill” for some applications requiring low bitrate and short communication distance. Furthermore, using Wi-Fi or BT implies the necessity of connecting your Smartphone or device with proper authentication.
Imagine that you simply need to turn on/off an external light, or change the lamp intensity, or open an electric gate. Would it be worth to use Wi-Fi or BT?
Depending on the environment and applications, wireless communication over IR (Infrared) wavelength might come at handy. A Serial over IR, implemented with few external components (3 discrete components!), and uChip (a very small Arduino compatible board) can be the solution you were looking for!
Bill of Materials (for one Tx-Rx device):
1 x uChip
1 x IR LED: having the emission peak at 950nm
1 x TSOP-38238 (of equivalent)
1 x 1KOhm Resistor
1 x breadboard/proto board
1 x Black Plastic Tube: inner diameter the same size as the IR LED, the tube is necessary to prevent cross-talk with the TSOP receiver.
1 x Aluminum Foil (3cm x 3 cm)
1 x Tape
TIP: You can make an only-TX or only-RX device in case you need a one-direction communication by removing the unnecessary RX/TX hardware from the circuit or enable/disable the related code in the sketch.
Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.
Step 1: Wiring
Wire the components together accordingly to the schematic.
A few notes on the simple schematic. Since the TSOP-38238 allows a power supply from 2.5V to 5V and absorbs 0.45mA at most (you find the datasheet HERE), I will be powering the receiver using two pins, which will provide ground and power supply respectively. This allows turning on/off the receiver on demand and a very simple hardware wiring setup. Furthermore, in case you need a one-direction communication you can choose whether to make a (Tx/Rx)-only device by simply disable/enable the TSOP-38238.
How does the circuit work?
It is quite simple. The TSOP output pin is pulled low when the sensor detects a train of 6 pulses or more at 38KHz, on the other hand it is pulled high when there is not such a signal. Therefore, in order to transmit the serial data over IR, what the circuit does is powering the LED anode with a 38KHz PWM modulated with the TX serial signal which pulls low the LED cathode.
Consequently, on a high level of the serial TX0, the LED is not biased or biased in reverse (no pulses) and the TSOP output pin is pulled high. Transmitting a low level on the serial, the LED is powered and generates IR pulses accordingly to the applied PWM signal; therefore, the TSOP output is pulled low.
Since the transmission is direct (0->0 and 1->1) there is no need for inverters or other logic on the receiver side.
I regulate the LED optical output power by selecting the PWM duty cycle accordingly to the application. The higher the duty cycle, the higher the optical output power and therefore, the further you will transmit your message.
Keep in mind that we still need to generate pulses! Thus, you shouldn’t go above 90% duty cycle, otherwise the TSOP won’t detect the signal as pulses.
Do you need more power?
In order to increase the current, can we simply reduce the value of the 1kOhm resistor?
Maybe, just don’t be too demanding! The maximum current you get from a pin of the MCU is limited to 7mA when driving the port pin stronger than normal (PINCFG.DRVSTR = 1 and VDD > 3V) as stated in the SAMD21 datasheet.
However, the standard configuration (which is the one adopted by the Arduino IDE libraries as default) limits the current to 2mA. Therefore, using 1kOhm already gives the current limit with the default settings!
Increasing the current is not only a matter of electrical components. Briefly:
- Change the resistor (whose minimum value is limited to approximately 470Ohm -> VDD/470~7mA);
- Set the correspondingly PORT->PINCFG->DRVSTR to 1;
I will provide the code including this feature in a future update.
But remember, sinking and draining current from MCU pins close to its limits is not such a good approach. Indeed, it lowers the MCU lifetime and reliability. Therefore, I suggest keeping the normal drive strength for long-term usage.
Step 2: Programming
Load the sketch “IRSerial.ino” into uChip (or the Arduino compatible board you are using).
In case you need changing the pin generating the PWM, make sure that you are using a pin connected to a TCC timer, since this version of the code works only with TCC timers (check the “variant.c” of your board for this info). I will add the code to use also TC timers in future updates.
The code is quite simple. After setting the PIN_5 low (provides TSOP GND) and PIN_6 high (powering the TSOP), the MCU starts the PWM on PIN_1, setting the timer period and capture compare accordingly to the necessary frequency modulation (in my case it is 38KHz) and duty cycle (12.5% as default).
This is done exploiting the standard analogWrite() function on PWM pins and changing only the PER_REG (period register) and the CC (capture compare) register (the written code is simply a cut-and-paste from the wiring_analog library).
You can set the necessary frequency accordingly to the TSOP sensor changing PER_REG (which is the upper limit resetting the timer counter), while set CC proportionally to the period value to the desired percentage of duty cycle.
Next, the code sets the Serial port using the correct baud rate that is 2400bps.
Why such a low baud rate?!
The answer is in the TSOP datasheet that you can find HERE. Since the TSOP features high noise rejection filters to prevent undesired switching, it is necessary to send a train of multiple pulses in order to pull down the TSOP output pin (the number of pulses depends on the TSOP version, 6 is the typical value). Similarly, the TSOP output is pulled high after a minimum amount of time equivalent to 10 pulses or more. Consequently, in order to set the TSOP output as the modulating TX0 signal, it is necessary to set the baud rate considering the following equation:
Serial Baud < PWM_frequency/10
Using 38KHz this results in a baudrate lower than 3800bps, which means that the higher “standard” allowed baud rate is 2400pbs, as previously anticipated.
Do you want to increase the baud rate? There are two options.
The easiest option is changing the TSOP into a higher frequency version (as the TSOP38256), which would allow you to double the baud rate (4800bps)
Not enough?! Then you need to make your own optical link using a simple IR LED+photodiode and amplification circuitry. However, this solution requires a lot of coding and electronics expertise to prevent noise from affecting the transmitted data and therefore its implementation is not easy at all! However, if you feel confident enough, you are more than welcome to try making your own TSOP system! :)
Finally, I set the SerialUSB port (2400bps) which I use to send and receive data on the serial monitor.
The loop() function includes the code necessary to passthrough data over the two serials and is copied directly from the example sketch SerialPassthrough changing only the serials names.
Step 3: Shielding IR LED
If you power up the above circuitry after loading the “IRSerial.ino” code, check the Serial Monitor on Arduino IDE and try to send a string.
You will probably see that uChip is receiving exactly what it is transmitting!
There is a cross-talk in the circuitry due to optical communication between the IR LED and the TSOP of the same device!
Here comes the hard part of this project, preventing cross-talk! The loop must be broken to make bidirectional Serial communication over IR.
How do we break the loop?
First option, you lower the PWM duty cycle, thus lowering the optical power output of the LED. However, this approach also reduces the distance over which you get a reliable serial IR channel.
The second option is shielding the IR LED, thus making a directional IR “beam”. It is a matter of try and error; at last, using a piece of black pneumatic air hose wrapped into aluminum foil and tape (providing electrical insulation) I managed to break the cross talk. Putting the transmitting IR LED inside the tube prevents communication between the TX and RX of the same device.
Look at the picture to see my solution, but feel free to try other methods and/or to suggest yours! There is no absolute solution to this issue (unless you need a simple one-direction channel) and you probably need to tune the circuitry layout, PWM duty cycle and IR shield accordingly to your needs.
Once you break the cross talk, you can verify that your device is still working by creating a loop on the device Tx-Rx exploiting the reflection of the IR wavelength on IR reflective surfaces.
Step 4: Communicate!
That is all!
Your serial over IR device is ready to communicate, use them to send data over IR, turn on/off anything you like or check the status of a sensor that you are secretly hiding!
The distance upon which the communication is reliable is not as much as for a WiFi or BT device. However, it is directional (depending on the LED aperture and the implemented IR shielding system), which can be very useful in some applications!
Soon I will upload a video where you can see few examples of the applications I made. Enjoy!