Reliable data transmission

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Ben Eater is absolutely amazing. So many "ah ha" moments in my head as I watch his videos. Things that I thought I fully understood that he takes to a whole other level.

πŸ‘οΈŽ︎ 13 πŸ‘€οΈŽ︎ u/DarkbunnySC πŸ“…οΈŽ︎ Jun 10 2018 πŸ—«︎ replies

Can't wait for the continuation of this. His breadboard CPU series was amazing.

πŸ‘οΈŽ︎ 21 πŸ‘€οΈŽ︎ u/kantokiwi πŸ“…οΈŽ︎ Jun 10 2018 πŸ—«︎ replies

One the best teachers on the internet. Has made learning digital logic engaging and fun. So much respect for someone who takes the time to do something like this correctly. Can’t wait to watch the rest of these.

πŸ‘οΈŽ︎ 9 πŸ‘€οΈŽ︎ u/souljorn πŸ“…οΈŽ︎ Jun 10 2018 πŸ—«︎ replies

Interesting. I like to use serial with the serial.find method. So to send two variables from two different sensors to another micro I would create a string with a trigger letter B, value, a comma, and the other value.

sender

String message = "";  //empty message
String comma = ",";  //string that holds just a comma
String B = "B";      // trigger
int value1 = 255;
int value2 = 777;

message = B + value1 + comma + value2;   //putting together the message
Serial.println(message);  // it will send B255,777/n

receive and parse

