Hey guys - I am working on a pulse sequence generator which needs to sync pulses across 4 channels using the RMT. The esp32 documentation shows examples of how to configure a sync manager to make sure the channels are firing in sync. I don’t see an implementation in the NF for this but I am a noob so maybe it’s abstracted and I’m missing it. (Note: I would be happy to contribute to the project and add it if it doesn’t exist if that’s possible!)
#ESP32-S3 RMT Sync Manager
1 messages · Page 1 of 1 (latest)
if it's not there (I can't recall) it sure can be added
@autumn beacon any idea about this? 🙂
The sync manager is only available in the latest IDF api for RMT. We are still using the legacy API from v4.4 for the RMT native driver.
I think this should be now updated to latest API which will involve some changes to managed interface for the better. Instead of calculating clock frequency based on native clock used to run RMT we can just specify the desired RMT frequency which simplifies the manage code libraries for the different target ESP32s.
The C# API would also need to be updated with a SyncManager class so that the synchronised channels can be added to it and started together.
I'll create an issue to track this change.
@autumn beacon How about the ADC, PWM and I2C?, They also need to be migrated to 5.x IDF new api.
They do. As time permits. 😉
Thank you for the explanation! I am excited for the update!!
In the mean time hoping I can cobble something together. Is there a way to synchronize channels with 4.4? I inherited a micropython implementation which I am converting to NF and it’s doing sync by direct register writes (I think) - the developer notes in the micropython mention that micropython doesn’t support sync either.
This is a for a medical device and the timing between pulse sequences across four channels must be exact. The pulses themselves are simple though - 100 us pulses at 100Hz staggered in time across 4 channels.
UPDATE: It looks like by setting bits in this register, I can do the simultaneous transmission. It appears it waits until you do a send on the last Tx channel before starting them all. I am a noob (sorry) - is there a way to write to this register using the NF?
No possible from the managed layer. You can write your own interop (native to managed) code
OK. Just to be 100% sure before I go that route. In the python (I am not a python guy) that does this - it does this:
from machine import mem32
mem32[0x600160C4] = 0x1F
If I can write 0x1F to that memory address it will sync the signals across the 4 Tx channels...so there is no way to do that other than writing my own class library? Like no NF equivalent for the Machine.mem32 in python?
No, in nF we cannot poke raw memory nor register. I guess it is to prevent shooting one's foot.
Gotcha. Now the problem is I have no idea what to even wrap to be able to write to the register! LOL
@bright knoll @stark horizon So to do a C wrapper you have to be able to do a full build of NF? That’s what it seemed like @stark horizon article said. Can you not just build the DLL and interop and put it on the device like you would on windows? (Like I don’t need to rebuild windows to create a DLL wrapper.). Sorry if that is a stupid question!
Not stupid. And yes you need to rebuild the firmware. This is Interop in the sense that it uses the mechanism.
There is no way VS can build a C# project and at the same time compile the C/C++ native code that you want to add and squeeze it into the firmware. This is a static build against the MCU SDK. Not a fair comparison Windows PC vs a small MCU with very limited RAM and flash...
Ok - how hard is it to rebuild the firmware?
(Let’s call it an ignorant question - lol)
I’m not sure that fits into “Easy Peasy” but your instructions are very well written! Hopefully an old fart like me can follow. Now assuming I get it built, how bad will wrapping 5.3 of the RMT code be? I’ve looked at what you guys have in the RMT classes and it doesn't seem bad but - would it be better for me to wrap something that can do the register write?
We've recently moved to IDF 5.2, shortly after 5.3 came out. It was decided to wait for the next revision release instead of going straight to the very first one.
5.3 will be available as soon as time permits, I don't have a time frame to inform
Adrian already created that issue above to track the work on that. Don't know what else he can share at this point...
I apologize - my last post came out garbled and may have come across wrong. I was not in any way trying to be pushy. I was asking if I go ahead and do it myself what is better path - try to wrap RMT 5.3 or to create something that lets me write to a register since that would solve the issue to. No work on your part at all or intent to be pushy!
In other news, a colleague suggested that I try to use the PWM since you can do pulse sequences there as well. It appears there is the same problem. The methods to synchronize channels do not appear to be exposed or were not a part of the PWM version you guys used.
No worries. Moving to 5.3 requires some work on both the build system but also on the drivers, comming up with those new APIs. DOn't knonw how familiar you are with CMake and IDF...
@autumn beacon Does this expose the sync manager to synchronize multiple channels as well?
@brisk yarrow
The latest API for RMT hasn't changed between IDF 5.2 an 5.3 so we can just update driver to use latest API without updating IDF. I don't want to try and add the sync manager to the current nano RMT driver as that will be a duplicate of work as we need to use latest API. With latest API there is no need to write to registers.
I'll be looking at updating driver over next few weeks. At the moment i am just looking at the scope of the work.
@autumn beacon You are awesome! I thought I had figured out a hack that I am fighting with in the mean time. It seems like it should work but I think I am not fully understanding RMT. I am trying to get 2 channels to output syncronized 100 us pulses at 100 Hz. If I just set that up as one command on each channel: AddCommand(100, true, 9900, false), I get the two pulse sequences, but the 2nd channel is offset by about 3 ms. My idea was to create the second channel pulse sequence with 2 commands where the true straddles them: AddCommand(4950, false, 50, true) + AddCommand(50, true, 4950, false), and then by using a scope and trial and error I could shift the 100 us true period to anywhere I wanted by changing the false period at the beginning and then adding back time at the end: AddCommand(3000, false, 50, true) + AddCommand(50, true, 6900, false). What I am seeing is it only repeats (loopenable = true) the first command and ignores the second. Not sure if I need to do something with the ring buffer or what. (total noob here sorry)
From what I understand the default buffer of 1(NumberOfMemoryBlocks) should be ok for 64 commands to loop.
So i am not sure why you are not seeing more then first pulse looped.
I forgot to post update. I figured it out. I was calling clearcommands and then Dispose to try to get the RMT to stop. What seems to happen is it removes commands 2-N in the list but not the first command. As far as I can tell the only way to stop it looping the first command is to remove power to the board.
I plan to go back to RTM when the sync manager is there but for now I’m using PWM. It’s less flexible but the start and stop commands work.
@stark horizon @autumn beacon @grizzled folio OK guys! I am taking the plunge and following Jose's instructions on how to setup to my system to build NF so I can get these pulses timed perfectly - it's medically dangerous to the patient if TENS pulses aren't perfectly timed - I am sure I will have lots of questions. Is there a better thread for asking these questions? (And Adrian, looking forward to sync manager to save me from myself! I am a bit terrified to build the whole framework myself!)
(I found the build your own thread.)
ADRIAN!!!! I managed to get it working!!!!!! I created a interop and write directly to the RMT register!
=> ((uint32_t ) (0x600160C4)) |= param0; // 0x1F for all channels.
Thats great. I am currently working on new version with sync manager included.
I can’t wait! I think figuring out how to do this using a native interop really helped me understand NF better so was worth the experience.
One of the things I learned - which you should watch for - is there is a ESP-IDF bug with stopping transmission. At present with NF there is no way to actually stop the RMT once you start it in loop mode. Even disposing of all the channels doesn’t work. It disposes all but the first seemingly and plays its sequence forever. A (simple?) stop - like with PWM would be really good.
Espressif ESP32 Official Forum
Oh also - I timed the sync with 4 channels and it looks like +- 100 nanoseconds from channel 0 to 3. Oddly the last channel (which triggers all the rest) comes in ahead of the first.
But to the uS they are stout!
There is a rmt_disable() would that stop the transmitting.
I don’t think that’s exposed.
But from link above I’m not the only one who has seen it - not a big deal for me though. I am lucky because we have a high voltage power latch. I can let the pulses play forever and unless I latch the high voltage it’s like they’re not even on. 😉
I think NF only exposes the channels themselves at present. There’s not an overarching manager.
You are right, there is no manager yet.
But it’s done VERY well because I could not write the register until I define the channels - that enables the RTC clock and whatever’s needed to write the registers.
I continue to be very impressed with the NF crew! I’m in hook line and sinker!
I really like this community as we get responses very quickly.
(Even if you are an annoying old guy like me !!! I apologize to everyone and will start answering questions as soon as I can!!!)
I am no spring chicken here too.
Were you born before pong? Use rotary phones? lol
Yes have rotary dial phone before all this digital stuff.
Now even the house is without a physical land line phone.
I played asteroids when I was 7 or 8 loaded off a cassette tape on a commodore - took 20 min to load of you were lucky!
I did not have the luxury of having that but was drooling over it. 😄
I didn’t have it either! My friends dad had it.
My first computer was an XT with 1MB of ram. That was like king of the hill. 😄
My dad worked at NASA in the 70’s. He was cheap but some of my friends had computers.
Oh man - that’s what I went to college with in 88
I had the fastest computer at all of brown university!
All the rich kids has Mac’s. lol. Remember the ticking time bomb that counted down until it lost all your files!!! Hilarious!