P2 Stepper Motor using Trinamics TMC2590 over SPI
Greetings everyone. It has not been that long since I came to learn about P2. While I was going through various options for a project, a friend of mine suggested P2. And it's great to learn about such an active community here.
I have been checking resources about P2 and trying to get along the Spin2 language, at a complete beginner level. I don't have any prior experience with Spin1 either. Although I have been using other platforms such as Arduino and RaspberryPi for a while now. I wonder if there's a structured series of tutorials for a complete beginner on Spin2.
Moreover, has anyone tried controlling Trinamics motor drivers over SPI using P2? In my project, I intend to control multiple stepper motors using TMC2590 in SPI Mode.
Thanks in advance.
Comments
I have just used the TMC2208 to drive two stepper motors though. They are very quiet, even when you turn them on, nothing. I think they are not powered but when I supply the steps to them they turn just like that.
Unlike you, I have not crossed over to the SPIN side.
SPI works great with both the P1 and the P2.
Mike
What platform do you preferably use or would suggest to the P2 beginners to get started?
It's all about the journey.
If you like programming in C, you can continue to do that with little effort. The flexprop compiler works great and I use Visual Code to do the programming.
Check out these projects to see how it's done.
P2 Edge RoadSteer
P2 Edge Goes for a ride
P2 Edge SCARA does Tower
Mike
Indeed, I have been going through them. They are interesting and inspiring. Great job!
If any, could you please share a template or an example for P2 SPI?
Ah, yes, the documentation for a lot of the C code functions were born on the P1 and documented in SimpleIDE.
Most of those functions are now in FlexProp but not the documentation part of it.
Anyway here is an example of the SPI HX8357 Display. I believe this display has Arduino code as well from Adafruit.
Mike
I've attached my P2 programming template. It includes a serial library for serial coms. If you're using Propeller Tool for Spin you can configure this code as your P2 template and then load it via File\New menu or by right-clicking on an editor tab.
I take a step-by-step approach, which I suggest you consider here since you're learning a device and a language. The Px series does not have specific SPI hardware built in so we synthesize SPI operations in code. This is easy and gives us a lot of flexibility. Luckily, it seems you only need one method to handle SPI with the TMC2590; you send it 20 bits and get 20 bits back. You can start with an experiment that communicates with a single device. Start by defining IO pins for the SPI connection.
Remember that the data output from one device connects to the data input on the other, and vice-versa. Somewhere in your program you'll want to initialize the pins. My programs have a method called setup() that is called at the beginning to configure IO and objects. Your setup might look like this (assuming you want to output via a terminal).
And now you could have a simple method to transfer values between the P2 and the TMC2590. Based on experience with the P2 and similar code, my guess is that this will run at about 500kHz if you use a 200MHz clock for the P2. This is well under the max speed of the device which means that -- once you have a firm grip on communications with it -- you could improve the code using inline assembly, and possibly even using P2 smart pins.
Once you're fully confident in the connection to the TMC2590, it would be a good idea to create an object (library) for it. That will simplify your code when connecting to multiple devices.
I did an online class introducing new Spin programmers to SPI using the flash chip that is on all P2 boards (holds the program). I started with a very simple version that uses Spin (as in my examples above). I updated that to use inline PASM2 for speed. I also did a version using smart pins. For small transfers I just find it easiest to go the inline PASM2 route; you get the speed without the work involved setting up and dealing with the smart pins.
Assuming the code above works, an object for that device might have this variation of the method. Of course, that object would have a start method that allows the caller to pass the SPI pins used for the device, and -- optionally -- the SPI clock speed. Once you know the pins and have configured them, this method would handle the transfer at high speed.
I've attached my SPI objects for the flash so you can compare the Spin, inline PASM, and smart pin variations.
Thank you for your valued suggestions @JonnyMac. I will be following all that you said and will be sharing any the advancements here as well.
There're two questions that I would request you to clarify as well:
Is it not true "The smart pins are really tuned to mode 0 SPI"?
Is there a way they can be configured to handle any of the modes?
I can't see where smart pins here helps at all. It takes just as much code as just doing bit banging.
Also if you use some ones name it adds a space at the end of it. This space needs to be preserved otherwise it doesn't work.
Mike
The SPI modes of smart pins are easiest to use with mode 0. That said, there is some flexibility, though we're still at the early stages of documentation so it can take a bit of work to sort out. Before we do, though, I agree with Mike that smart pins are not useful in this specific case -- the inline PASM I provided above will give you the speed you want and is just easier to deal with.
But... if you really want to try smart pins, you have to configure them. Start with the clock
This will setup the pin passed in sck as an inverted clock (CPOL = 1). The last 0 in pinstart() configures the pin but doesn't output any clocks
Now, the SDO (old name MOSI) pin
The normal behavior of SYNC_TX is to output the bit on the rising edge of the clock. Well, we have inverted the clock output, so we have to re-invert it here so that the data output is on the falling edge of the clock (as shown in the docs).
And here's the SDI (old name MISO) pin
The SYNC_RX mode samples on the rising clock edge which works for us because that happens in the middle of the bit period (the device setups its SDO pin just after the falling edge).
As Mike points out, it's a lot of setup for the simple interaction for this device which is why I wouldn't do it here. Finally, the transfer routine.
As you can see, after setting up the smart pins the code is still nearly as long as the simpler mechanism of using inline PASM.
Fair warning: None of this code is tested. That said, I have a lot of experience with Spin, and feel confident this is a good starting point should you want to test it.
I'm attempting to communicate with an AD7124-8 ADC which requires SPI Mode 3 (SCK idles high, with data to its ADC's DIN input shifted out of the P2's SDO pin at falling edge of SCK). This requires ......
..... as described by JonnyMac in the previous post. Note his 'Fair Warning' disclaimer that this is an untested possible solution for Mode 3 SPI operation.
I'm using Jon's "jm_ez_spi_demo.SPIN2" and "jm_ez_spi.SPIN2" code as a starting point for code development.
Observations on my scope show that the first data bit shifted out of the SDO pin (which should be the value of the shift register's LSB bit) is present at the SDO pin IMMEDIATELY following execution of the following two lines of code [ see the jm_ez_spi.spin2 file for shiftout() routine for details ] :
This behavior agrees withe the Parallax Propeller 2 documentation for the "%11100 = synchronous serial transmit" function which states:
"During reset (DIR=0) the output is held low. Upon release of reset, the output will reflect the LSB of the output word written by any WYPIN during reset."
In SPI Mode 3, the leading falling edge of the first SCK pulse is expected to trigger outputting of the first data bit from the SDO output pin, then after the trailing rising edge of the first SCK pulse, the ADC DIN pin is expected to sample this initial data bit. Unfortunately, the first data bit value is already present following "pinl(sdo)" execution, so at the first leading (falling ) edge of the SCK pulse the NEXT data bit value is output instead, and the ADC DIN pin samples this incorrect value.
Within the shiftout() routine, I was able to finally achieve communication with the ADC's ID register by using two code fixes:
As the above solution will not work when shifting out 32 bits, and is specific to 'mode 3' only, I would have to agree with others on this forum that the use of 'smart pin' mode for SPI communication is far too complicated. I see Jon's attached SPIN2 code above which uses inline assembly to accomplish SPI communication. Does this code represent the most up to date implementation of SPI under SPIN2 ? Perhaps someone has a robust implementation of the equivalent of Jon's "jm_ez_spi.spin2" code, ideally one that allows for SPI mode specification ?
I use PASM2 based off JonnyMac's implementation and hacked a CPOL/CPHA feature in. You can find it here: https://github.com/deets/unifhy-rocket-engine-test-stand/blob/master/modul2/P2/spin/deets_spi.spin2
I use it for an ADS1256 that also wants mode 3. It "works for me", but that might be a glitch / implementation detail of the actual SPI implementation.