if(Serial.available()>2){
if(Serial.find("B"){
int X1 = Serial.parseInt();  //will parse until the comma
int X2 = Serial.parseInt();   // will parse until the end line
}}
πŸ‘οΈŽ︎ 2 πŸ‘€οΈŽ︎ u/yellowsnow2 πŸ“…οΈŽ︎ Jun 10 2018 πŸ—«︎ replies

Can somebody help a newbie, why doesn’t he put a pulldown resistor to ground on the data line?

πŸ‘οΈŽ︎ 1 πŸ‘€οΈŽ︎ u/muff1n_ πŸ“…οΈŽ︎ Jun 12 2018 πŸ—«︎ replies
Captions
Anytime we send information from one computer to another whether that's over the internet or even a simple wired connection like this There's a lot involved to make sure that the information is received correctly depending on the network or or connections involved there are lots of different ways for errors to occur and Often the reliability of a network depends more on detecting and correcting these errors than then avoiding them altogether So for the next couple videos will look at some mathematical tricks that we can use to detect and even correct errors And I'll show you how some of that math can be done really elegantly in hardware with just a handful of logic gates but before we get into any of that in this video I want to figure out the bare minimum of what it takes to send data from one computer to another and for computer I'm going to use these Arduino nanos So what's the most basic thing we can do to transmit information from one of these Arduino and receive it correctly on the other? well, if we're gonna program one of these is a transmitter and that's going to send some data and we'll program the other is a Receiver. Let's start by figuring out how the transmitter is going to work well One of the simplest ways to send data is with one data line that has two levels If it's low that means we're sending a zero And if it's high that means we're sending a one this is a pretty basic method and this is has a fancy name It's called NRZ encoding which is non-return-to-zero Which maybe sounds like kind of a weird name because it looks like it's, you know going between zero and one here So what is this non-return-to-zero business? Well, maybe the the name makes more sense If you look at return to zero encoding which looks like this So there's some baseline voltage level here and then to send a zero It pulses in the negative direction and then to send a one it pulses in the positive direction And then between each bit it returns to zero So that's what this return to zero Business is all about but this is a bit more complicated right because there's three different voltage levels. So we're starting to get outside the world of digital sort of on or off logic So we'll stick with the NRZ encoding where logic low means zero and high means one So let's the first arduino up and get it to transmit some data So i'll connect it to a breadboard here and i'll hook the 5 volt pins and the ground pin up to the power rails of the breadboard and then for energy data we just need a single data signal that we can control to go high or low like this and so we can use any of the Digital pins on the Arduino here. So hook up an LED so we can just monitor whichever data pin we're using And I'll hook this led up to one of these data pins And let's see. I think that's it's like d3 Maybe so our LEDs hooked up to today to pin d3 on the Arduino and then I'll just hook the other end of the LED To ground with a current limiting resistor. I think this is 330. Ohms but anything that's a couple hundred ohms ought to be fine And so now we ought to be able to transmit data by switching pin d3 high and low to transmit a 1 or 0 and then we should be able to see that by just looking at the LED to see if it's On or off and then at least give us a starting place to start to see what what it looks like to transmit some data So let's program this Arduino to transmit some data So I'll start with the pin assignments and we're just using pin 3, so I'll call pin 3 the transmit data And I'll set that as an output pin since we're transmitting then of course We'll need a string telling us what message we want to transmit so go with an old classic hello world We're going to transmit one character at a time. So to keep track of what character we're on Let's loop from 0 through the length of our message One byte at a time Then the actual byte of data to transmit is going to be the character from our message at the current byte index So each time through this loop transmit byte Will be you know one character from from our message we can treat this character variable like it's an 8-bit number that represents the letter since that's actually what It is So then to transmit each byte we'll need another loop to go through each of the eight bits So in here we want to figure out if the particular bit we're transmitting is on or off so to do that we'll take the byte that we're transmitting and Then end it with with a number that has one bit set to see if the same bit is set in the byte we're sending so if we end with eighty hex that lets us test if the first bit is set, but we can then shift that to the shift that to the right to test the other bits So if bedad index is zero, which will be at the beginning of the loop Then we won't then you know, this is shifting right to the zero places Which is not shifting it at all and then we'll test the first bit But then if we come through this loop the second time we're testing Instead of bit zero we're testing bit one, then it'll shift this bit that's set in this 0x80 It'll shift that one bit to the right and then when we end it with TX byte We'll be testing that the spit and then each time through the loop We'll just be testing each bit on down the line through all eight bits So at this point now we're we're looping through our message So we're going one one byte at a time through the message and then for each byte We're going one bit at a time through that byte and then TX bit will be You know at this point in our code TX bit will be whatever bit we want to send So now we just need to transmit that bit and to do that All we need to do is set the transmit data signal high or low depending on the value of the bit We're sending and that's pretty much it. So this will set the value of the TX data signal That's the that's that pin three that we hooked up to the LED It'll set that high or low based on whether the transmit bit is is a one or a zero So this will go through our whole message and transmit our whole message a bit at a time. But unless we add some delays It's going to transmit it so fast We won't be able to see it do anything and also if we don't know how long each bit takes it's gonna be hard for The receiver to know how many bits it's getting so so let's slow it down a bit So to make it easy to adjust I'll define a target transmit rate here in bits per second and just to start out You know relatively slow. We'll start with five bits per second and then we can use this Transmit rate of five bits per second to add a delay right after we output the new data bit so do delay And then transmit rate is bits per second. So a thousand divided by transmitted rate will be Milliseconds per bit and so in this case since transmit rate is is five. So five bits per second This will give us you know thousand divided by five will be 200 milliseconds. So in other words, we're gonna have a Delay of 200 milliseconds between each bit that we output and if you think about it The receiver is gonna need to know this transmitted rate in order to have any hope of interpreting this signal But at this point let's let's give it a try So I'll go ahead and connect the computer here to the Arduino with the USB cable and it's powered up so let me just make sure I'm on the right port and go ahead and upload this and It's done and and right away you can see the LED is blinking. So maybe that means it's signalling each bit. I don't know It's kind of hard to tell Yeah, if it's if it's actually working right It does seem to be outputting something Sort of random ish looking but it's hard to hard to keep track of what it's doing if you can't kind of look at it You know five times per second and see exactly what state it's in which is pretty hard to do just by looking at it Although it. Looks like it's done sending the message and it's just stuck on At least I'm assuming that's what happening is is that the last bit was a one? But one thing we can do to check if this is working, right, you know, well, we could slow it down, you know Maybe slow it down. So it's sending one bit every five seconds And then that would give us more time to to actually consult a stopwatch or something and and watch it But that's kind of a pain So what I'm gonna do is I'm gonna hook it up to an oscilloscope that will actually graph the voltage over time And give us you know a way to quickly see exactly what it's doing and so now if we look at the scope what we see is we see that our Our voltages is up here at five volts. So zeros here in the middle, and then it's two volts per division So 2 volts four volts and then a minimal and this is almost 5 volts here And so it's just constantly here at 5 volts and it makes sense Right because our LED is on so we're outputting the high voltage here So we're seeing 5 volts here And then the way I've got this set up now is each of these divisions across this 500 milliseconds. So to two squares across Is going to be one second and then and I can also do a single shot here that will stop it and then it'll start Once it sees a a transition So now if I reset the Arduino, so it reruns that program and then outputs that data again I'll reset it and then when you see it starting to output the data And I'll see on the scope that it's going high and low so we can actually see exactly what the LED was doing So we take a closer Look at this we can try to figure out if the right data is being sent now Since each horizontal division here is 500 milliseconds. That means this is one second Now since what we think we're doing is sending five bits per second Well, then we ought to be able to interpret this one second interval as five bits So it looks like we've got one zero zero one zero here So, let's see if that matches what we expect and we're sending the message helloworld So the first letter we're sending is a capital H. So we take a look at an ASCII table it looks like a capital H is encoded as 72 in decimal or 1 0 0 1 0 0 0 in binary and sure enough. That's what we see though We're sending each character as 8 bits and this is only 7 bits So presumably we need to include an extra 0 here at the beginning And so now this is the first byte of our message Now one thing to notice here is that it's not all that clear how to know where our message starts I made a video a few years ago about framing that talks about solving that particular problem But for now, we'll just assume that we know how to find where the first bit is So this is the first byte of our message then the next byte will just be the next eight bits So that looks like 0 1 1 0 0 1 0 1 which represents a lowercase e? Then the next byte looks like 0 1 1 0 1 1 0 0 which represents a lowercase L? So sure looks like it's starting to spell out hello world So it's great that we're able to verify that everything's working with this scope But you know if you don't have a scope or certainly, you know As we as we start to make this thing a little bit more complex and want to keep troubleshooting it it's gonna be kind of a pain to have to hook that back up and Interpret the the bits just from looking at the graph there So what I'm going to do instead is hook this LCD panel up to up to the Arduino and then what we can do is update this LCD screen to show exactly what data we're sending and What we're doing? So it'll be a little bit easier to tell what's going on And the way this LCD works pretty easy to interface with the Arduino. There's a bunch of pins that you can connect here But if you're not doing anything fancy with the LCD Which which we're not planning to do we just need to connect pins d4 d5 d6 and d7 Just four of the data pins. And then there's the RS pin the register select pin and the enable pin I think those are the only six pins that we need to connect to the Arduino and then there's a few other things we need To hook up, you know power and things but we'll go through all that. So I'll start by disconnecting the USB here So and then a pin pin d4 on the on the LCD, I'll just hook up to d4 You know data data pin 4 on the Arduino and I'll do the same same thing for d5 Just hook up d5 to pin 5 on the Arduino Hook up pin 6 to pin 6 on the Arduino and hook up pin 7 to pin 7 on the Arduino so those are those are the four data pins just D 4 5 6 & 7 that we need to hook up and we also Need to hook up this RS pin, which is register select And so I'll just hook that up to pin 8 on the Arduino It doesn't really matter which pins as long as we're hooking these up to some digital pins in the code will tell they are the the LCD which pins it's using and then finally the enable pin is We need to hook that up as well. So I'll just hook that up to pin D 10 on the Arduino So those are the only connections we'll need to the Arduino. But of course, we also need to give power to the LCD So the VSS pin goes to ground and the VDD pin goes To five volts and then you know because we're not using the full functionality of the LCD We're only gonna be writing to it. We aren't reading from it. It has some internal memory and stuff that we're not going to use There's this readwrite pin So if we just tie that to ground the RW pin Tie that to ground that just means we're always gonna be writing to it to do that We only need four of the data lines and then there's this pin v-0 which is used for setting the contrast and And typically what you do with that is just hook it up to a variable resistor I have this little potentiometer that actually came with the LCD the LCD comes with a potentiometer at least where I got it So I'll just hook through the potentiometer to ground and then we can we can adjust that to adjust the contrast and then finally, there's this a and K which are the anode and cathode of the backlight LED and So we want to hook power up to that So hook the cathode of that backlight LED to ground and then the anode we want to hook up to five volts But of course we need a current limiting resistor. So I'll hook hook that up there And I think that's a 330. Ohm current limiting resistor But anything, you know a couple hundred almost ought to be fine. And so there we go So look at this back up. We see the back light comes on Of course We're sending our data but nothing's gonna display on the screen because we haven't written any code to use it But let's go and take a look at that And for the LCD, we're just gonna use a library that does most of the work so if you got a sketch include library manage libraries I just want to make sure there's this liquid crystal library and make sure that's installed so we've got that and Then we just go up to the top and we'll include that and then I'll define the pins that we're using So we've got LCD you know d4 through d7 are the data pins and then LCD RS is the the register select and we hook that to pin eight of the Arduino and then the LCD enable pin we hook to pin nine of the Arduino and so basically before we Do our transmit loop here I'll just initialize the LCD and so you just define this object and then in the constructor We're going to send in all of the pins that were that it uses So the RS pin en pin and then LCD d4 d5 d6 and d7 the data pins So that will initialize the LCD and then that'll give us this LCD object that we can do things with so we do begin and Start by telling it how big the LCD is so we have a 16 character by 2 line LCD There's a bunch of different commands and you can you can look up online how this works But do LCD set cursor will move the cursor. So 0 0 will be the top left And then what I'll do is I'll just print the message that we're gonna send and so I'll just put the the message this message Helloworld, that'll put that on the LCD and then on the second line of the screen I'll just have it print out each bit as it sends it so go to the go to this second line And the column will be the bit index So that'll start it at bit 0 and then move You know a bit 1 2 3 4 5 6 7 across and then that'll be on the second line Which is starts at 0 so line 0 would be would be the first line. So now we're on line 1 It's the second line and then we'll print the the bit so TX bit. It's a boolean So if it's if it's true, then we'll print a 1 on the rise Well print a 0 so that'll that'll output that bit on the second line And then what we'll do is after we've output the whole the whole character and we move on to the next byte I'll clear the second line. So here clear the second line of the display so we'll just go to 0 1 so that's the the beginning of the second line and just print 8 spaces to just write over the Zeros and ones that we might may have printed there on the previous character and then the only thing I can do is the LCD has this cursor feature which will actually put a little Underscore cursor on a character and so what we can do is we can keep track of which Byte. We're sending by by moving the cursor along underneath the character of our message But basically every time I print what I want to do is move my cursor back to the character that were that were currently at working on So I'll set the cursor to point to the byte that were they were writing on the first line and then you just say LCD Det cursor that'll turn the cursor on and then we'd really want to turn the cursor off when we're doing other things That's no cursor. Same thing down here So just copy these and then when we update the display here We'll go back and highlight the byte that we're sending and then same thing here turn the cursor off before we start Hopefully this all makes sense Once you see it actually working and I really want one other thing I'll do is at the very end here I'll just turn off the data bit because you notice now it just sort of ends either on or off depending on what data we Happen to be sending so this will just turn it off when it's done So let's go ahead and upload this and see if it works No, it looks like I missed a semicolon. Oh I missed a period There we go Yeah, it's a programming And there it goes now, it looks like it's outputting something and you can see that that cursor moving along showing, you know Which which character it's actually outputting and you can also see the ones and zeros That are being printed as it as it outputs each bit And so this should be easier to keep track of because you can see when it outputs a zero the L You should be off and when it outputs a one and we should see the LED on so even if you don't have an oscilloscope You know if you slow the clock down a bit It should be fairly straightforward to To match this up and just to verify that it's doing what we expect it to do and then once you verify that it's outputting The right bit so you can also look and see you know, so this is you know, what is this value? This is 32 plus 1 is 33 so the last at least the last byte it out put it was a 33 and 33 is in fact the ASCII value for an exclamation point so you can also verify that so the LCD makes it a lot easier to just you know both see what's going on as well as troubleshoot this so great now that we've built something that will transmit this hello world message using NRZ encoding now, let's move on to building receiver And so for the receiver actually The hardware is gonna be the same because most of the hardware here is for the LCD and and the receivers gonna have an LCD As well so, you know It's gonna be hooked up the exact same way and then the transmit signal instead of being a transit signal Then we've got a receive signal but I'm still gonna hook it up in the same place. I'm gonna hook it up to d3 but now d3 will just be an input instead of an output and we'll hook the output of this over to the input here and That'll be the input now for our receiver. But otherwise the hardware is gonna work the same way So really the only difference is, you know I'm using a green LED here Just so that once I program them I could tell which ones which because there certainly could be programmed differently But other than that the hardware is gonna be the same so I won't walk through building all of it But it is going to be programmed completely differently. So let's go ahead and program the receiver So for the receiver, we're just gonna start a new a new sketch and we'll start by defining the pins and actually we can copy a bunch of that from our Transmitter because our pin assignments are going to be pretty much the same because most of them are for the LCD The only different one is going to be the transmit data is now going to be receive data so pin 3 is going to be for receive data and Then in our setup we'll want to set our pin mode Or that rx data pin and receive data pin to be input. So this is obviously a big difference right now Our receive data is an input pin rather than over here We had our transmit data which was an output pin, but then beyond that we can also copy some of the LCD stuff So a copy the include therefore liquid-crystal library And then the initialization here is also going to be the same Although I'm gonna put it outside the setup here so that we have a global variable because I want to be able to use this LCD variable from Inside the setup as well as in the loop because we're actually gonna be doing all of our reading in the loop here But we do need to setup the LCD in our setup and that's just the LCD 16 comma to tell it that it's a 16 Character wide by 2 rows and then, you know, our receiver also needs to keep track of our message So we'll define a character string will just say 16 bytes for now And this will be the the message that we're receiving Although in our setup to start out with we'll start with that string as empty because we haven't received anything yet And then in the loop What we'll do is we'll add characters to that message string as we receive them so we can have a boolean which is our received bit and that's just going to Equal whatever value is is on the RX data signal line. So we do in our digital read for the RX data pin That'll tell us what bit is there. But of course we want to do this at the right time So we'll put a delay in here of 200 milliseconds because we expect to receive a bit every 200 milliseconds And so that's pretty much it. We're receiving these bits Of course, it's not very useful. If we don't do something with them and actually display what we're receiving so what we need to do is we need to take this bit build a byte from that as we receive bits add it to Our message and then output all of that to the LCD screen so what I'll do is I'll define a byte which is our received byte and that can start equal to 0 and then also define an integer for a bit position We'll start that equal to 0 as well so that tells us which bit we're on because we're gonna be receiving these bits one at a time and Then for every 8 bits we want to make a byte. So what we'll do is Say if the receive bit basically means if it's a 1 so if it's on you know if we if we if we read a high value then what we want to do is we want to take our Rx byte and flip the the bit corresponding to our current bit position So what we could do is we can or it with a value that has the the current bit position set So if we do is 0 X 8 0 that'll be the first bit But then we can shift that right to the bit position that we're on and then you know bit position We'll just go from zero to seven So for our first bit, you know It'll be zero and and this will basically flip on that first bit in the receive bite and then the next time we come through the loop we'll do is Increment that bit position and so the next time through the loop bit position will be one And then it'll shift this zero eight zero to the right so it'll be zero X4 0 and then if that bit is said it'll flip that bit and then next time through the position will be two And so on and it'll it'll flip those bits one at a time and then what we want to do is if we come in here and If bit position is eight, then we want to set the position back to zero Of course the other thing we want to do once we wrap around is set our byte back to zero because The way we're building this byte is it starts at zero and then we just only flip on those bits where the bit is is a 1 and so as we receive this byte if we get to a point where we've received the whole byte, so if If for a bit position 8 here after we've received a bit So we've received that 8 bit then what we'll do is we'll concatenate on the byte that we got so take our message and concatenate on the the received byte and that'll just be one byte that will that will stick on there and that ought to basically be it in terms of Receiving that message and building it up But of course we want to output stuff to the LCD so we can actually see what this is doing We'll start by going to the the top and printing the message. So whatever our message happens to be at this point in time We'll print that out and then we'll go to the second line and then we basically just to print each bit So we'll do a for loop here to go through, you know, all eight bits and then we want to print that bit so the LCD dot print and then The receive byte but then we want to figure out if the if the bit is set So we're going from you know bit, you know 0 through through 7 here, basically So we want to check if that set so we can end the the byte that we've built up so far by 0 x8 0 shift right eye and that'll that'll tell us if the ithe bit in receive byte is set and Then if it is we want to print a 1 otherwise we'll print a 0 but You know, of course, we may not have received the whole bite yet So we only want to print a 1 or a 0 if we've actually gotten that far through the byte so if we say if I is Less than our current bit position, right? Because if we've only received four bits of the byte, we only want to print those four bits. Otherwise, I'll just print a space Overwrite anything that might be there and so that should output Yeah, so that should output our message on the first line And then on the second line It'll output the ones and zeros that we've received so far of the current byte And then I can also set the cursor to show just where we are in the message although in this case It'll always be just the last character that we're receiving but I'll do it anyway on the first line and then turn the cursor on And then before we do all this mess, I'll turn the cursor off so that should be that should be everything so this this this loop function You know that Arduino is automatically going to call that as fast as it can so we'll you know delay 200 milliseconds and then receive that that bit use that bit to build up a byte add that byte to our message and then just sort of print out where we are and then it'll just go back to the top of the loop and wait another 200 milliseconds and get the next bit so let's connect our receiver and program this so plug that in and upload And There it goes and you can see it's just printing zeroes, you know, which which makes sense, right? Because this is our input and our input is just low. So it's looking at that every 200 milliseconds and every 200 milliseconds It's low. So it reads in a zero, so we're just getting a bunch of zeros So now let's hook it up to our transmitter and send it some data and see if we can get it to receive that correctly and so I basically just want to hook up a wire between the data signal on the transmitter here and the data signal on our receiver And because our signals a voltage and a voltage only makes sense as a difference of potential Both of these need to share the same ground potential So in practice what that means is that our transmitter and receiver need to be connected with two wires one For the data signal and then one for the common ground So let's power these up and see if it works. So I'll just connect a five volt power supply To our receiver and we see it's receiving the zeroes And then I'll connect power to our transmitter And we can see it's starting to receive some zeros and ones But the message that we're getting looks to be just gibberish. So what's going on there? Well, of course what's happening is the mitr is sending each character as eight bits and the receivers receiving those eight bits But the eight bits aren't necessarily lined up that is to say like the eight bits that make up the h-here that we sent You know, some of those bits might have been received, you know partway through a byte here And so and so those bits got shifted over and so this first byte which is this weird little character here Might have just been some of the the bits at the end of the H and then the next character which looks like a blank might have been You know the rest of the character of the bits from the H and then some of the dips from the e and so forth And so if it doesn't line up, you know, obviously we're not going to receive the same thing So what we can do is it you're trying to get these things in sync we can reset both of them at the same time And let's see if we could get it to be synched up There's the H so it looks like we're doing okay there and now it looks like it's working But what happened here it looks like we were receiving things just fine but then It looks like things something went off the rails. So what's going on there? Well, if we look back at the code, there is there is something that might be a problem which is when we're transmitting Let's see here. We are transmitting we've got this for loop and we're just going through each bit and We're writing and updating the LCD and then delaying this is going to be 200 milliseconds When we're reading we're delaying 200 milliseconds And then we're we're reading the the bit and then we're also updating the LCD But we're actually doing a little bit more processing here we have this for loop We're printing a little bit more here, and we're also moving the cursor and we're printing the whole binary. Whereas here We're only printing one bit. We're moving the cursor. We're printing one bit and then we're moving the cursor back But we're doing less here when we transmit and so even though our delay statement is the same, you know This is going to be 200 milliseconds and then our delight delight statement when we receive is 200 milliseconds There's some extra delay in our receiver because we're doing a little bit of extra processing So if we reduce this delay Instead of 200 let's make that like 198 maybe So let's give that a try. I'll reprogram the receiver so plug in the USB here and hit upload And there we go, so now we've got the slower slightly slower speed here, so maybe this will be better in sync So let's reset both of them and give it a try So far so good Huh and looks like that's not quite enough. I don't know if I'm too slow or too fast. Let's try one 96 upload that Okay, now let's just reset both of these and see if that's better Well, it certainly looks a lot better this is a lot more promising right? Oh But Almost what happened here. So this last thing it's last character instead of an exclamation point we got a quote We almost made it to the end So what's going on here? and the reality is is actually this delay thing is is really a bad way to try to synchronize these things because you Know we really don't know how much time this processing is going to take so we could tweak this and maybe get a little bit Better and get a little bit longer message But this is hardly what I would call a reliable Means of communication here because this is only going to work for a little bit while these things stay in sync but eventually they're going to get out of sync so Delay, really isn't the right way to ensure that we're reading at a fixed time interval Now there are better ways with arduino to do that So one would be using timer interrupts and with timer interrupts we can have the arduino run code exactly over 200 milliseconds so we could have the transmitter transmit a bit exactly every 200 milliseconds and We could have the receiver read input exactly every 200 milliseconds and when I say exactly every 200 milliseconds I mean as exact as the Arduino can possibly get Using the clock oscillator that that's on the Arduino, which is this little ceramic resonator Which is this little thing here that's gonna isolate at 16 megahertz So how accurate is the clock oscillator on the arduino? Because that's going to tell us the best case we can possibly do in terms of getting the timing synchronized between both of these We can actually look at that by hooking a our oscilloscope probe up to it And then if we look at the oscilloscope, we can see well, here's our 16 megahertz clock looks pretty good But let's actually measure to see how close it is to 16 megahertz. So we've got our frequency here turn that on to channel 1 And it looks like it's fifteen point nine seven nine megahertz so not exactly 16 megahertz And I wouldn't expect it to be exactly 16 megahertz because these ceramic resonators that are on these Arduino Nana's aren't the most precise clock source in the world But the real question is how different is the clock on the receiver here from the clock on the transmitter? So let's look up another probe to the clock on the transmitter just to compare and so now that's hooked up Let's turn on channel 2 and compare It's already we can see we're getting something here, but it's not in sync with channel 1 which I wouldn't expect You know, there's no reason to expect these clocks to be in sync, you know, we can change our trigger here So if we trigger on channel 2 We can have channel 2 in sync and then channel 1 goes out of sync But you know, so that suggests that they are different frequencies, but let's actually measure and see how different they are So we go back to our measurement frequency counter here. So channel 1 was fifteen point nine seven nine megahertz and channel two is sixteen point zero three mega or zero zero three megahertz So they are different but how big a difference is that? And and does it matter for what we're trying to do in terms of transmitting data from one to the other Well, if you look at the difference here it's about 0.15 percent. So how big a deal is 0.15 percent? 0.15 percent another way to look at that if you if you take one over 0.15 percent you you get about 667 so what does that mean? That means if the transmitters the faster one, which it is then for every 667 bits that the transmitter sends the receiver is only going to try to receive 666 bits so that means we're gonna get out of sync in under 666 bits. So that's obviously no good So it looks like unfortunately we're out of luck If we want to use this NRZ encoding just by itself, you know, maybe better clocks would help a little bit But they're only gonna get you so far and actually as the bitrate is faster as we send more data faster than the importance of having those clocks synchronized becomes even more important because the shorter the time interval between The bits the more important it is for both sides of this communication to agree on how how long that interval is So trying to improve the clocks is kind of a dead end unless you go for atomic clocks or something, you know completely unreasonable but what is very easy and very common is to send the data like this, but then also send a clock so Essentially, we'd send two signals that would look something like this We'd have the data which looks just like our NRZ encoding In fact, it's exactly the same but then we have a second signal that we would send which would have a clock and then the clock would just pulse on and off and then the other Receiver could then use that clock to figure out when to read the data and so then it doesn't matter if the internal oscillator if those are off by a little bit because if the transmitter is sending its own clock along with the data then you can just recover that clock and read the data using that clock and this is actually pretty easy to implement the only downside is that instead of having one data signal and then of course the ground will have two data signals or while a Data signal on a clock but two signals plus the ground So it does take a few more wires to transmit this way, but for our little setup here, that's just fine So for a clock signal that's just going to be another pin coming off for Arduino here So, let's see if we're using pin three for our data then We're using pin four five six seven eight for the LCD now Let's use pin two for the clock and I'll just hook that up to another LED over here Because this is just going to be a second signal that we're gonna send across from our transmitter to our receiver And just like before I'll connect that led to ground through a current limiting resistor. Again. That's a 330 Ohm resistor and same thing here on the receiver I'll connect pin two in the same way to an LED down here and Finally instead of just these two wires connecting data and ground. We're gonna need three wires connecting clock data and ground so hookup clock data and ground on our transmitter and then the other end here I'll connect clock data and ground on our receiver and So, there we go Now we have our new clock signal and of course a new connection between the transmitter and receiver Because we now need a third wire for our clock So now let's go ahead and program it. So now to add the code to send the clock I'll start with the transmitter We've got another pin assignment here transmitted clock is on pin two We'll want to set that to an output pin So pin 2 will be an output pin on our transmitter and then when we transmit here We're out putting our data bit and then we basically want to then pulse our clock. So I'll put the clock And then low so once our bit is set on the data line Then our clock goes high and then low to signal that we've got a new bit there But I am going to tweak the timing a little bit here. So what I want to do is Instead of having our whole delay down here at the end What I'll do is I'll put a delay right after we set the bit and I will delay for half of our delay time then Then I'll update the LCD Then we'll pulse the clock and then actually while we're pulsing the clock the clock will go high For the other half of our delay and then go low. So what we've got here is We're transmitting our data byte or bit rather one bit at a time here We're transmitting our data bit And then we're delaying for half of our bit time then updating the LCD to say that we're sending the bit And we do that right before we actually pulsed the clock high which is which kind of moment that the bit is Is being sent if you will and we pulsed the clock high Then wait for the other half of the the bit time and then the clock goes low. So that'll be the transmitter Let's upload that and give that a try And there it goes and You know we can see It looks like it's transmitting hello world and now we can obviously see the clock is flashing and so every time this flashes that indicates that we're sending a bit and Just so we're clear what that looks like. We can hook this scope up to that as well So look one probe up to our clock line and then hook the other up to our data line So the scope hooked up we can see both of them are currently 0, but if we reset actually, what I'll do is I'll single-shot this and then reset 1 starts transmitting again and there we go We're capturing and you can see the clock on the top and then the data on the bottom If we take a closer, look there's a couple things I'll point out first it's easy to pick out each bit of data just by looking at the points where the clock goes from low to high the Receiver doesn't necessarily need to know anything about the expected timing. In fact, the other thing I'll point out Is that while the clock looks pretty good on the left here where it's lined up with these 500 millisecond grid lines There's another of a skew that we get over to the right side here and you can see the clock doesn't even line up with Those 500 millisecond grid lines anymore So we're definitely not doing a great job of hitting our target rate of five bits per second, but that's okay we're sending our less than perfect clock and it's the rising edges of that clock that matter and as long as the data bits always line up with the clock then it's okay if the clock drifts a little bit and this is A really important aspect of engineering to design systems that can deal with things going wrong or or deal with imperfections like this so in this case It's timing and you know because our clock doesn't have to be perfect we can get away with cheaper or less accurate timing hardware but of course at this point we're still not using the clock for receiving so we still may Get some of these errors like this if we're not perfectly synced up So let's take a look at what we can do about that So if we come over to the receiver here, you know currently we've got this loop where we're delaying, you know Approximately the right amount of time Between bits and then reading and then reading the bit But what we want to do is we want to read the bit When the clock transitions high and there's actually a really cool way to do that with your do we know which is using interrupts? So the Arduino supports these pin interrupts basically the way that it works is you define a function that you want to have called when a pin transitions so we can make a Function called on clock pulse and then what we can do is in the setup here. We can attach an interrupt Yeah And the way this works is you have to pass in the the interrupt Number which you can get using this digital pin to interrupt function and then you pass the pin number That'll give us the interrupt number that we want to attach And then you you give it the function name that you wanted to call So if we say on clock pulse then that's going to call this on clock pulse function When something happens with our received clock and then we just need to tell it what we're interested in So in this case we can say rising and that means when the receive clock signal rises that is it goes from 0 to 1 Then call this function And then of course in this function, that's when we read our bit. So basically we can take all of this stuff Well, maybe not the LCD stuff, but we can take all this stuff We read that bit and move it into this on clock pulse function The basically this says you know, essentially we won't do anything in our loop we get rid of this delay I suppose we won't really do anything in our loop maybe still update the LCD there But we won't read any data in the loop what we'll do is we'll only read data in this on clock pulse function and that function is only going to get called when the the clock pulses so in this on clock pulse function We'll do all this all this stuff we're doing before so we'll say well read our RX bit received a bit We'll update our bit position if we're if we're at the end of a bite Otherwise, we'll update our bite And increment our bit position and then if we've gotten to the end of the bite Then we'll update our message and add the new the new bite to it So then what do we want to do in the loop? Well, I guess we still want to update the LCD, but we don't want to just update it constantly. So what I can do is Create a variable. I'll call it LCD update out LCD and Start off as true, and then the loop we can say if update LCD is true then update the LCD so basically in our loop we're only going to do anything if this update LCD saying is true and if it is then we're gonna Well update the LCD But first thing we'll do is set that to false So if update LCD is true then we'll set it to false and then update the LCD and then at that point our loop isn't going to do anything and then We want to change this to true when we receive a bit. So here in our in our on clock pulse when we get that clock pulse will receive the bit will update our Bit position will update our message will update a received byte And then we'll say update LCD equals true and then the next time through the loop It'll it'll update the LCD We don't want to actually update the LCD in this clock pulse because this is an interrupt Handler and in an interrupt handler You want to keep it pretty tight? You don't want to waste a bunch of time in the interrupt handler But also the LCD library might might actually make use of interrupts And so if we're calling it from inside an interrupt handler, then interrupts will be disabled and it may not work so it's best to To not do very much inside an interrupt handler to sort of update your data structures and then set some flag that we can then Use in our loop One other little gotcha with interrupt handlers is any of the variables that we're modifying in the interrupt handler? I'll set this volatile keyword on here and that basically just tells the compiler You know don't try to do too much optimization with these things because there's an interrupt handler that might be mucking around with them when when when you don't suspect because the compiler doesn't know exactly when this interrupt handler might get called because you know We don't really know until the hardware actually calls it. So anyway, that should that should do it Let me connect the USB to the receiver there and upload this code Our X clock is not declared No Thought I define that Guess not and there goes and so there we go. And the first thing you'll notice is that we're not receiving those zeros anymore So remember before every 200 milliseconds would look at the data signal and if it was low You know would say well must be receiving a zero and and we just, you know receive a zero every 200 milliseconds But now it's actually waiting for that clock so we don't see just printing those zeros like it was before The other nice thing about that is that it's also not only waiting for the clock to receive a bit It's it's waiting for the clock to receive the first bit And so we don't worry about keeping them in sync by resetting both of them at exactly the same time So it's already just waiting for that first bit of the first byte So if we just reset the transmitter then as soon as it starts sending it starts receiving a bite and the byte is always going to be aligned just just perfectly and So now we see we're receiving the message just fine. And in fact, we should continue to receive the message just fine I wouldn't expect any problems now that we have the clock in there to keep everything in sync and so we can continue we can just reset this and reset the transmitter whenever we're ready and Retransmit that signal and we should be able to do this all day We should have no problems transmitting this because we've got the clock will keep everything in sync Doesn't matter if the timing is a little bit off we really should have no problems with this at all However, there are still things that could go wrong So it's always possible that an error introduces itself into the transmission and that's the case any time that you have any kind of communication network is always a chance for Errors to crop up but what happened here? Well, I did something a little bit sneaky, um the connection between the transmitter and receiver I have this little button In here that I can push that interrupts the data signal and so I can actually cause it to miss bits By pushing this and so I had that off frame and and just introduced a little bit of a bit error Right there in the middle of the message and you might think well, that's not very realistic I mean how often you're sending a message where someone has a you know a way to Interrupt the message while you're sending it But the reality is any communication system is susceptible to errors and in fact any communication channel has a theoretical maximum Bandwidth and particularly as the bitrate gets close to that theoretical maximum then the channel becomes more susceptible to noise and Noise can cause errors where you miss a bit or something something is off a little bit And so I put this switch here, obviously when we're sending five bits per second over just a short distance We're over not anywhere near close to the theoretical maximum here But I put this switch here to simulate that because you know in high speed or wireless networks, things like that it's very common to get errors and what I want to talk about in the next video is how do you detect those errors because what happened here is the transmitter sent a series of bits and the receiver actually received a different series of bits and You know I mean you can look at this and say well that's probably not the message that we intended to send But as the receiver, how do you know that you know? This is certainly a representation of the bits that the receiver received. It just happens that Interrupted some of those bits and so we got a little bit weird a bit of a weird message But is there a way to tell with you know some amount of certainty on the receiver side here that yeah We got these bits, but the bits were wrong well it turns out there are a number of different ways of detecting that and figuring that out and and knowing That maybe you need to ask the transmitter to retransmit the message or even knowing how to reconstruct the correct message with Incomplete data and so that's what I'll be covering in the next video. So this video was really just kind of a lab setup I guess where we're just setting this up particularly with this ability to introduce these errors so that we can explore a little bit deeper in the next video how to How to detect those errors and perhaps even how to correct them in future videos. I Want to thank my supporters on patreon who are helping make more of these videos possible. I particularly appreciated their feedback on this video Specifically I asked them if I was hitting the right balance between taking the time to walk through every step of the process While keeping it engaging the overwhelming feedback was very positive But I love more feedback if you've got a different perspective and if you'd like consider supporting me on patreon if you're able if not That's totally cool I know there are a number of people who support this work Explicitly to make sure that it's free for others who aren't able to support it directly. So definitely an extra. Thank you to them
Info
Channel: Ben Eater
Views: 814,891
Rating: 4.9648895 out of 5
Keywords: NRZ encoding, data transmission, data clock, error detection, error correction
Id: eq5YpKHXJDM
Channel Id: undefined
Length: 43min 54sec (2634 seconds)
Published: Sat Jun 09 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.