Drahtlose Datenübertragung per Laser (LiFi) – 100 Bit/s im Überblick
Benötigte Bauteile
| Arduino Nano R3 | 2 | |
| Steckbrett (Full Size) | 2 | |
| Alphanumerisches LCD 16×2 | 2 | |
| Steckbrücken (Jumper Wires) | 30 | |
| Tastatur 4×3 (Keypad) | 1 | |
| 9-V-Blockbatterie | 2 | |
| 9-V-Batterieclip | 2 | |
| Laserdiode (2 Pins) | 1 | |
| Solarmodul (Solar Cell) | Als Empfänger | 1 |
| Drehpotentiometer | Für LCD-Kontrast | 2 |
| Widerstand 10 kΩ | 3 |
Benötigte Werkzeuge
- Lötkolben
- Lötzinn (bleifrei)
Software & Online-Dienste
- Arduino IDE
Projektbeschreibung
Dieses Projekt besteht aus zwei Teilen: einem Sender (Emitter) und einem Empfänger (Receiver). Es ermöglicht die Übertragung von Textnachrichten per Laserstrahl – eine einfache LiFi-Implementierung (Light Fidelity). Eingabe erfolgt über ein 4×3-Keypad, die Anzeige auf einem 16×2-LCD.
Sender (Transmitter)
Der Sender nutzt einen Arduino Nano, ein LCD, ein Keypad und eine Laserdiode. Der Benutzer tippt Buchstaben über das Keypad ein (Bestätigungstaste drücken), und sendet die Nachricht per „Senden“-Taste. Der Text wird in ein 5-Bit-Codierschema umgewandelt (A–Z und Leerzeichen) und per Laser gepulst übertragen. Ein Startbit (9 ms High) leitet jedes Zeichen ein, dann folgen 5 Datenbits à 10 ms. Zwischen den Zeichen liegt eine 20-ms-Pause.
Empfänger (Receiver)
Der Empfänger verwendet einen zweiten Arduino Nano, ein LCD und eine Solarzelle als optischen Empfänger. Die Solarzelle detektiert die Laserpulse. Ein einstellbarer Schwellwert (Threshold) unterscheidet Hell/Dunkel. Nach Erkennung des Startbits werden 5 Bits eingelesen (Sampling alle 10 ms) und mit der internen Codetabelle verglichen. Erkanntes Zeichen wird auf dem LCD ausgegeben.
Schaltpläne & Verkabelung
Empfänger-Seite
- Solarmodul: Plus an Arduino A0, Minus an GND
- LCD (16×2):
- VSS → GND
- VDD → 5 V
- K (Kathode Hintergrundbeleuchtung) → GND
- A (Anode Hintergrundbeleuchtung) → 5 V
- RW → GND
- V0/VEE → Potentiometer-Schleifer (Kontrast)
- RS → Digital 12
- EN → Digital 11
- D4 → Digital 5
- D5 → Digital 4
- D6 → Digital 3
- D7 → Digital 2
Sender-Seite
- LCD (16×2): RS→12, EN→11, D4→6, D5→5, D6→4, D7→3, V0→Potentiometer, VSS/RW/K→GND, VDD/A→5 V
- Keypad 4×3:
- Zeilen (Rows) A→A2, B→A1, C→9, D→7 (als Outputs)
- Spalten (Columns) 1→8, 2→10, 3→A3 (als Inputs mit Pull-Down-Widerständen 10 kΩ an 8, 10, A3)
- Laserdiode: Kathode → GND, Anode → Digital 2
Bedienung
- Gewünschten Text per Keypad eingeben (nach jedem Buchstaben Bestätigungstaste drücken).
- Zum Abschluss Senden-Taste drücken.
- Laser und Solarzelle frontal ausrichten (Sichtverbindung nötig).
- Empfänger zeigt den Text auf dem LCD an.
Code
LI-FI Transmitter Code V 2.0 (C/C++)
/* LI-FI Transmitter Code V 2.0
Written By HOUALEF AHMED RAMZI
Started on 29-9-2020, Last Update 14-10-2020 */
#define LaserPin 2
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 6, d5 = 5, d6 = 4, d7 = 3;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
int incomingchar;
int KeyPad_R[] = {A2, A1, 9, 7};
int KeyPad_C[] = {8, 10, A3};
int KeyReturn = 0;
int ABC = 0;
int Row, Column;
int StCursor = 0, NdCursor = 0;
int outcomingmatrix[32][5];
int m = 0;
// 5-Bit-Codes für A-Z und Leerzeichen
int A[] = {1,1,1,1,0}, B[] = {0,0,0,1,0}, C[] = {0,0,0,1,1}, D[] = {0,0,1,0,0},
E[] = {0,0,1,0,1}, F[] = {0,0,1,1,0}, G[] = {0,0,1,1,1}, H[] = {0,1,0,0,0},
I[] = {0,1,0,0,1}, J[] = {0,1,0,1,0}, K[] = {0,1,0,1,1}, L[] = {0,1,1,0,0},
M[] = {0,1,1,0,1}, N[] = {0,1,1,1,0}, O[] = {0,1,1,1,1}, P[] = {1,0,0,0,0},
Q[] = {1,0,0,0,1}, R[] = {1,0,0,1,0}, S[] = {1,0,0,1,1}, T[] = {1,0,1,0,0},
U[] = {1,0,1,0,1}, V[] = {1,0,1,1,0}, W[] = {1,0,1,1,1}, X[] = {1,1,0,0,0},
Y[] = {1,1,0,0,1}, Z[] = {1,1,0,1,0}, SPACE[] = {1,1,1,1,1};
void setup() {
lcd.begin(16, 2);
pinMode(LaserPin, OUTPUT);
Serial.begin(9600);
for (int i=0; i<4; i++) pinMode(KeyPad_R[i], OUTPUT);
for (int j=0; j<3; j++) pinMode(KeyPad_C[j], INPUT);
lcd.print("HOUALEF RAMZI");
delay(5000);
lcd.clear();
lcd.setCursor(0,0);
}
void conv(int alpha[5], char Char) {
for (int i=0; i<5; i++) outcomingmatrix[m][i] = alpha[i];
lcd.print(Char);
}
void start_bit() {
digitalWrite(LaserPin, HIGH);
delay(9);
digitalWrite(LaserPin, LOW);
}
void KeyPad() {
for (int i=0; i<4; i++) {
digitalWrite(KeyPad_R[i], HIGH);
for (int j=0; j<3; j++) {
if (digitalRead(KeyPad_C[j]) == 1) {
Row = i; Column = j;
digitalWrite(KeyPad_R[i], LOW);
if (Row == 0) { switch(Column){ case 0: KeyReturn=1; break; case 1: KeyReturn=2; break; case 2: KeyReturn=3; break; } }
if (Row == 1) { switch(Column){ case 0: KeyReturn=4; break; case 1: KeyReturn=5; break; case 2: KeyReturn=6; break; } }
if (Row == 2) { switch(Column){ case 0: KeyReturn=7; break; case 1: KeyReturn=8; break; case 2: KeyReturn=9; break; } }
if (Row == 3) { switch(Column){ case 0: KeyReturn=10; break; case 1: KeyReturn=11; break; case 2: KeyReturn=12; break; } }
}
}
}
Serial.println(KeyReturn);
}
void KeyToAscii(int KeyN, int FirstAsciiValue) {
if (KeyReturn == KeyN) {
incomingchar = FirstAsciiValue + ABC;
ABC++; if (ABC == 3) ABC = 0;
}
}
void CursorControler() {
lcd.setCursor(StCursor, NdCursor);
if (KeyReturn == 10) { delay(100); StCursor++; m++; }
if (StCursor == 16) { StCursor = 0; NdCursor = 1; }
}
void loop() {
KeyPad();
delay(150);
CursorControler();
KeyToAscii(1, 65); KeyToAscii(2, 68); KeyToAscii(3, 71);
KeyToAscii(4, 74); KeyToAscii(5, 77); KeyToAscii(6, 80);
KeyToAscii(7, 83); KeyToAscii(8, 86); KeyToAscii(9, 89);
KeyToAscii(11, 32);
switch (incomingchar) {
case 65: conv(A,'A'); break; case 66: conv(B,'B'); break; case 67: conv(C,'C'); break;
case 68: conv(D,'D'); break; case 69: conv(E,'E'); break; case 70: conv(F,'F'); break;
case 71: conv(G,'G'); break; case 72: conv(H,'H'); break; case 73: conv(I,'I'); break;
case 74: conv(J,'J'); break; case 75: conv(K,'K'); break; case 76: conv(L,'L'); break;
case 77: conv(M,'M'); break; case 78: conv(N,'N'); break; case 79: conv(O,'O'); break;
case 80: conv(P,'P'); break; case 81: conv(Q,'Q'); break; case 82: conv(R,'R'); break;
case 83: conv(S,'S'); break; case 84: conv(T,'T'); break; case 85: conv(U,'U'); break;
case 86: conv(V,'V'); break; case 87: conv(W,'W'); break; case 88: conv(X,'X'); break;
case 89: conv(Y,'Y'); break; case 90: conv(Z,'Z'); break;
case 32: conv(SPACE,' '); break; case 33: conv(SPACE,' '); break;
}
if (KeyReturn == 12) { // Senden
delay(100);
for (int j=0; j<m; j++) {
start_bit();
for (int i=0; i<5; i++) {
digitalWrite(LaserPin, outcomingmatrix[j][i]);
delay(10);
}
digitalWrite(LaserPin, LOW);
delay(20);
}
// Puffer löschen
for (int k=0; k<32; k++) for (int l=0; l<5; l++) outcomingmatrix[k][l] = 0;
}
incomingchar = 0;
KeyReturn = 0;
}
LI-FI Receiver Code V 2.0 (C/C++)
/* LI-FI Receiver Code V 2.0
Written By HOUALEF AHMED RAMZI
Started on 29-9-2020, Last Update 14-10-2020 */
#include <LiquidCrystal.h>
#define SolarCell A0
int StCursor = 0;
// 5-Bit-Codes (identisch zum Sender)
int A[] = {1,1,1,1,0}, B[] = {0,0,0,1,0}, C[] = {0,0,0,1,1}, D[] = {0,0,1,0,0},
E[] = {0,0,1,0,1}, F[] = {0,0,1,1,0}, G[] = {0,0,1,1,1}, H[] = {0,1,0,0,0},
I[] = {0,1,0,0,1}, J[] = {0,1,0,1,0}, K[] = {0,1,0,1,1}, L[] = {0,1,1,0,0},
M[] = {0,1,1,0,1}, N[] = {0,1,1,1,0}, O[] = {0,1,1,1,1}, P[] = {1,0,0,0,0},
Q[] = {1,0,0,0,1}, R[] = {1,0,0,1,0}, S[] = {1,0,0,1,1}, T[] = {1,0,1,0,0},
U[] = {1,0,1,0,1}, V[] = {1,0,1,1,0}, W[] = {1,0,1,1,1}, X[] = {1,1,0,0,0},
Y[] = {1,1,0,0,1}, Z[] = {1,1,0,1,0}, SPACE[] = {1,1,1,1,1};
const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
int Cell_Input, Threshold;
int info[5];
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
pinMode(A0, INPUT);
Serial.begin(9600);
lcd.begin(16, 2);
lcd.setCursor(0, 0);
Threshold = analogRead(SolarCell) + 10;
lcd.print("READY TO RECEIVE");
delay(5000);
lcd.clear();
}
void BufferClear() {
for (int i=0; i<5; i++) info[i] = 0;
}
void check_condition(int received_bits[5], int Binaryalpha[5], char Lcdalpha) {
if (received_bits[0]==Binaryalpha[0] && received_bits[1]==Binaryalpha[1] &&
received_bits[2]==Binaryalpha[2] && received_bits[3]==Binaryalpha[3] &&
received_bits[4]==Binaryalpha[4]) {
lcd.print(Lcdalpha);
CursorControler();
}
}
void CursorControler() {
StCursor++;
if (StCursor == 16) lcd.setCursor(0, 1);
}
void loop() {
Cell_Input = analogRead(SolarCell);
if (Cell_Input > Threshold) { // Startbit erkannt
delay(10);
for (int i=0; i<5; i++) {
info[i] = (analogRead(SolarCell) > Threshold) ? 1 : 0;
delay(10);
}
check_condition(info, A, 'A'); check_condition(info, B, 'B'); check_condition(info, C, 'C');
check_condition(info, D, 'D'); check_condition(info, E, 'E'); check_condition(info, F, 'F');
check_condition(info, G, 'G'); check_condition(info, H, 'H'); check_condition(info, I, 'I');
check_condition(info, J, 'J'); check_condition(info, K, 'K'); check_condition(info, L, 'L');
check_condition(info, M, 'M'); check_condition(info, N, 'N'); check_condition(info, O, 'O');
check_condition(info, P, 'P'); check_condition(info, Q, 'Q'); check_condition(info, R, 'R');
check_condition(info, S, 'S'); check_condition(info, T, 'T'); check_condition(info, U, 'U');
check_condition(info, V, 'V'); check_condition(info, W, 'W'); check_condition(info, X, 'X');
check_condition(info, Y, 'Y'); check_condition(info, Z, 'Z'); check_condition(info, SPACE, ' ');
BufferClear();
}
}
Hinweise & Tipps
- Laser und Solarzelle müssen präzise frontal zueinander ausgerichtet sein (Sichtverbindung).
- Die Datenrate beträgt ca. 100 Bit/s (5 Bits pro Zeichen + Startbit + Pause ≈ 100 ms/Zeichen).
- Das 5-Bit-Codierschema erlaubt 32 Kombinationen – genutzt werden 26 Buchstaben + Leerzeichen.
- Für den Außenbetrieb: Umgebungslicht kann stören; Abschirmung oder Modulation (z. B. 38 kHz) würde die Robustheit erhöhen.
- Der Code ist bewusst einfach gehalten (keine Fehlerkorrektur, kein Protokoll) – ideal als Lernprojekt.
Herstellungsprozess
- Expertenratgeber für Aluminium-Lasermarkierung: Präzision, Langlebigkeit und Industrieanwendungen
- Umfassender Leitfaden zur Lasermarkierung: Arten, Vorteile und Anwendungen
- Faserlaser-Markierung: Präzision, Geschwindigkeit und Vielseitigkeit für moderne Industrien
- Laserpointer: Design, Fertigung und Sicherheitsübersicht
- Halbleiterlaser: Präzise Lichtgenerierung für moderne Technologie
- Festkörperlaser: Technologie, Anwendungen und Zukunftstrends
- DVD-Player: Geschichte, Technologie und zukünftige Innovationen
- Laser-gelenkte Lenkflugkörper: Entwicklung, Fertigung und strategische Bedeutung
- Revolutionärer elektrooptischer Laser: 30 GHz Pulsrate für ultraschnelles Imaging & Kommunikation
- Durchbruch bei optischen Fasern: 1 Petabit/Sekunde Übertragungsgeschwindigkeit