Skip to content

Instantly share code, notes, and snippets.

@wlmeng11
Created February 17, 2017 01:18
Show Gist options
  • Select an option

  • Save wlmeng11/469243778975754bf650ea086240798c to your computer and use it in GitHub Desktop.

Select an option

Save wlmeng11/469243778975754bf650ea086240798c to your computer and use it in GitHub Desktop.
Laser UART Transmitter
/**
* Laser UART Receiver
* William Meng
* 2/16/17
*
* Based on "Gateway_better_code_receive.ino" by Sean Zimmermann
*
* What's new in this version:
* The program has been updated to work better with the laser
* transmitter and solar cell receiver circuit. The bitrate has been
* reduced to 10 bits per second so you can actually see the laser
* pulses. Additionally, the idle state has been changed to be an
* alternating sequence of HIGHs and LOWs so that the capacitor
* voltage in the receiver circuit doesn't drift too close to the
* HIGH or LOW voltages, which caused erratic oscillations.
*
* This required a lot of changes in the control flow in terms of
* how and when to detect a start bit.
*/
#define IDLE_TIME 100
#define STOP_IDLE_TIME 200 // must be longer than IDLE_TIME
#define BIT_TIME 100 // 1 bit per 100ms
#define WAIT_CYCLES 1
#define WAIT_PERIOD WAIT_CYCLES*IDLE_TIME
#define RX_PIN 6
#define TX_PIN 7
void setup() {
pinMode(RX_PIN, INPUT_PULLUP);
pinMode(TX_PIN, OUTPUT);
digitalWrite(TX_PIN, HIGH);
Serial.begin(9600);
}
/**
* Receive the data
* Wait for and identify the stop idle signal, wait for the start bit,
* then wait until the midpoint of each data bit to sample.
*/
void receive() {
byte data = 0;
//Serial.println("Begin receive function");
while(detect_stop_idle() == 0) {}
while(digitalRead(RX_PIN) == HIGH) {}// wait for the start bit
delay(BIT_TIME/2); // wait until midpoint of start bit
for(int offset = 0; offset < 8; offset++) {
delay(BIT_TIME);
data |= digitalRead(RX_PIN) << offset;
}
//Serial.print("Data: ");
Serial.print((char)data); // convert byte to char
delay(IDLE_TIME);
}
/**
* Returns true if a stop idle signal has been received.
* Returns false means the signal is still idling.
*/
int detect_stop_idle() {
while(digitalRead(RX_PIN) == 0) {}
delay(IDLE_TIME*3/2);
if(digitalRead(RX_PIN)) {
//Serial.println("STOP idling");
return 1;
}
else {
//Serial.println("I");
return 0;
}
}
/*
* Prints 1's and 0's every 20ms to serve as a very crude logic
* analyzer, for debugging purposes.
*/
void printRaw() {
Serial.print(digitalRead(RX_PIN));
delay(20);
}
void loop() {
receive();
//printRaw();
//detect_stop_idle();
}
/**
* Laser UART Transmitter
* William Meng
* 2/16/17
*
* Based on "Gateway_better_code_receive.ino" by Sean Zimmermann
*
* What's new in this version:
* The program has been updated to work better with the laser
* transmitter and solar cell receiver circuit. The bitrate has been
* reduced to 10 bits per second so you can actually see the laser
* pulses. Additionally, the idle state has been changed to be an
* alternating sequence of HIGHs and LOWs so that the capacitor
* voltage in the receiver circuit doesn't drift too close to the
* HIGH or LOW voltages, which caused erratic oscillations.
*
* This required a lot of changes in the control flow in terms of
* how and when to detect a start bit.
*/
#define IDLE_TIME 100
#define STOP_IDLE_TIME 200 // must be longer than IDLE_TIME
#define BIT_TIME 100 // 1 bit per 100ms
#define WAIT_CYCLES 1
#define WAIT_PERIOD WAIT_CYCLES*IDLE_TIME
#define RX_PIN 6
#define TX_PIN 7
void setup() {
pinMode(RX_PIN, INPUT);
pinMode(TX_PIN, OUTPUT);
digitalWrite(TX_PIN, HIGH);
Serial.begin(9600);
}
/*
* Transmit a strictly alternating series of 1's and 0's while idling
* Each bit has a duration of IDLE_TIME
*/
void idle() {
digitalWrite(TX_PIN, HIGH);
delay(IDLE_TIME);
digitalWrite(TX_PIN, LOW);
delay(IDLE_TIME);
}
/*
* Transmit the data, but first send a stop idle signal and the start bit
*/
void transmit(byte data) {
// transmit a stop idle bit
digitalWrite(TX_PIN, HIGH);
delay(STOP_IDLE_TIME);
// transmit the start bit
digitalWrite(TX_PIN, LOW);
delay(BIT_TIME);
byte mask;
for (mask = 0x01; mask>0; mask <<= 1) { // iterate through bit mask
if (data & mask){ // compare the bits
digitalWrite(TX_PIN,HIGH); // send 1
}
else{
digitalWrite(TX_PIN,LOW); // send 0
}
//delayMicroseconds(bit9600Delay); //hold for one bit cycle
delay(BIT_TIME);
}
// idle for the wait period
for (int i = 0; i < WAIT_CYCLES; i++) {
idle();
}
}
void transmitV() {
// transmit a stop idle bit
digitalWrite(TX_PIN, HIGH);
delay(STOP_IDLE_TIME);
// transmit the start bit
digitalWrite(TX_PIN, LOW);
delay(BIT_TIME);
// transmit data for V
digitalWrite(TX_PIN, LOW); // 0
delay(BIT_TIME);
digitalWrite(TX_PIN, HIGH); // 1
delay(BIT_TIME);
digitalWrite(TX_PIN, LOW); // 0
delay(BIT_TIME);
digitalWrite(TX_PIN, HIGH); // 1
delay(BIT_TIME);
digitalWrite(TX_PIN, LOW); // 0
delay(BIT_TIME);
digitalWrite(TX_PIN, HIGH); // 1
delay(BIT_TIME);
digitalWrite(TX_PIN, HIGH); // 1
delay(BIT_TIME);
digitalWrite(TX_PIN, LOW); // 0
delay(BIT_TIME);
}
void loop() {
if (Serial.available() > 0) {
// Required delay to enable re_transmit
// More retransmits may require higher
// delay. Can be commented out if no
// retransmits are used to achieve higher
// speed.
//delayMicroseconds(per_letter_delay);
// read the incoming byte:
byte data = Serial.read();
// say what you got:
Serial.print("I am sending: ");
Serial.println((char)data);
// if you do Serial.println(SWval, DEC);
// then you can see the ASCII code
transmit(data); //send it out
}
else {
idle();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment