Implementacja Li-Fi (świetlne Wi-Fi?) w JavaScript - komunikacja na odległość (film, 13 minut)
Charlie Gerard w swoim najnowszym filmie wideo zaprezentował fascynującą technologię znaną jako LiFi, która wykorzystuje źródła światła do przesyłania informacji. W przeciwieństwie do Wi-Fi, które korzysta z fal radiowych, LiFi używa widzialnego światła jako medium do transmisji danych. Kluczowym punktem LiFi jest oszczędzanie energii poprzez połączenie możliwości oświetleniowych żarówek z możliwościami przesyłania danych, co sprawia, że nasze lampy stają się swoistymi routerami. W wideo Charlie pokazuje, jak stworzyć prototyp projektu LiFi, korzystając z JavaScript i Arduino, co pozwala na lepsze zrozumienie działania tej technologii.
Na początku film zawiera przegląd materiałów potrzebnych do budowy projektu. Charlie sugeruje użycie Arduino Uno oraz NeoPixel Jewel z siedmioma diodami LED jako nadajnika. Alternatywnie można użyć standardowych diod LED, ale wymaga to dodania rezystora i umiejscowienia czujnika świetlnego bliżej nadajnika. Z drugiej strony odbiornik jest zbudowany na bazie innego Arduino Uno, 10k rezystora, fototranzystora, przewodów połączeniowych oraz płytki stykowej. Charlie krok po kroku wyjaśnia, jak połaczyć te elementy, co czyni to projektem dostępnym nawet dla amatorów.
Kiedy już wszystkie komponenty sprzętowe są gotowe, Charlie omawia działanie systemu przed przystąpieniem do kodowania. Użycie logicznych stanów w żarówce oraz zasady kodowania informacji w postaci binarnej są kluczowymi elementami tego filmu. Podkreśla, że odbiornik potrzebuje wyraźnego sygnału, aby rozpocząć dekompozycję danych. Za pomocą unikalnego protokołu komunikacyjnego, Charlie wyjaśnia, jak ważna jest synchronizacja pomiędzy nadajnikiem a odbiornikiem, co jest fundamentalne dla poprawnego przekazu danych.
W dalszej części filmu Charlie wprowadza widzów w świat programowania tej technologii, wykorzystując JavaScript oraz framework Johnny5. Pokazuje, jak w prosty sposób można przesyłać dane przez światło, z wykorzystaniem zmiennych, funkcji oraz zasad logiki binarnej. Zauważa jednak, że chociaż JavaScript jest łatwy do użycia, w praktycznych zastosowaniach LiFi przewaga będzie mieć kod Arduino, który zapewnia wyższą wydajność. Charlie demonstruje różnice w wydajności między dwoma metodami kodowania, podkreślając, że zbyt wolna transmisja światła nie będzie użyteczna w codziennym użytkowaniu.
Na koniec Charlie podsumowuje swoje doświadczenia podczas tworzenia prototypu oraz zaprasza widzów do dalszego zgłębiania tematu LiFi. Mówi o potencjale LiFi, jak również o wielu możliwych zastosowaniach technologii, takich jak lepsze połączenia w samolotach, gdzie LiFi może zminimalizować zakłócenia radiowe. W chwili pisania tego artykułu, film zgromadził 9794 wyświetleń i 328 reakcji, co świadczy o rosnącym zainteresowaniu tą nowoczesną technologią. Charlie na pewno zainspirował wielu entuzjastów technologii do dalszego eksplorowania tego innowacyjnego rozwiązania.
Toggle timeline summary
-
Wprowadzenie do technologii LiFi i jej celów.
-
Przegląd prototypowania projektu LiFi przy użyciu JavaScript i Arduino.
-
Opis materiałów potrzebnych do projektu.
-
Montaż komponentów sprzętowych nadajnika i odbiornika LiFi.
-
Wyjaśnienie, jak żarówki reprezentują stany włączony i wyłączony.
-
Wprowadzenie do zapisów binarnych i kodowania danych.
-
Znaczenie niestandardowego protokołu komunikacyjnego dla przesyłania danych.
-
Testowanie protokołu komunikacyjnego z wykorzystaniem stanów świetlnych.
-
Kodowanie strony nadajnika przy użyciu JavaScript i frameworka Johnny5.
-
Dyskusja na temat wdrożenia strony odbiornika projektu.
-
Udane przesyłanie znaków za pomocą sygnałów świetlnych.
-
Ograniczenia napotykane przy użyciu JavaScript w porównaniu do Arduino.
-
Potencjalne zastosowania technologii LiFi w przesyłaniu danych.
-
Przykłady, jak LiFi może poprawić łączność w czasie lotu.
-
Podsumowanie i przyszłe perspektywy projektów LiFi.
Transcription
Recently, I spent some time learning about LiFi, a technology that uses light sources to transmit information. The same way that Wi-Fi uses radio waves to transmit data between your router and your devices, LiFi uses another part of the electromagnetic spectrum, and that is visible light. The prospect of LiFi is to save electricity by combining the lighting capability of your light bulbs with data transmission capabilities, so your lights would kind of be turned into a router. In this video, I want to show you how you can prototype your own LiFi project using JavaScript and Arduino, so you can better understand how this technology works. First, let's look at the material you need. There's a lot of different ways to build this project, but to keep it simple, the transmitter side is going to use an Arduino Uno, and a NeoPixel Jewel with seven LEDs. If you only have standard LEDs, you can also use that. The only difference is that you're going to need to add a resistor, and your light sensor will have to be set up closer for it to work, as an LED is much less bright than the NeoPixel Jewel. But if you just want to try it out, it will also work with a simple LED. On the receiver side, I used another Arduino Uno with a 10k resistor, a phototransistor, some jumper wires, and a breadboard to assemble everything. All of these components are then assembled following these schematics. The NeoPixel Jewel is connected to pin 7, 5V, and ground. The 10k resistor is connected to one end of the phototransistor, that is then connected to 5V. An extra wire is connected to pin A0, and the other side is connected to ground. Now that our hardware components are set up, let's talk about how this is actually going to work before we write any code. A light bulb has mainly two different states. It's either on or off. If you're using an RGB light bulb that can change color, we're not going to consider here that the different colors are different states. You could use that if you were using a color sensor, but here we're using a light sensor that is going to detect the level of brightness, so we're going to work with only these on and off states. So how could we encode information using only two possible values? Well, if you're used to working with computers, you probably know about the binary notation, where you also only have two possible values, 0 and 1. So we could use the off state of the light bulb as a 0, and the on state as a 1. Now, we need to think about how the receiver, so the light sensor, is going to decode this information to reconstruct the original data transmitted. This is where it gets even more interesting, because we need to come up with a custom communication protocol to make sure that the transmitter and the receiver are in sync. Let's look at an example to understand better what I mean by that. Let's say you are sending the letter A continuously. The letter A in binary is 01100001. When we're sending this stream of bits, we know that our character is 1 byte, and 1 byte is 8 bits. So we can sample the data every 8 bits, convert that back to a character, and keep going through the stream. But what if the receiver starts the sampling at the wrong location in the stream? All of a sudden, even being 1 bit off means that the data samples will be incorrect. If the light sensor starts trying to decode 11000010, it's a character that actually doesn't exist in ASCII, so the rest of the stream is wrongly converted as well. Technically, if the light sensor is on, it continuously detects the current brightness level around it, but it doesn't mean that data is currently being transmitted. So we need to find a way to trigger the decoding logic at the actual time that the light is sending data, and that's why we need to implement our custom communication protocol. At first, we can expect that the initial state of our light bulb is going to be on. For the light sensor to start sampling data, we need a change of state, and the only change that can happen at that time is the switch from on to off. So we can use that as a kind of preamble in our protocol. It's going to be the signal that a message is coming. After the preamble, we can send our 8 bits in the form of light toggling between on and off. Here the message would be 10101010. This is not a real message, I'm only using it as an example. And then we need to set our light back to its initial state so that this logic can repeat for the rest of the data transmitted. So we have a preamble, then our data, and then back to our initial state. But we also need to determine an interval, so the light will be in its different state for a specific amount of time, and the receiver will sample data at the same interval as well. We can take 100 milliseconds, for example. So every time the light represents a bit value using its state of either on or off, it does so for 100 milliseconds. On the receiver side, the very first interval is going to be one and a half times the interval of 100 milliseconds, because we don't want to sample the preamble, and we want to make sure that it samples data within the interval of 100 milliseconds. Now that we have an idea of what the communication protocol will look like, it's time to start implementing it. To do this, we're going to use JavaScript and the awesome Johnny5 framework. If you've never used Johnny5 before, I highly recommend it. It's an awesome framework to build hardware projects in JavaScript, and it supports a lot of different boards and components. If we start with the transmitter side, we need to start by declaring a few variables here and instantiate a board with the port to the first Arduino. Then, our communication protocol states that the light first needs to turn off, then wait for a specific amount of time, and then encode bits into light states. So first, let's look into how a string can be converted to binary data in JavaScript. For this, I wrote a function called convertToBinary. It takes a string as parameter, it splits it, loops through each character, calls charCodeAt0 to get its decimal representation, then calls toStringTo to get the binary number, and then I call the method padStart, because by default, if you don't do that, it will remove the leading zeros. So sometimes, a byte will actually result in five bits without the leading zeros, but that would be a mess for our decoding logic. And finally, I call join to return the full byte as a string of bit values. Then, here's also my implementation of a delay function used for the intervals. It's basically setTimeout inside a promise that uses the interval that is passed in. So now, let's go through the core of the logic. When the board is ready to receive instruction, I store my light into a strip variable, so here I call pixel.strip, and I indicate which pin my NeoPixel dual is connected to on the Arduino, and I also declare how many LEDs are on the component, so seven. When that strip is ready, I turn the light on here, and I apply a delay to kind of simulate that the light was on by default. Then, I call a function named sendBytes. This function will loop through each character in the string and starts by turning the light off as specified in the communication protocol. Then, I apply the delay, and I convert the character to binary. And for each bit, if it's a one, then I turn the light on, and if it's a zero, then I turn it off, and then I wait for the interval specified. When we've looped through all of the bits here in the byte, we turn the LED back on, and we wait again. Finally, I call sendBytes recursively to keep sending the data continuously. So now, if we're in this code, let's look at what happens. So it should turn the light on for about three seconds to start with, as if it was the default state, and then it's going to flash to represent the bit values. So when the light is on, it means that the bit sent is a one, and when it's off, it means that the bit sent is a zero. Okay, now let's implement the receiver side. Some of it is going to be quite similar. We also start by declaring a few variables and instantiating the second board with its port here, and we pick a certain threshold. So this is going to be the level of brightness that is going to be the threshold between the light being on or off. When the board is ready, we declare the sensor here, and we store it into a sensor variable, and when data is received from that sensor, we store the current brightness value into a light value variable. Then, I use this.loop to call this function every 10 milliseconds, and if it's not already decoding data, we call the decode function. This function first gets the current state of the light. If the value of the light sensor is above the threshold, then we are going to decode the value one and otherwise zero. The communication protocol indicates that the signal for a message coming is that the light goes from on to off. So here, we have a condition that says that if the current state is zero and the previous state is one, then we can start the detection and call the getByte function. In getByte, first, we wait for one and a half times the interval. Then, we look at the value of the light sensor that will return either one or zero. We wait for the interval before doing it again eight times. Then, we pass the string into a function that will convert the binary data back to ASCII character, and we log the output to the terminal. The conversion does the inverse of the conversion that happened on the transmitter code. For each byte, it gets the decimal value and then converts it back to ASCII character. If it looks a bit hacky, it's because it is. Remember that the point here is not to make it perfect, but to understand how it works, and then you can improve it in a lot of different ways. Now, let's run the whole thing and see if it works. So I'm running the transmitter code that's going to turn the light on, and I also run the receiver. Okay, the light turns on, and it should start sending characters, and actually, it works. So it's writing characters in the terminal that are sent via light signals to the light sensor. So, the light sensor is decoding the light signal sent by the transmitter into characters that are actually then written in the terminal. So, it does work. That's really cool. Okay, so now the point of Lifeline is to use your existing light to transmit data, and at this speed, it would be super disturbing if your lights were flickering like that. It would be totally unusable. So, when working in JavaScript, the fastest speed I managed to make it work with was using an interval of 60 milliseconds, but that's still too noticeable, because 60 milliseconds is applied ten times per byte. There's the interval for the preamble, then for the eight bits, and finally for the end, when the light is turned back on. So, it's a total of 600 milliseconds per byte. If we send a string of five characters, like hello, it's a total of 3,000 milliseconds, so three seconds. It's definitely way too slow. This is where, if you're interested in experimenting more with this, you need to move away from JavaScript, and you can use Arduino code instead. That's based on C and C++. It's much more suited for a project like this, where speed is super important. I'm not going to go through the whole Arduino code, but here's the link somewhere here to the GitHub repository, if you want to have a look. What I'm going to do, though, is show you the difference in terms of speed. First, what I'm going to do is upload the transmitter code into the first Arduino where the NeoPixel is connected. You can see the light flickering is already much faster than in JavaScript. Then, if I upload the receiver code onto the second Arduino, that should just take a second, and I open the serial monitor, it should be writing hello world much, much faster. As you can see here, it doesn't take the three seconds that it took in JavaScript. It maybe takes, like, a second. Then you can see it's much faster, and the light flickering is much less noticeable. There's still a lot of improvements that could be made, but I'm going to stop here. So, in this video, I explained how to prototype a live fire project with JavaScript, but as you can see, it's not the most performant solution. I use this programming language because I'm recording this video as part of a presentation for a JavaScript conference, but if you want to explore this further, I would recommend using the Arduino programming language. That's it for this video. In a production version of a LiFi system, you would want to be able to send more than only text. You'd want to be able to stream music, videos, and more, but this is something that would require more performant hardware and definitely more time. I still think it's super interesting to be able to experiment with that kind of technology in a more DIY prototype version. I've definitely learned a lot building this, and I hope you did too. Even though it doesn't seem to really be implemented in a mainstream way, the idea of LiFi has been around for a while, and the possibilities are pretty exciting. One of them would be around better in-flight connectivity. So, Wi-Fi can create interference with other radio signals used by pilots, but as LiFi uses another part of the electromagnetic spectrum, passengers could actually have access to the internet using the little reading light that's over everyone's seat. There's many more ideas of how this technology could be used, but that's a cool one. I personally have some ideas of future projects I want to build as an extension of this, but that would be for another video, maybe. I added links to some extra resources in the description, so feel free to check that out if you're interested. But until next time, thanks for watching!