Raspberry Pi & Python SPI Deep Dive with TonyD! @adafruit LIVE!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Music] oh [Music] hey everybody it's Tony from Adafruit and hopefully that intro works so I've got a whole new streaming set up and as you can see it's pretty crazy I've got like a little retro terminal thing going on in the background uh and today I wanted to talk a little bit about SPI this serial peripheral interface and last week I had done a deep dive on the i squar c protocol so I think it makes sense to follow it up with looking at the Spy protocol using the raspberry pi and we'll look at uh how to talk spy using Python apis and maybe even look at a deeper level in Linux how it's all implemented um but first I'll give you a quick kind of rundown to of what I've got with the setup so I upgraded everything I'm using uh wirecast now to do the streaming so it's pretty fancy um there probably will be issues in things so just kind of work through it as we go but hopefully I'll be able to do some cool stuff here um in the background it's actually a little video uh that I shot uh from my desktop from Linux it's this program called cool retro terminal that gives you like a retro style CRT image uh and then I'm running a little program called C Matrix that gives you the Matrix effect back there so I just kind of screen captured that and have it as a background uh but everything else should be uh ready to go so I've got um main desktop kind of view we'll come back to this uh in a little bit and I can pop up also uh the head down here and then I've also got a workbench view so we'll see and of course got the logic analyzer and it's not really in focus for some reason uh still working out some bugs and issues but this is uh Raspberry Pi here's the pi zero and it's connected to I have both the ads uh 1015 that we were looking at last week with iqu c and then also I have a little mCP 3008 analog to digital converter uh this one uses the Spy protocol so we'll kind of play with that uh investigate it so let's see so I've got that and let's maybe jump uh back to the desktop view here so real quick kind of before I dive into the spy stuff uh last week I talked about I squ C and we kind of looked at I left it at a point where I started to investigate using IO control functions uh to talk directly to the i squ c Hardware on the Raspberry Pi at least the device driver uh and I done some little prototyping with that and had a basic example and this week I've kind of spun it out into a little Library that's it's a work in progress right now um but it's basically a little python Library here I called the python pure iio and it's meant to be a pure python uh access to i squar c and eventually spy maybe even gpio um you know just have to look and see what's available and kind of standardized on Linux and the reason it's pure python is because like that basically means that there's no native extension that you need to compile um you can just install this with Pip and it just uses python libraries to talk directly to the hardware uh because the big problem I was talking about before with the i squ c the python smbs Library it's sort of maintained it's a little hard to find the owner uh it's not Python 3 compatible so it's a bit of a pain uh to deal with and if you make a pure python version of that then it's a little bit easier you can make it work with python python 3 uh might not be as performant you know they tradeoffs of these things uh so this uh this is a link it's on our GitHub repository it's the Adafruit python p. and once this video is on YouTube I'll put in the description links all these things too um I kind of put a note here that you know this is a work in progress so it's definitely not uh fully kind of ready to go yet but it's a good example if you just kind of want to check it out and see um you know how I'm using IO control and C types uh so I basically fleshed it out and I have an SM bus class that's a direct copy of what the python smbus Library exposes so all of the same functions you know like reading B reading B of data uh I've reimplemented those using IO control functions against the iqu C Hardware uh and so I have some little helper functions that make it easier uh turned out to not be as difficult as I thought like let's see this is only um maybe 300 lines of code or so uh there's one function I didn't Implement yet because I actually have to get in at a much lower level and the io control stuff doesn't work I have to use a different IO Control Function U but it's it's not a really commonly used function it's reading a block of data which is sounds like it's important but it's a really weird format where a block of data like the first bite indicates how much data is going to be read and I don't know of any I Square C devices that use that but uh I'm sure there's stuff out there I mean there's a reason they added it but anyways though so it's a good example to kind of look at um it does work so I'll I'll kind of uh we'll jump to the pi so I swapped over my gpio library that all of my Raspberry Pi Library use and I made it use this new uh pure IO for smbus and it was just a direct swap so like in the code um I'll actually show you so the gpio library code um for i squ c so previously I was importing SM bus Which this is the uh python SM bus module that we looked at before and I just swapped it over to import my new pure iio SM bus and just renamed it the same thing didn't change anything else in my code here so it's it's calling all the same functions you know like read bite read bite of data doing the same Transformations uh and it actually does work now it's it's a little unstable uh I ran into a problem I need to debug a little more um but if I go into the uh python ads and the examples and if I run the simple test uh so this is actually outputting data you can see it just uh exploded at least got two readings uh so it it's something funky about um the format of the data I'm returning and it's working sometimes I have a feeling like maybe it's getting like a null value somewhere and my behavior is slightly different so it's it's close it's kind of coming there and eventually you know I'll kind of sort this out and have this available as a little pure python library because I'd like to eventually move all of our python libraries to depend on this pure python implementation so that way uh it can actually work with Python 3 uh it's you know we have a little more controller over it we can add more functions to it that we need uh and it's easier to install so you don't have to have like the python developer tools and things ready to go for it so um that's just a little update on that so what I wanted to talk about for this stream is looking at the Spy protocol the serial peripheral interface bus um and so spy is just another way for a chip to talk to another chip so it's a Serial protocol which means there's a clock uh that's driven to kind of synchronize uh how the two chips talk to each other other and like last week we looked at the i squ c protocol which is a neat little protocol um it just uses really two main lines for the data there's a clock line and a data line and it has a concept of addressing so you can have like up to 128 devices all just sharing those two lines now the Spy interface is a little bit different so it's uh it's still a Serial protocol there's still a master who controls a clock uh but it actually has more lines of data so there are four lines that you primarily deal with so there's the clock block line still uh there's also a chip enable line which kind of tells a chip that it's going to receive or send spy data and then there's a data out and a data in uh line kind of like a Serial protocol uh and unfortunately they're always a pain because you need to kind of think about okay from whose perspective is that data an input or an output uh and so sometimes you see like mosy Master out slave in or miso master in slave out and in that case the master means the clock master like who's actually driving the Spy bus clock and with the Raspberry Pi in almost all cases it's the Raspberry Pi itself like when you're talking to peripheral the pi has to control the Spy bus uh so in that case you know the data output would be the pi outputting data to a chip and the data input would be uh reading data from a chip to the Raspberry Pi uh and so we'll kind of see that as I look through uh as we look at more of the examples and things here but the Wikipedia page um is again it's pretty good just to kind of skim and get in over rview about the protocol so it talks about you know at a physical level how it works uh you know really just those four lines now the one big difference with iqu C is that each chip needs an individual chip select line that goes directly to it to talk to it so if you had like four devices that use spy and you wanted to talk to them using Raspberry Pi you'd have to have four different chip select lines because each time you want to talk to a chip you have to toggle its chip select line uh and so you can't have multiple chips sharing that or else they'll get confused and they'll see that oh you know I'm being told that I'm having something you know sent to me but I don't understand it uh so that's one big difference um another important difference is that the master has a lot more control in the Spy interface over things like the clock speed um I don't know if the protocol actually has any limits on the clock speed you know it can go well into the upper megahertz um the Raspberry Pi supports um I don't know what the slowest speed is that's I'm sure it's like maybe down like the kilohertz or so uh you can actually find the BCM 2835 peripheral reference manual that's kind of the definitive reference of uh all the Proto all the peripherals on the Raspberry Pi I'm sure it says like what the limits are for this spy Hardware but it can go up to um I want to say around like 20 megahertz roughly maybe if it's overclocked uh so that's pretty fast uh you know the i squ c was only 400 khz so you can send things a lot quicker with the Spy interface uh because you have control over that clock uh and so that's kind of one of the big things uh that's different about it is you know having control over the clock and each device uh has to have an IND individual chip select line uh the other thing and we'll kind of look at this we'll look at uh the logic analyzer and kind of look at on The Wire what things look like but there's also a big concept of polarity and phase and this kind of comes down to you might see it referenced as the Spy mode uh and so this controls uh how the chips interpret the Spy bus data like if the clock should be high or if it should be low when it's active uh or if you want to sample data on the rising clock Edge or the falling clock Edge and so those two different bits or two different states you can kind of change independently so they're four different modes um so there's like spy mode zeros usually the default I mean every chip kind of varies so yeah you know sometimes you might see some differences but with uh you know spy mode zero you've basically got uh the clock is active uh it's active uh what is it active is it active low uh inversion active is zero so yeah wait let's see when then polarity is zero oh right so polarity zero the clock is at a low level and it goes High when it's active and then um when the phase changes so that's when the data is captured when it's sent so when the phase is zero uh then you're capturing data on the rising Edge uh and then you're uh outputting data on the falling edge of the clock so it's something to be aware of uh when you look at a device's data sheet it it should tell you what mode it expects to be in and everything's different sometimes they're like like I'm in mode zero or mode four and you kind of have to go back and map that to okay mode four means a polarity of one and a phase of one uh sometimes the data sheets give you the polarity in the phase so it's a little bit annoying sometimes to uh look at those different options but I mean ultimately there's only four that you can kind of choose here um so let's actually look at on The Wire what things look like so I'll switch real quick to the uh desktop view so again I've got the Sala uh logic analyzer the pro8 hooked up and this time I have four of its inputs hooked up so I have an input hooked up to the clock the chip enable the data output and the data input line uh and that's just connected to the little mCP 3008 here uh analog to digital converter so if we jump back to the desktop and let's see I'll put the uh workbench up in the corner too so we kind of see this uh I'll go to the pi and we can run a little example on it so uh let's go to the mCP 3008 library and we'll go into the examples and let's just run the simple test uh and so this is a little simple test that's just going to read all eight channels of the ADC uh you know we've uh I think I looked at this in a previous stream and so you can see as I change the uh uh channel the potentiometer that's connected to Channel Zero you know I cranked it all the way up so this is a 10 bit uh ADC so it goes from 0 to 1020 3 and I crank it all the way down um and then the other channels aren't hooked up so they're just getting kind of random noise but you can see um I have it hooked up using Hardware spy to the Raspberry Pi so it's using uh the the spies built-in uh the the Raspberry Pi's built-in spy peripherals and we let's take a look then at uh the Salia logic analyzer program so uh this is actually showing a previous capture but what I'm going to do so it's running in the background every half a second it's uh reading data from the ADC so I'm just going to do a capture it's a 2C capture and we'll just pull in all of these lines of data uh like we saw before it kind of starts out zoomed out or zoomed in so we'll kind of zoom out so we can see each half second you know there's a new kind of flurry of activity and we'll zoom in here and we'll go through all the different signals that we see uh for this so let's see let's maybe see we zoom in one more ah let's go out a little bit okay there we go so at the Top This one is the chip enable signal and so you can see this kind of it starts at a high level and then it goes low uh when we're going to talk to the Chip And it stays low the entire time we're talking to the chip and then it goes back high when we're done uh the next one is the clock line and so you can see this changes really quickly and this changes every time data is sent or received over the Spy bus and real similar to like we saw with i squ c you know it also has a clock like any kind of a synchronous serial protocol usually has a clock that shared between the devices uh the next one is the most Z line so the master out slave in uh slave input this means the Raspberry Pi output and it's the input to the mCP 3008 so you know think of this third line as the whatever the Raspberry Pi is saying any anything it's outputting and the fourth one is the master input slave output so this is the output from the mCP chip to the Raspberry Pi so it's what the pi is reading oops I get kind of moved out of the way there so already you can kind of see okay so there's some stuff going on here like the chip enable line gets pulled low and that's just a part of the uh polarity of the device and the kind of the Spy mode it controls whether the you know for some devices they expect to stay in a low State and then go high uh you know in this case this device it's it it expects to be in high State and go low uh you can see the clock changes and if we zoom in we can see the frequency here uh of the clock and it's about um 625 khz it's close to a megahertz uh so when I look at the code you'll kind of see um you know I'm trying to set this for a megahertz but sometimes when you're using like hardbar spy uh you can't control the the clock speed at a super fine granular detail you know usually it's like powers of two sometimes like a division of the main clock speed so in this case we're hoping to get a mehz we got 625 khz that's that's still pretty quick that's good enough uh and then we can see the um the output from the Raspberry Pi down here and then the uh output from the mCP chip down here and again I've got set up in sala's program they have a little spy analyzer so this is really handy um you know you can configure this and you just tell it which channels are hooked up to which I squ C uh lines and then it will actually go in and decode things and so that's what you can see in the little blue Parts uh underneath here are the values uh and unfortunately they kind of go away as you Mouse over them but you know this upper blue part right below my mouse that's the output from the raspberry pi and then the one down here uh I guess right below the cursor that's the output from the mCP chip so you can kind of see okay the chip enable line is getting pulled low the clock is cycling so let's count let's see one two three 4 five six seven eight so eight clock Cycles that's a bite basically uh so you can see I've effectively transferred three bytes of data here and then the Raspberry Pi for the first bite is sending some data so it's sending a value of 192 and if you go back to the um data sheet for that device you can kind of decode it and see uh there's certain bits you have to send to it to say okay I'm ready to take a capture and like which channel I want to capture uh and then after I send that bite you can see that uh the clock is uh pulsed you know for two more bytes and this time the chip is actually responding so it's sending back a value and this is uh just a a numeric value of like 252 and then a value of 31 so you know those two eight bits of data data you have to put them together and you'll get 10 bits of data for the ADC uh output and so that's basically one ADC reading that we see here so you know it's a little bit simpler than I squ C like we saw last time like with i squ c it had whole concept of start conditions and stop conditions um you couldn't really tell which device was talking because they all shared the same data line and so it was just whenever one device pulled the line low it was kind of uh activating the bus whereas here you can actually see like if I only want to look at the output of the mCP chip I really just care about this third Channel down here uh or the Raspberry Pi you know I can kind of see that more in isolation so a little bit easier to debug uh but one big thing too because it's running at a faster speed I had to go in and crank up uh the sample rate here so like before I was capturing spy or I squirt C at like U you know four Mega four million samples per second I cranked it up to 10 million samples per second just because I know my clock rate is about a megahertz and so I want to make sure I'm at least twice uh above that to to capture that sign signal so uh you can see that's one spy transaction and if I kind of zoom out a little bit you can see a few more transactions that kind of uh happen and so there's actually eight of these 1 2 3 four five six seven eight and that just corresponds to the eight different channels of the ADC so the way this sample program uh works you know as it's running uh in the background here it's reading all eight of these channels in a kind of U sequential order so this is Channel Zero and then if I zoom in here this is Channel one that it's reading uh and you'll see it's just kind of getting back like no useful data you know this got back zero values for that uh basically just noise because they're not connected uh and so then you can see like uh I've got you know four of these kind of little flurries of activity just because every half second oops Zoom it out here go all the way out ah come on zoom out there we go so kind of four of these little flurries of activity uh so that's kind at a physical level how things are working uh on the wire you know you can see it's a little bit simpler protocol um easier to understand I think than spy just because you don't have to understand you know what's uh what's controlling the the data line in this case um so next I was thinking maybe let's dive in and kind of play with python and uh we'll I'll show you what are some of the libraries you can use to talk to the Spy interface and maybe we'll look at I'll actually do some coding you know we let's try out the different modes of the Spy communication like let's send some bites see what it looks like on the wire uh and how things change and so maybe before we do that uh I'll just kind of give a quick little overview about what your options are as far as talking to spy devices um using python so the big thing uh the big library that I think a lot of people probably end up using is spyd the python spy Dev Library which is very similar to the python smbus Library it's it's a c extension that just wraps um some Linux kernel apis that expose uh the basic API to talk to spy devices uh although luckily the Spy Dev library is a little better maintained I think uh kind of in the last 6 months or so uh some I think some folks took over kind of ownership of it so you know there's recent code up here on piie um it's I think the when they switched the Raspberry Pi to uh Debbie and Jesse and like the device tree overlays and things last year that broke the old spidev uh interface and so luckily some people kind of uh came up and fixed it and so you know it's awesome that people for maintaining this stuff but this is the python package index which you might kind of consider this the homepage for the project it mentions it's basically a modified version of some older code and so you can go back and see that and I I don't think that's code that uh code is maintained anymore so this is kind of the current version um it's also on GitHub luckily so you can kind of see here's the actual code for it uh and you can even jump into the module if you want and take a look at how it's all implemented very similar to SM buus like we saw before it's this is just a py on C extension and pretty much all of the functions uh like if we scroll down and see um oh wow you can see so they're having fun uh and this is kind of nice like luckily this Library deals uh actually supports Python 3 but uh you can actually see some of the ugliness when you have to support python 2 and three where you know you've just got if defs here where it's like okay here's the python 2 version and here's the Python 3 version which I think that's a painful thing unfortunately it's just a fact of life with python 2 and 3 but good to know at least this Library supports it uh but you can kind of see okay like here's the Reyes function and you know it's really just parsing out the arguments and then ultimately it's going to be calling like a read uh function uh C function from the uh Linux kernel to read in new data and then just kind of convert that to an output that it returns um so kind of good good thing to explore if you're a little more familiar and you just want to see like okay how is spy Dev implemented uh take a look at the code for this if you search around um and you search for like spy Dev documentation you'll probably find this PDF uh that someone put together and it's it's actually pretty good it's a nice little PDF uh short and right to the point and kind of tells you a little bit about U the python spy interface um it tells you kind of how to get it installed and going on Raspberry Pi gives you a little bit of an example for it so you know here's like a maybe hello world almost of spy communication so you create a spy Dev device you open it up uh and then you can just call certain functions so look there's a transfer 2 function uh this goes through and then actually talks about all the functions that are available and the different members you can use so you know you can change things like uh the mode like I was talking about before so this changes like the polarity and the phase um but really there's only about four functions that really matter with spy so you can read data you can write data with right bytes or you can transfer data which is reading and writing at the same time uh and they're two different transfers and it kind of tells you the difference here in that it changes how the chip select line behaves and maybe we we'll kind of run these and see what happens uh with some python code and and look at on The Wire how things work uh so I don't know let's just start let's just uh do this example and see kind of you know how this actually works so going go to the pi and maybe let's cancel out of this and let's make a new little program file we'll call this uh spy test.py and let's just copy out the source code from here that they show and see if this works oh wow that's kind of weird so I'm uh I'm actually connected remotely to my Linux machine uh I'm on a Mac right now so hopefully this works uh this is I'm using the free NX which is like a really nice little desktop sharing thing and I'm screen capturing that that's why you probably see the very top this no machine thing and uh this is just a little window but anyways it's uh seems to be working so all right so let's paste in the code here so okay so we need to import the Spy Dev module uh oh and by the way before I get too far into this um maybe just real quick on how to initialize spy so the very first time you boot up a Raspberry Pi you know using the raspberry operating system you probably won't have spy enabled so again you have to go into raspy config and it's under the advanced options and go through and click yes to all dis enable uh the Spy interface and it's going to want you to reboot I'm just going to cancel of this for now but then once you do that you can actually see the dev uh spy Dev devices so there's /dev spidev 0.0 and /dev spidev 0.1 and we'll look at kind of what those numbers mean in a second but if you don't see these devices it probably means you don't have spy enabled and if you try and run a program that uses spy you're going to get an error like file not found or IO error uh because it's trying to open the one of these devices and it's not there so real common stumbling block uh I make that mistake a million times too so you know it just happens uh so okay so for this python code then uh basically we need to import the library oh and to install this Library um you can just pip install it so you can do pseudo pip install uh spev and that'll pull it down it needs to compile a native extension so anytime you need to uh compile a native extension on a Raspberry Pi you need to app get install uh it's just always safe to do build- essential this will make sure you have the GCC compiler all the basic Linux headers and things you need uh and then you also want to install python-dev so this installs the python header if you ever pip install something and you get an error that says I can't find python. uh that means that you didn't install python-dev because it's trying to find the main header file that c extensions need to link to for python so first install those two uh and then if you don't have Pip installed you can actually install uh python Das pip and that'll give you pip and once you install all those prerequisites then you can pip install spy Dev and that'll just do a quick little compile of its native extension um and install it and once you got that all set up then you can actually do this import spy Dev and uh start using their Library so okay so the basics are you create um a spy Dev instance then you need to open it and so this has a couple options so there's a port and a device and this comes back to the two devices we saw here so there's spidev 0.0 and 0.1 and so this first number is the port which is just an indication of you know a device might have multiple spy uh buses or or or channels that it can talk to uh the Raspberry Pi just has one that's exposed uh to to users and so that's basically spy Dev zero and then the second number after the dot is the device and so remember like I was saying spy has a concept of a chip select line and so the Raspberry Pi has two different chip select lines for its Hardware spy interface so there's c0 and ce1 and with those two lines those just correspond to uh the the device numbers here so device number zero is going to be uh ce0 and device number one will be C1 when it's connected to the Raspberry Pi uh so it's important to make sure you've got the lines correct uh you know check out the Raspberry Pi uh gpio diagram uh there's tons of them online and you know you should be able to see where the the C lines are for that and make sure you know you've got if you're using if you've connected to c0 that your code will actually specify that so this code it's saying okay use um Port zero device one well in this case uh my mCP chip I'm actually talking to is on uh device uh Port uh sorry device zero so it's on c0 so I'll change that uh now it goes into a main Loop here and let's see actually let me just fix up some of the spacing here that kind of got mangled uh and and so okay so now we've got a while loop and actually let's put some spaces in here too and we don't need that so okay so we just have a main Loop and this is just going to send a transfer request uh and actually let's let's not start with transfer let's start with like a read um let's start with a read bites uh command so let's go back to the little spy reference here and see kind of what are all the functions we've got that we can call so there's a read bytes which just takes in how many bytes to read and it's going to return back an array of uh the bite data so let's go back and let's actually call read bytes and let's just read two bytes of data um and that's going to give us a response now let's print it out so let's print out received ox and uh let's see I'm going to use uh let's use let's use the bin asky Library so this is always a nice Library I think I mentioned this before so the bin ay. hexlify is a fun little thing to use so let's do basy dolify my response data I think this will work sometime I think hex hexlify wants a bite string we'll see if this gives an error I'll show you how to fix that um that's one murky area of python unfortunately is especially because it changes between two and three um you know how do you interpret an array of bytes um you know it's in like C you can just have uh an array of u8s in Python it has a concept of strings and strings might be Unicode and you you some you don't care about Unicode in a lot of cases and so uh I'll show you a little bit about how to deal with that there's basically a bite array class that means uh a list of bytes and it shouldn't be interpreted as a string I mean it could be if you encode it or decoded the right way uh but that solves a lot of problems as far as you know in a lot of cases sometimes in Python especially python 2 you get back data and if it has Unicode in it it might explode and you might not even it might inadvertently have Unicode like it might have you know some bite that's higher than 255 so uh it's it's it's a little bit of a murky area even I don't understand it all fully there some good talks I think I've seen that try and break down the Unicode mess and it's getting better I think Python 3 is kind of where they fix things so okay let's delay uh let's delay for um I don't know let's delay for a second so we'll do that and then uh this is just a little accept to see when we catch uh if I control C out of this I'm going to change this so let's make this a finally um because this will just ensure that no matter what happens if I control C uh and that throws a keyboard interrupt exception then this close is going to be called uh or if like an error occurs you know this finally Clause is going to call be called and this close will be called um it's it's good to close the the Spy interface it's not the end of the world if you don't because when your program exits um it's going to close those connections and really the only thing that's open is just that slev slpy Dev device um so you know it's really just an open file uh but it's good it's it's especially good practice to always be in the habit of uh being conscious about the resources you're using and making sure to clean them up so okay let's save this uh oh boy uhoh wow that was a little funky I uh normally I have to I press oh I I see what it is so this is a little bit of transition on my Mac I have to press the option key to uh save things on Linux it's control so I'm sure I'll have some fun with that okay now let's run this thing let's go back and uh this is probably uh might error out because of that aify thing but let's just see what happens uh so python spy test and let's see uh yep so like I thought so telling me uh must be a string or buffer not a list basically this is Bin ask. heex ify it's right now it's getting a list of bites but it it expects explicitly either a string or a buffer and I'll show you how to fix this um just take that array of bytes and turn it into a bite array uh and so basically the bite array is uh a class in Python and it it just gives you a buffer of bytes that's like a string but not ex always interpreted as string data uh and it's it as it's initialized it can take in a list of data uh and actually here how about this make it a little more obvious let's just print out what we get back directly uh let's just print out the response and we should see that this is actually a a list of data uh from python so yeah so you can see this is coming back as two bytes and it's reading nothing it's getting z z um and now if I actually use the B asky function so that bite array is being past that array of bytes now it creates a bite array with that value with those values uh and then oh sorry I don't want to do bite array here I want to do bite array before I call the Basi function so let's do bite array there we go we get all the parentheses right so I take that array turn it into a bite array just to make hexlify happy uh and then I call Bin ask. hefi and this should print out inex uh the output that I got so let's do this oh uh oh did something wrong oh I'm probably missing a parenthese here yep I am there we go and let's do this so now you can see okay Ox o o so it's reading back zeros here um which is good so this is uh you know real really simple now unfortunately um in order to get some output from this chip I actually have to send it something um so maybe we'll we'll try that in a second here but let's look let's look at this on the wire with the the Salia just to make sure that everything's kind of working so um actually here let's run this thing again and then let's do quick little capture so we should see a few instances of this so yeah there's a couple instances and let's just kind of dive in here and so uh like we saw before the chip enable line gets pulled low the clock Cycles a lot uh now the output from the device down here it's you know it's not sending anything so um you know we we'll see as we kind of send it receive data that it's it's responding here but that's kind of cool so that's kind of showing okay here's the default mode of zero let's play with the the Spy modes a little bit and see how things change so let's save this capture um let's call this read mode zero okay now let's change and let's go back to the documentation here so this the mode is a parameter we can change uh on the Spy Dev device and this you can send a value from 0er to four and this just changes is how the polarity and the phase are interpreted so let's change this to like a value of one and see how things happen uh how things change so to do this you just need to change the Spy mode so like let's set this to one by default it's going to use zero so let's save this and let's see how things change uh when I rerun the program so now I'm running it still getting zero back but that's okay and we go back to the saler and let's do do a new capture and we should see some differences so we zoom in here oh we might actually not see a difference in this one uh because I I kind of forget offhand how all the different modes map here so let's go back to Wikipedia uh and see what the polarity and the phase uh how these change so okay so a value of one here we go spy mode one so my polar it is going to be zero so polarity that's what controls whether my clock is active high or active low and then my clock Edge like when I'm sampling things U that controls uh the the phase of this so okay so in spy mode one I have the exact same polarity so we're not going to see difference so let's change it to spy mode 2 and see how the clock changes uh in this case so let's go back to the code and let's change this to spy mode two and now let's run this and so now let's run a new capture and we should see the clock should be different oh already I see a difference see the clock line here is high whereas before it was low uh so that's kind of telling me that the clock is staying at a normal uh State uh now it looks like I see a little red dot and that's probably the saler uh the logic analyzer is a little confused now uh because i' I've told it that uh in the protocol analyzer that my clock is low when inactive let's change it let's say it's high when inactive um I probably have to capture again for it to reinterpret this oh no actually looks like it just worked so okay now we see a difference here like look at the clock lines so uh remember this is the read from mode zero uh you know we can see the clock is low and then it jumps high when it's active and here's with mode two we can see it's high when it's active and it's low um or sorry it's high when it's idle and uh low when it's active so you kind of see the difference in in how these modes operate uh and it actually changes how things change over the wire here uh now the chip select line I can't remember let's see I think I think we can control whether that's um yeah here we go so there's this CSH High property so this controls if the chip select is uh normally if it's active high or if it's active low uh and let's just check and see if there's anything else okay yeah there's just CS High I don't think they have a CS low parameter yeah so so let's set CS High to uh true so this should tell us because right now we're seeing uh in the logic analyzer you know the chip select is uh active low so when when we're talking to the chip it's pulled low but if I set CS High to true this should invert we should flip this around so let's let's check that this actually works so we'll do spy CSI equals true oops and let's save that and now let's run this and okay so we're running and let's do quick little capture and okay yeah now now it's different so we can see we're low and if we zoom out and find our data kind of Zoom all the way in here and yep it looks like it changed so we've got you know we're act we're idle low now on the chip select line and then when it's active it jumps up High versus you know when we saw in mode zero uh with this uh chip select it was idle high and then active low so something to be aware of and again you're going to want to check your chips data sheet it uh it's going to differ by you know each chip is sometimes different most chips the standard usually is that you uh pull your chip select down low to be active but it's different uh for different chips so something to be aware of okay so those are a couple knobs that you can tweak um there a few others and maybe won't show all of these so you can control how many bits per word um basically you can change to either do you want to send things a bite at a time or a word at a time like two bytes at a time and again it just comes down to what chip you're talking to and you know how it likes to uh interpret the data um let's see let's let's see what else is here um the uh LSB first MSB first this controls the order of bytes that you're sending so actually we can see this in a second um let's do some wrs uh so let's update our program and we'll kind of play with some of these parameters so instead of read bytes let's do a write bytes and let's look at the little docs here on this so this takes in a list of values and so this is a list of bytes that we want to send in uh and so let's send two bytes let's send um Ox how about 42 and uh ox1 maybe something like that so okay so we'll send two bytes uh and there are a lot of ways you can do this like you could send an array like this um you could create a bite array object and pass this in I think this will work um again it's kind of this murky area of python you know sometimes things are written to expect arrays of things sometimes they expect strings sometimes they expect explicit bite arrays um I like the bite array just because it's the most explicit thing like it's showing my intention that uh you know this thing is a list of bytes you know don't necessarily interpret it as a string uh you could if you like encode it or decode it as Unicode or whatever but you know it's really just bites uh so i' like to be explicit but let's just do this we'll keep it simple uh so okay let's save this and let's run our program and now let's do a little capture oh interesting nun type is not oh duh so uh obviously the uh the right bytes function is not going to return anything uh and we we you should actually be able to see in the docs here I don't think it mentions anything so yeah returns nothing so obviously I need to change this code a little bit so let's just uh delete that and comment that out okay so now let's run this thing and we won't see any output uh but it should be running in the background so let's do a quick little capture and see kind of what what changes so zoom out and we can see okay now we see some stuff going going on so um you know we we have the modes kind of set in a funky way uh like we had before so you know the chip enable is active high now and the clock is uh active low but now we can see okay the the mosy line the Raspberry Pi output has some data on it and let's change our spy protocol analyzer here so let's uh oh this is where we change a Tex there we go that's I've been looking for this setting so okay so let's change things um so most significant bit first uh that's yep that's standard eight bits that's standard so the clock is low when inactive and your enable line is active High that's how we have things configured right now uh let's see what is it saying oh wait did I get that right no sorry the clock is high when inactive there we go save that there we go Okay cool so look at that uh we can see now we've actually got some data that's interpreted so this ox42 down down here that's data that was uh observed being written out by the Raspberry Pi and ox1 which matches exactly what we had so that's kind of cool so we can see these things um working so let's okay let's play with that MSB LSB um bit so if we go back to the docks on this so there's a little Boolean here called LSB first uh so least significant bit first so it's a Boolean um the default is uh I think the default is true I want to say let's see um no no sorry it's false well let let's actually see what is the uh most significant bit that's coming back for this so um if I go back to the the capture here so for 42 if I run uh little calculator let's actually see what this looks like and what the bits are set so we go into hex and we put 42 in here so okay so yeah so here's the most significant bits uh up at the top so it goes 0 1 0 0 and that looks like yeah so we're we're going most significant bit first so 0 1 0 0 z0 1 zero so that's the default is uh that the so LSB first is false is the default it looks like so let's set this to true and see what happens we should see this inverted so let's set spy. LSB first true and let's save this and let's run this now and we'll go into oh uh what this thing what's this m about invalid argument to sleep uh oh I must have did I put in something incorrectly here um let's make sure I got this thing named the right thing so yeah LSB first that's a little funky did I put in too much white space or something somewhere let me uh just comment this out and just make sure that this is right uh okay that's really weird I've never seen that fail in that way uh let me just let's cancel this let's see what's going on here so okay so I want to set LSB first equals to true and I I don't see anything wrong with this line that's interesting huh that is really interesting invalid argument for this uh well maybe this is maybe the Raspberry Pi Hardware doesn't support this mode this is uh I actually haven't really tried it so um something to be aware of that you know maybe this doesn't actually work uh with the the hardware spy I'd be surprised if it doesn't support it but that's that's a little funky maybe something to look at later but again you know this just comes back to these are all the different options we can set um we can change the speed let let's try changing this and see how the clock speed changes so just for now let's see what the clock speed is that we're using so looks like it's about 300 KZ so let's let's crank this up let's set this to a high speed so let's uh what is this thing called it's Max Max Speed Hertz okay so max speed Hertz and let's see can we do 10 megahertz so one two 3 one two three and let's see what the the Raspberry Pi can do so we'll save this and let's run this and okay so it should be running so let's do a little capture and now let's kind of zoom out let's see how the clock changes so I kind of zoom in here and we should be a lot faster oh interesting wow so it's uh looks like 3.33 megahertz and you can see it's it's not that nice of a clock this thing is kind of all over the place oh well duh I'm sampling at 10 mehz so of course I'm not going to see this thing let's crank this thing up to like 50 million samples per second uh so that's uh good old n quest uh where you know if you're if you're you can't recreate a signal if you're capturing it at the same rate so you need to capture at least double uh the rate of your signal in order to see it and so we can actually see like we're getting this funky signal where like the clock's not matching up it's not doing eight bits that's because we're not sampling the right way so you know little thing to to run into uh okay so let's uh let's run this thing again and now we should be able to see the signal zoom out and now we should see a nice clock and yeah it's looking a lot better now so okay 6.25 MHz and actually I remember that I think that is the limit um for the Raspberry Pi uh the hardware spy interface without I'm I'm pretty sure there's like some kind of wacky device tree setting you can change to uh crank this up a lot higher uh but in most cases you know you can get up to like 6 MHz uh which that's pretty quick like six megahertz you know that's at a point where like you can't toggle an eye open on the Raspberry Pi at 6 mahz I you can in some cases but you really can't do much uh so this is you know one benefit of using spy that you can do really fast things and this does matter like you know for a little ADC like this it's 10 bits okay we don't need to uh talk to it at 6 MHz but you know imagine an LCD device uh like a TFT display and when you need to send you know thousands and millions of bits of data to update the entire screen changing that clock rate to you know High megahertz rate makes a big difference and you know you can see dramatic speed increases for it so okay cool so we can control the clock um you know that's pretty much all the different settings we can change here uh so we saw reading bytes writing byes uh I'll do the transfer functions now and so let's let's try so transfer and transfer 2 let's start with transfer and kind of see how this works um so let's change this to what we had before so we want to say uh our response equals and then let's call xfer and so like I said before transfer is going to write out ox42 ox1 and at the same time it's going to be reading in two bytes of data so it reads in exactly as many bytes as you write out uh which in a lot of cases like you sometimes might need to write out you know like dummy data like let's actually write out three bytes you know so imagine a device where like I need to write a couple bytes to tell it to start and then I need to read a bite after that in which case I just need to clock out like a dummy bite of zero to make sure that I read that data um so let's save this and let's see what this does uh on the hardware here so let's run this and let's do a little capture yeah good it's running and now zoom out U oh and I sorry I should actually uh print out what we're doing so let's uncomment this line and let's save this and let's just run this again and so now we should see so you can see there are three bytes that it's returning uh you know there's two hex characters in a b and so that's because I did a transfer of three bytes so it's sent three bytes and then it's also receiving three bytes and I'm printing out the results here I'm not getting anything back just because you know I'm not talking the right format to this ADC but it doesn't really matter we can still look at it on the wire here so let's do another little capture of this and we really won't see much difference here because our our chip isn't responding uh to what we're sending but we can see at least that we're sending the data again um so 42 01 and then 0 0 again so it's exactly what we sent uh now the interesting thing here notice the chip uh enable line up at the top here it's held active the entire time that this transaction happens let's change to a different function so let's kind of read what these functions so the xer function is telling me the Cs line will be released and reactivated between blocks uh delay specifies the delay in um Nan between blocks uh so I'm trying to remember from I believe a block is uh how many bits per word like you know it's it's it's saying uh it should be set up by default so between each bite it should be toggling the uh CS line and that's the difference between the X for two function where this is actually just going to hold the Cs line now the interesting thing is I actually don't see that in my in the saler trace here like you know in between these two B I don't see any difference here so I I might not be interpreting this correctly it's it's not something that that we commonly use uh you know in most cases the chip enable line is just always held high and low um but I don't know let's let's just try let's see uh if I can actually see some something change so telling me there's a delay parameter I can change in here so let's try that um in nanocs so let's do a lot let's do like 1 th000 NCS so let's save that let's see if this changes anything so we'll run this and oh that's weird huh well maybe these docs are out of date so so in the documentation fails let's just jump down to the source real fast let's look at uh xfer so let's go down to xfer and we should see okay here it is so what's it doing is it parsing out okay so it's it's parsing out an optional integer delay usex um maybe I have the name incorrect delay micros seconds yeah this should be oh no interesting it's uh you can actually pass in like the speed in in hertz and the bits per reward wow I didn't know that that's kind of interesting that um you can explicitly say during the transfer how you want to configure the the Spy interface that's kind of nice uh okay so I must have this named incorrectly so it might be delay uncore nanocs so let's try this um so unfortunately that document uh seems to be out of date but that's just unfortunately the fact of life uh so no takes no keyword arguments boy that is really bizarre why that's not uh taking that argument so I must be sending this in the wrong uh order here so well anyways um you know I was hoping to show kind of the difference between these two functions but you know I'm not really seeing a difference like let's let's just try it let's call the other function uh transfer to and see if we see any difference here um so let's do let's get rid of that and let's just call X for two and oops press the wrong button there we go save that and let's run our script again and okay now we're getting dat back so let's take a look on the wire how things look and let's see if the chip uh select line changes so yeah I don't see any change here unfortunately so huh that's a little weird and it's also weird I don't know what that's kind of bizarre we got a little blip over here uh that had cycled uh maybe I'm actually interpreting this the wrong way I didn't do enough homework on this part um it could be I have a feeling perhaps maybe it's like in between uh maybe it's in between transfer calls it's changing the chip enable line not totally clear on that so you know it's something you're probably going to have to look more into the docs uh to to see but those are really the core functions like you can write data you can read data or you can transfer data like read and write data at the same time uh and so when we saw earlier the trace of um reading data from the uh ADC and actually here let's just go back and run that script again um that was using the transfer function because it was reading data and writing it at the same time uh so if I run that simple test and so now that's reading uh the ADC and I should oh I so that's kind of interesting I think I've uh I have the Raspberry Pi Hardware in a weird spy State because I was messing with the Spy device so i' I've probably changed like the polarity and things although it's interesting my uh my code should be setting that back to normal but let's just capture it let's just see what happens um but I have a feeling that yeah things have like you can see now for some reason it's stuck in the mode where the chip enable line is active low when it really should be active uh high or sorry it's active High when it really should be active low so I've kind of gotten in a bad State now uh which that that's a bug uh my cach should be handling that but uh so you can kind of see it's all funky now um but ultimately the code for this is just using that transfer function uh like we saw kind of documented here so you know read write and then transfer those are your main operations with the Spy bus uh and then real briefly we're maybe kind of run a little bit longer on time um so again like I squar C I was kind of wondering how is this stuff implemented at a kernel level because you know this module uh although it's really nice and it's maintained and you know the code is up on GitHub uh you have to compile a native extension luckily this one does support Python 3 uh which is pretty nice so that's that's not to too bad uh but you know if I want to make a pure python version I wanted to look and see how does this actually work at a kernel level and just like we saw with iqu C before uh go to the kernel.org Linux kernel documentation and you can find all kinds of documents on the Spy Dev SPI deev the Spy Dev interface and that's what really is happening behind the scenes with all these libraries so like we saw that those Dev spy Dev devices this document tells you how to inter interact with these devices so you can open them as a character device um you can when you write data to these devices it talks about how it will use that as just a a spy write if you read data it'll do a spy read and then to do a combined read and write you have to go back to our old friend the io Control Function and so this explains how to set up those IO control functions to do like a transaction that reads and write data um there's IO control functions it talks about to set set the Spy mode um to set the Spy bits per word like all of that stuff that we saw exposed by the python Library underneath uh the covers it's really just making these IO control calls and uh it's actually the Linux uh kernel spy interface functions they're calling this and then the python code calls that spy interface um but again I think you know it's it's definitely feasible I can do IO control functions again I don't have examples of them yet for spy uh but ultimately I want to do um in this little pure IO Library a version of spidev that has the exact same API so like we saw you know I'll expose all these same functions but have it implemented by doing the raw IO control calls and then that way it's nice and that it's a pure python function like it's the exact same problem as the iqu C where you know um I'm not calling a c extension so it's easier to install but it's a little bit slower because python has to do all of this data marshalling uh as far as like you know getting memory into the format that the C functions expect and then pulling it out of that format and putting it into a format that python likes there's a little bit overhead there uh but I think it's a good trade-off in that now you know libraries can depend on this and they can just do a pip install you won't have to compile a python extension and it's all kind of ready to go uh in that regard so uh otherwise I think that was it um if folks have questions then you know maybe feel free to throw them in the uh the twitch chat and maybe I'll jump back to uh the fun little here's the the crazy Matrix view uh so yeah that was kind of the Deep dive into the Spy the serial peripheral interface and again it's very similar to i squ c and it's a way for two chips to talk to each other but there are some big differences so there are four wires that you need here there's a clock line a data output a data input and a chip select line and you know unlike i squ c all of your devices can't share the exact same line so like each device needs an individual chip select line they can all share the same clock data output and data input uh but they have to have a unique chip select line and then the other big difference is that the speed is something you can control with the Spy interface so you can crank it up to you know many megahertz as fast as the hardware supports um one brief thing that I didn't mention but the Spy protocols we saw is pretty simple like you're just toggling clock and enable lines you can actually do that in software so like a lot of the Arduino libraries we have have a software spy implementation I have a little software spy implementation I did in U in my main python gpio library and that's useful because now you can use any four gpio lines you don't just have to use those Hardware spy lines on the Raspberry Pi and so that's a good way where like if you have two chips and this is a big problem sometimes especially with Arduino you know you want to read like from a Micro SD card which uses a spy interface but then you also want to talk to a sensor that uses spy and if they don't use the same mode and polarity uh and clock phase then when you try to talk to one and you get that wrong it's not going to uh understand what you're saying so in a lot of cases it's easier instead of trying to constantly change the polarity and phase and things like that uh to just say let's just create a whole new spy bus it's got its own clock phase and polarity and it's easy to do that with software spy uh so it's just something to think about you know you can bit bang this protocol you know effectively emulate it with the gpio and it's it's not as hard as you might think because you really just have to toggle the pins and toggle the clocks and read and write data uh for it so yes like we saw there's the the python spy Dev is the library um it looks like it's pretty wellmaintained now and you know at a low level if you really want to get in there the check out the Linux kernel documentation um so I think that's it I don't see a lot of questions so uh we'll wrap this up uh thanks everyone for watching um hoping to make this kind of a weekly thing I I don't have a fixed time yet just because it takes so long to get this streaming set up that I want to get this process to be nice and smooth and just flip a switch and it's on and ready to go uh so hopefully then we'll see a lot more streaming after that uh but it's getting there it's getting a little bit easier um and hopefully the quality looks good and you know the audio sync hopefully is working well too uh and I'll upload this to YouTube and so check out uh the uit Youtube channel subscribe to that you'll see this video lots of little project videos uh check out the twitch .tv Adafruit Channel and that's where I stream this live and you can watch all kinds of other live streams uh there's stuff like the desk of Lady Ada that's happening uh no and Pedro has some 3D stuff that they like to stream so check that out and speaking of desk of ladyada if you tune in tomorrow I think uh lady is planning uh the last live stream for the pi zero contest so I think tomorrow evening sometime might look for that uh kind of see you know what's going to happen what's the number 10 stream going to be uh so that's it thanks a lot everyone for watching um and you know quick shout out too to uh cool retr term which is kind of the program in the background there that's pretty awesome uh and then the the intro video I had before got some like NASA Shuttle stuff there I'll have a little proper kind of credits thing at the end I'll put that in there too but you know uh everything's kind of fancy and you know I've just built this on top of other cool stuff that people have done so awesome thanks a lot we're going to end the stream and I'll see you guys in a week
Info
Channel: Adafruit Industries
Views: 19,165
Rating: undefined out of 5
Keywords: adafruit, electronics, diy, arduino, hardware, opensource, projects, raspberry, computer, raspberrypi, microcontrollers, limor, limorfried, ladyada
Id: bHpnu1te0uU
Channel Id: undefined
Length: 64min 21sec (3861 seconds)
Published: Sat Feb 20 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.