LCD Transferring Data
Abstract:
This research looks at the feasibility of transferring data between devices using a light sensor and LCD. To transfer the data, a macbook was used, and to receive the data, an Arduino with light sensor was used. Quarter, half, three-quarter and full brightness were tested. From the data collected, it was determined that transferring data in this way is feasible and using half brightness and above gave optimal results.
Purpose:
The purpose of this research is to test the feasibility of transferring data between devices using a light sensor and an LCD. The reasoning behind this is that LCDs are very common, whether it be a smartphone or computer, and it may be beneficial to design a device that doesn’t require an electrical connection. Some benefits of not needing an electrical connection are that it eliminates the need for cables and a device could be placed inside a sealed enclosure to make it waterproof.
Goal:
The user will hold their device with the light sensor against the LCD. The computer or smartphone will then flash the screen black or white to signal a “0″ or “1″ respectively. The device will then decode the “0″s and “1″s back into usable data.
____________________________________________________________________________________________________________________
Hardware:
Macbook Pro With Retina Display:
A MacBook laptop with high-resolution display. Refresh rate of 60Hz. In theory the laptop used shouldn’t matter too much.
____________________________________________________________________________________________________________________
Arduino Uno:
Onboard ADC (A2) is used to read the light sensor. I’m using the internal voltage reference of 1.1V. Values range from 0-1024 (0V = 0, 1.1V = 1024).
Instead of running wires to 5V and ground, I used A0 and A1 as digital pins to supply the voltages. By setting A0 high, it will supply the 5V and by setting A1 low it act as ground.
____________________________________________________________________________________________________________________
TEMT6000 Breakout Board:
Used as a light sensor. When more light is shown on it, the higher the output voltage. I’ve covered the board in clear glue–but made sure not to cover the sensor–to prevent scratching my expensive computer.
Connections:
____________________________________________________________________________________________________________________
Software:
To generate black and white screens, I used processing. The code below counts down from 3 to give the user time to align the light sensor, and then takes a string and breaks it down into ASCII binary. Then it flashes the screen black for a “0″ and white for a “1″. After it finishes transferring all the data, it closes the window.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
/******************************************************** Program: Light Transfer Author: Connor Taylor Updated: Feb. 1, 2013 This program is designed to send a string to a light sensor by flashing the screen either black or white to represent a "0" or a "1" respectively. Released under the Creative Commons Attribution 3.0 Share Alike Licence http://creativecommons.org/licenses/by-sa/3.0/us/ http://www.narkidae.com/experiments/transferringdata/ ********************************************************/ //**** WARNING: RAPID FLASHING. MAY TRIGGER EPILEPSY **** //30 Frames per second final int REFRESH_RATE = 30; //Enter the string to transfer final String str = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; int chars = str.length(); //The number of characters int bitNum = 0; //The bit place int letterNum = 0; //The letter number char letter; //The letter boolean countdown = true; //Whether or not to do a countdown int count = 3; //Number to start counting down from void setup(){ size(100, 100); //Create a window that is 100px wide by 100px high frameRate(REFRESH_RATE); background(255,255,255); //Set the background to white } void draw(){ //-----------------------COUNTDOWN--------------------------- //Count down from 3 before flashing if(countdown){ //Clear the display background(255,255,255); //Display the number fill(0,180,255); textSize(64); text(count, 32, 75); count--; delay(1000); if(count < 0) countdown = false; } //------------------------TRANSFER------------------------ //Execute flashing after counting down if(countdown == false){ //Get the letter out of the string letter = str.charAt(letterNum); //If the bit at bitNum is a 1, flash white if((letter >> bitNum) % 2 == 1) background(255,255,255); //If the bit at bitNum is a 0, flash black else background(0,0,0); //Move to the next bit bitNum++; //After finishing a letter, move to next letter and reset bitNum if(bitNum > 7){ bitNum = 0; letterNum++; } //After flashing all the letters, exit if(letterNum == chars) exit(); } } |
To decode the data, the Arduino waits for the sensor to fall below some threshold, wait half a clock cycle and then starts reading in the data. In this way, the Arduino should read the light sensor only when the LCD is not changing state. The code below samples the light sensor 30 times per second (the same speed as the Processing code outputs the data) and prints the read value to the serial monitor.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
/******************************************************** Program: Light Transfer Author: Connor Taylor Updated: Feb. 1, 2013 This program is designed to decode data sent to it via black and white pulses of an LCD. Released under the Creative Commons Attribution 3.0 Share Alike Licence http://creativecommons.org/licenses/by-sa/3.0/us/ http://www.narkidae.com/experiments/transferringdata/ ********************************************************/ #define threshold 50 boolean bits[1024]; //Buffer to store the data int index = 0; unsigned long time; int b; int input = 1023; void setup(){ pinMode(A0, OUTPUT); pinMode(A1, OUTPUT); pinMode(A2, INPUT); digitalWrite(A0, HIGH); //Supplies 5V to the sensor digitalWrite(A1, LOW); //Supplies GND to the sensor Serial.begin(9600); analogReference(INTERNAL); //Use the 1.1V internal reference delay(100); while(input > 24){ //Wait for sensor value to fall below some threshold input = analogRead(A2); Serial.print("Waiting... A2= "); Serial.println(input); } delayMicroseconds(16000); //Wait half a cycle time = micros(); //Start the timer } void loop(){ for(index = 0; index < 16; index++){ input = analogRead(A2); if(input > threshold) bits[index] = true; else bits[index] = false; Serial.print(input); //Outputs the 10 bit value that was read from the sensor //Serial.print(bits[index]); //Outputs the interpreted value (1 or 0) Serial.print(" "); while(micros() - time < 33300); //Wait until time passes is equal to 33300uS time = micros(); //reset the timer } Serial.println(""); } |
Results:
I decided to test different backlight brightness levels to test it’s affect on distinguishing “0”s from “1”. The following was sent to the Arduino using Processing and the LCD:
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
The light sensor was held firmly against the LCD and the following are the values the Arduino printed to the serial monitor. Red numbers signify what numbers should be read as a “1”.
Quarter Brightness:
23 39 43 47 46 44 45 27 18 37 43 42 47 44 48 22 23 37 46 47 47 48 41 24 18 38 45 46 44 47 42 27
25 39 48 44 43 46 39 25 23 46 46 44 47 48 43 19 20 34 48 45 49 45 46 24 26 46 47 44 44 48 44 22
20 42 44 45 48 46 49 22 23 45 48 48 44 48 46 20 23 49 46 48 48 49 48 25 21 47 45 48 49 48 47 21
26 47 45 46 45 46 44 24 22 46 43 47 47 44 47 25 25 45 47 47 45 43 47 20 20 45 47 46 42 47 45 24
23 40 45 45 44 47 42 21 22 42 42 45 44 45 47 22 21 41 45 44 45 46 44 23 19 41 46 44 44 44 44 22
18 43 45 45 44 45 44 22 21 43 43 44 45 44 44 21 18 43 42 40 44 45 45 22 20 40 43 44 45 44 44 20
21 44 44 43 44 44 44 20 19 44 44 44 44 42 45 21 21 43 45 44 45 46 43 19 21 44 46 44 45 45 46 20
20 41 46 47 46 45 44 22 21 46 46 45 43 45 46 22 23 45 46 45 45 45 45 22 23 46 47 45 47 46 46 21
Half Brightness:
13 82 84 84 85 84 85 17 13 78 85 83 83 83 83 15 14 81 83 83 83 82 84 15 14 81 84 85 85 83 84 13
13 80 84 85 85 84 85 15 14 79 84 83 85 85 86 16 14 78 86 83 86 82 83 17 13 78 86 85 80 85 86 14
12 75 85 84 83 83 86 16 14 75 86 85 85 86 84 16 14 77 85 82 84 83 85 19 12 73 85 83 85 84 81 20
13 70 85 84 84 85 85 22 13 72 84 83 85 83 83 20 16 71 84 86 84 84 85 24 15 70 85 82 85 86 84 27
15 67 84 86 84 85 84 26 14 66 85 86 86 86 79 16 14 83 85 86 82 85 86 10 16 84 86 86 86 82 85 15
13 84 86 86 85 84 84 12 15 83 83 85 86 86 85 16 16 83 84 84 87 85 87 13 15 83 87 83 86 85 84 15
12 83 87 85 88 86 84 13 14 84 87 84 86 86 86 16 15 84 87 86 87 86 83 14 14 82 85 86 84 88 86 18
17 82 87 86 87 86 83 14 15 82 85 85 87 86 81 17 16 82 85 85 87 87 85 17 15 81 87 85 86 85 87 17
Three Quarters Brightness:
12 180 186 187 189 188 187 14 12 180 188 189 188 189 190 15 11 178 189 188 190 188 188 15
10 171 189 189 188 187 189 17 12 175 187 190 190 189 182 17 12 175 187 188 185 188 190 17
11 174 191 190 185 188 190 19 12 187 186 188 190 188 186 21 11 188 190 191 190 191 190 12
11 187 190 191 190 191 189 12 13 190 191 190 190 189 190 12 12 189 189 189 190 189 188 13
11 190 191 190 189 191 190 12 12 189 190 190 190 190 191 12 13 191 192 190 192 185 190 13
12 188 193 190 191 191 189 12 11 190 192 190 193 191 190 12 11 190 192 189 192 190 190 13
11 188 190 190 193 190 189 14 12 188 189 187 191 191 190 13 11 187 190 190 191 191 191 14
12 188 192 192 190 192 191 13 11 185 192 190 190 191 190 13 11 185 191 191 193 192 192 13
11 183 193 192 191 190 192 13 12 184 190 191 191 192 191 14 10 182 189 190 189 189 190 11
11 187 191 190 190 190 192 11 11 191 188 190 189 190 191 11 9 190 189 189 189 191 191 11
9 189 189 191 190 191 189 11 11 189 189 190 189 191 187 12
Full Brightness:
14 379 390 393 392 391 391 18 15 377 393 392 390 386 391 19 15 373 392 390 392 390 389 20
14 372 391 392 392 384 383 22 15 369 391 390 392 390 393 20 15 365 392 392 390 390 391 28
14 361 392 390 389 390 390 31 15 354 392 391 390 390 390 35 16 350 390 392 392 392 390 15
15 388 389 391 391 389 391 15 16 390 389 390 392 391 389 15 15 389 391 391 390 392 391 15
14 389 390 390 390 391 392 14 14 389 391 390 392 393 390 16 14 383 382 392 392 391 391 15
16 385 390 390 384 390 389 16 12 386 383 390 392 391 392 16 15 384 385 389 392 392 392 16
14 384 394 392 393 393 392 19 15 379 384 392 395 392 393 18 15 375 390 391 391 392 390 19
14 374 390 391 390 391 392 20 15 370 390 393 390 392 392 22 14 367 390 390 390 386 392 24
14 364 391 391 391 391 386 27 15 361 392 393 393 391 390 30 15 356 392 391 392 390 391 36
15 349 390 392 391 384 390 17 15 388 391 392 390 392 393 15 13 388 391 393 391 387 393 16
15 390 392 393 391 391 391 13 14 388 391 391 392 392 391 15
Changing the Arduino code slightly by commenting out “Serial.print(input)” and un-commenting “Serial.print(bits[index])”, the Arduino will now output the interpreted value instead of the sensor reading.
|
1 2 |
//Serial.print(input); //Outputs the 10 bit value that was read from the sensor Serial.print(bits[index]); //Outputs the interpreted value (1 or 0) |
The following is the data that the Arduino interpreted for half, three-quarter and full brightness with a threshold of 50:
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0 0 1 1 1 1 1 1 0
Analysis:
From these results, it is clear that the sensor was able to detect a significant difference between a black screen and a white screen at every tested brightness levels. The sensor reading stayed relatively constant for a black screen, but the sensor reading for a white screen increased dramatically with every increase in brightness. At quarter brightness the difference between a black screen and a white screen was not very large, however there was no overlap between the two, meaning that this brightness level could work, but may not be as reliable as desired. At half brightness and above, the difference between a white and black screen was substantial. For half brightness and above, a threshold of 50 may be used to decide between a reading being a “0” (under 50) or a “1” (50 or greater).
Conclusion:
From this research, I have determined that it is feasible to implement a data transfer method using an LCD and light sensor. The difference between a white screen reading and a black screen reading was great enough for half brightness and above that reliable data transmission is possible.
Further Research:
One improvement that could be made on this method is instead of transferring one bit at a time by flashing the screen black or white, multiple bits could be transferred by flashing the screen different shades of grey.
Another improvement that could be made is auto-detecting the threshold used to decide between a “0” and a “1”.

