Use light to send binary code to reciever to rebroadcast as sound

I have the Arduino Uno and I am new to the Arduino system. This idea is for a class project I hope to guide my students through.
I am trying to create a transmitter that will flash a light to signal a binary code (on=1, off=0) to a receiver that will then retransmit that signal using a sound (low frequency= 0, high frequency =1). Ideally then I would have another receiver detect the sound and output 1s and 0s on a screen.
I'm limiting the signal to 8bits, just a single letter using ASCII. This would then be repeated for subsequent letters to send a word.
I'm not sure which aspects of this are possible with the equipment I have. Any guidance on where to start would be appreciated!

That's confusing (to me). If a 0 is low frequency, and 1 is a high frequency, what are the other 7-bits for? And what does ASCII have to do with it?

It almost sounds like you're making a MODEM, which uses audio signals to send digital data over an analog phone line. But your transmission medium is digital light, not analog "sound".

If you are transmitting 8-bits at time as serial data it's "simply" a matter of sending the bits (usually packaged as bytes) using an optical connection in place of a normal wired connection.

To follow your description. With the light off, which it will normally be off, make the receiving device send a CONSTANT tone for zero. Is that what you mean? Then with a light on, make a different tone. So the low tone will start when you power up the receiver and wait to receive a flash of light. You only need a common flashlight for the sender, not something complicated!

Hello jhenry2

Welcome to the best Arduino forum ever.

Take a search engine of your choice and ask the WWW for "Morse code +arduino".

Then understand that an Arduino Uno only has enough memory to hold at the most 3 seconds of sound even with 8 bit sound.

This video is a project from my book, it shows the sort of quality you can get with two words, "yes" and "no". It requires a resistor and capacitor on the output to generate something you can send to an audio amplifier.

In electronics a "word" is a multi byte variable. I am assuming you want to say the word.

Using light is tricky because of ambient light interference. Normally you get round this by using a modulated light, that is, rapidly turning on and off at between 30 to 38 KHz it is then turned back into a signal by a modulated receiver.

The problem is that all this uses Infra-red light so you will not see it.

I think this project it too hard to do as a class project.

What equipment do you have?
Then we can see what you can actually do.

Hi, @jhenry2

Say you want to send the letter A (capital).
The ASCII is;

  • Decimal: 65
  • Hexadecimal (Hex): 41
  • Binary: 01000001

So you will send 01000001.
How will you distinguish between the zeros being sent in a row?
OFF, ON, OFF, OFF, OFF, OFF, OFF, ON.

You would have to make sure the flash rate is constant, so the string of OFFs can be detected.

Idea, use the Arduino UART port, to send the flashes, on the transmitter use the TX terminal to switch an LED.
Use an Arduino UART port RX to receive the flashes with a Photo-diode.
The Serial port UART protocol would take care of the synchronisation.

This will allow you down to 300baud with a UNO.

Tom.... :smiley: :+1: :coffee: :australia:

1 Like

Rather than send the data at 'computer speeds' like TomGeorge has just suggested, you could send the data at a much much slower rate, say one bit per second, so that the information is 'human readable'.

Make the first bit sent a 'start bit'.
When you detect the start of this bit, check the time using millis(), then check what the data is (during the centre of each time frame) at times of 1.5s, 2.5s, 3.5s, 4.5s etc. until you you have built up the full byte.

I think that this approach would give a better visual / audio demonstration for the class.

2 Likes

TomGeorge explained it perfectly:
"Say you want to send the letter A (capital).
The ASCII is;

  • Decimal: 65
  • Hexadecimal (Hex): 41
  • Binary: 01000001

So you will send 01000001."

I'm not trying to get it to say a word, just two different tones.

I like the idea of using IR as a solution to ambient light, but maybe I can have an accompanying LED as a visual cue to the observer of what signal is being sent.

I have Elegoo's "Most complete Starter Kit, Uno R3 Project" and some random Grove accessories like the loudness sensor, buzzer, LEDs, Motion Sensor, IR reciever.

This is great! Thank you! I agree this pace is a lot more observable for a class project.

It looks like you can do it with what you have except you would need two more Unos. One transmitter and two receivers altogether. It could of course be done on just one.

Spoke to soon, there is nothing to detect the light.

You can use the Tone library to generate the high and low tones.

You can indeed do this, but you have to make sure that when you block the light path then you need also to block turn off the visible LED and the tone being generated at the time. I would recommend the TSOP4038 receiver, as all the other types of TSOPxxx chips will require that the IR signal stops beyond a certain number of repeats.

TSOP4038 light barrier.pdf (107.0 KB)

With this the signal can be continuous without having to worry about the number of repetitions. Also note you will need to modulate the IR LED at 38 KHz, which you can do by applying a PWM signal to the LED set to this frequency.
This code shows how you can set up the PWM to go at the speed you need.

This code fires off an ISR every cycle but there is no need to do this:-

/* Code to pulse pin 3 with a modulated signal
* Can be used to drive an IR LED to keep a TSOP IR reciever happy
* This allows you to use a modulated reciever and a continious beam detector
* By Mike Cook Nov 2011 - Released under the Open Source licence
*/
 volatile byte pulse = 0;

ISR(TIMER2_COMPB_vect){  // Interrupt service routine to pulse the modulated pin 3
    pulse++;
  if(pulse >= 8) { // change number for number of modulation cycles in a pulse
    pulse =0;
    TCCR2A ^= _BV(COM2B1); // toggle pin 3 enable, turning the pin on and off
  }
}

void setIrModOutput(){  // sets pin 3 going at the IR modulation rate
  pinMode(3, OUTPUT);
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); // Just enable output on Pin 3 and disable it on Pin 11
  TCCR2B = _BV(WGM22) | _BV(CS22);
  OCR2A = 51; // defines the frequency 51 = 38.4 KHz, 54 = 36.2 KHz, 58 = 34 KHz, 62 = 32 KHz
  OCR2B = 26;  // deines the duty cycle - Half the OCR2A value for 50%
  TCCR2B = TCCR2B & 0b00111000 | 0x2; // select a prescale value of 8:1 of the system clock
}

void setup(){
  setIrModOutput();
  TIMSK2 = _BV(OCIE2B); // Output Compare Match B Interrupt Enable
}

void loop(){
// do something here
}

Still need help?