The project I'm working on: Short-Range Coded Visible Light Communication System.

Visible Light Communication (VLC) systems use light to transfer data between transmitter and receiver over short-range links. This project intends to build a wireless VLC system capable of transmitting voice between two microcontrollers such as an Arduino or a Raspberry Pi using visible light.

An LED or laser diode is deployed at the transmitter side, and a Light Dependent Resistor (LDR) or photodiode is deployed at the receiving side.

Digital data is transmitted using on-off keying where the LED functions as on-off light. Strings of ones (1) and zeros (0) are transmitted with high frequency such that the LED flicking is undetectable to the human eye.

I'm using an Arduino Uno and this is the code that I used. I'm hearing noise from the speaker, not my voice.

Transmitter code: 
// Define microphone pin
const int micPin = A0;

// Define LED pin
const int ledPin = 9;

// Define sampling frequency (in Hz)
const int samplingFrequency = 8000;

void setup() {
  // Set microphone pin as input
  pinMode(micPin, INPUT);
  // Set LED pin as output
  pinMode(ledPin, OUTPUT);

  // Begin serial communication at 9600 baud rate

void loop() {
  // Read analog voltage from microphone
  int analogValue = analogRead(micPin);

  // Map analog voltage to PWM duty cycle (0-255)
  int dutyCycle = map(analogValue, 0, 1023, 0, 255);

  // Set LED brightness based on duty cycle
  analogWrite(ledPin, dutyCycle);

  // Print duty cycle value to serial monitor

  // Delay to maintain sampling frequency
  delay(1000 / samplingFrequency);

Receiver code:

const int ldrPin = 9;
const int speakerPin = 11;
int voiceSample;

void setup() {
  pinMode(ldrPin, OUTPUT);
  pinMode(speakerPin, OUTPUT);

void loop() {
  analogWrite(ldrPin, voiceSample);
  if (voiceSample > 255) {
    voiceSample = 0;
  int voiceInput = analogRead(A0);
  voiceInput = map(voiceInput, 0, 1023, 0, 255);
  analogWrite(speakerPin, voiceInput);

1 Answer 1


The Serial.println(dutyCycle) in your transmitter is going to seriously slow down communications. It takes 1.04 ms to send a single byte over serial at 9600 baud, and assuming you have 3 digits, plus carriage return and linefeed that will take over 5 ms for each serial print.

However you are trying to sample at 8000 times a second (once per 125 µs) so you simply won't keep up. I suggest removing the serial print.

delay(1000 / samplingFrequency);

The delay function takes a long argument, not a float. 1000 / 8000 will evaluate to zero so the sample rate will not in fact be 8000 times a second.

You may want to consider the delayMicroseconds function.

Did you write this code or ChatGPT? ChatGPT questions are currently banned on Stack Overflow. I'm not sure about their policy in regards to Arduino Stack Exchange.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.