Wireless Data Transmission – Schematics

The transmitter unit must be constructed in such a way that a laser diode may be powered on and off in order to send the previously mentioned high/low states. For that reason, the circuit consists of a power circuit, which utilizes an NPN Bipolar Junction Transistor as a current switch. This means that depending on the applied voltage, the Transistor will allow or prevent current from flowing to the laser diode, effectively allowing a microcontroller to turn the laser diode on and off. An accompanying program is then written to allow the laser diode to transmit the data bits of ASCII characters received via serial link from host device and the transmitting microcontroller. The user simply enters whichever ASCII characters they desire to transmit. The microcontroller interrupts on any given serial event and immediately begins transmitting the character received.

The receiver unit was constructed using a Wheatstone Bridge circuit. The Wheatstone Bridge is a resistive circuit. Therefore, resistors and resistive sensors, such as photoresistors, make up each branch of the circuit. R2 and Rx in the circuit are similar photoresistors in order to allow for automatic adjustment to dynamic ambient light conditions. The versatility and relative accuracy of the Wheatstone Bridge allow for the photoresistors, which change resistance inversely with the amount of light shined on them, to change the overall circuit resistance allowing obvious high and low states to develop. These can then be interpreted by a Microcontroller such as the Xplained Mini Board with the appropriate software.

Wireless Data Transmission – Code

Transmitter Program

#define LASER_PIN           7
#define LASER_BAUDRATE      5  // bits per second
#define SIGNAL_HOLD_PERIOD  (1.0 / LASER_BAUDRATE) * 1000.0
#define SIGNAL_START_HOLD_PERIOD  SIGNAL_HOLD_PERIOD / 2.0

unsigned long transmit_begin;
byte c;
int message[10] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0};


int isNthBitSet (byte c, int n) {
  static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
  return ((c & mask[n]) != 0);
}

void transmitHoldStart() {
  while (millis() - transmit_begin < SIGNAL_START_HOLD_PERIOD) {}
}

void transmitHold() {
  //transmit_begin = millis();
  while (millis() - transmit_begin < SIGNAL_HOLD_PERIOD) {}
}

void transmitByte(byte c) {

  for (int idx=0; idx<8; idx++) {
    message[idx+1] = isNthBitSet(c, idx);
  }

  transmit_begin = millis();
  digitalWrite(LASER_PIN, message[0]);
  transmitHoldStart();

  for (int idx=1; idx<10; idx++) {
    transmit_begin = millis();
    digitalWrite(LASER_PIN, message[idx]);
    transmitHold();
  }
}

void serialEvent() {
  c = Serial.read();
  //if (!isPrintable(c)) { return; }
  //Serial.write("Transmitting '");
  transmitByte( c );
  //if (isPrintable(c)) {
    Serial.write(c);
  //}
  //Serial.write("&gt;&gt;&gt; ");
}


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(LASER_PIN, OUTPUT);
  transmit_begin = 0;
  c = '\0';
  Serial.begin(9600);
  Serial.write("\r\nReady to transmit!\r\n");
  Serial.write("\n&gt;&gt;&gt; ");

}

void loop() {
  
}

Receiver program

#define REF_PIN       24
#define SIG_PIN          23
#define LOGIC_1_CUTOFF      0
#define LASER_BAUDRATE      5
#define SIGNAL_HOLD_PERIOD  (1.0 / LASER_BAUDRATE) * 1000.0
#define START_BIT           1
#define STOP_BIT            0

int bit_val;
static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
int buff[8] = {};
byte data = 0;
unsigned long receive_begin;
int bias = 0;
int bias_samp_size = 20;
int bias_samp_delay = 100;

void adjustSensorBias() {
  for (int i=0; i<bias_samp_size; i++) {
    bias += analogRead(SIG_PIN) - analogRead(REF_PIN);
    delay(bias_samp_delay);
  }
  bias /= bias_samp_size;
}

int sensorRead() {
  int val = analogRead(SIG_PIN) - analogRead(REF_PIN) - bias;
  Serial.write("sensorRead(): val = ");
  Serial.print(val);
  Serial.println();
  if (val < LOGIC_1_CUTOFF) { return 1; }
  return 0;
}

void poolBuffer() {
  int tmp = 0;
  for (int idx=0; idx<8; idx++) {
    tmp += buff[idx] * mask[idx];
  }
  data = (byte)tmp;
}

void receiveWait() {
  receive_begin = millis();
  while (millis() - receive_begin < SIGNAL_HOLD_PERIOD) {}
}

void laserRead() {
  receiveWait();
  for (int idx=0; idx<8; idx++) {
    buff[idx] = sensorRead();
    receiveWait();
  }
  if (sensorRead() != STOP_BIT) {
    receiveWait();
    receiveWait();
  }
}

void setup() {
  Serial.begin(9600);
  pinMode(REF_PIN, INPUT);
  pinMode(SIG_PIN, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  adjustSensorBias();
}

void loop() {
  bit_val = sensorRead();

  //Serial.write("\r\nbit_val = ");
  //Serial.print(bit_val);
  //Serial.println();

  if (bit_val == START_BIT) {
    laserRead();
    poolBuffer();
    Serial.write("\r\ndata = ");
    Serial.write(data);
    Serial.println();
  }
}

Wireless Data Transmission – Big Picture

Wireless data transmission is achieved via optical means utilizing receiver and transmitter units. The transmitter unit consists of a laser diode and supporting power and switching circuit. The laser diode is supplied power from an Arduino. The 3.3V from the Arduino is voltage divided to near 3.0V to match with the laser diode specifications. The 3.0V is provided for the diode through a transistor, which also functions as a current switch controlled by software running on the Arduino. The circuit is used by the microcontroller to transmit binary data in the form of diode off (0) and diode on (1). The data is transmitted common asynchronous serial format (8N1). The receiver unit consists of photoresistors and an accompanying resistive circuit, arranged in a Wheatstone Bridge configuration. An Xplained Mini Board then uses both points ‘D’ and ‘B’ in the circuit to measure signal strength; one as a reference to ambient light, the other as a measure of ambient light plus signal light (i.e laser diode light). The Xplained Mini Board then decodes the bits received (8N1) and extracts the data bits, finally translating them back into ASCII characters that can be displayed via the serial terminal on the connected host device; TeraTerm in the case of this experiment