Teensy 4.1 Dual motor control (PMSM/BLDC)

Elwin

Member
Hi all,

For quite a while I have been working on a dual motor (PMSM/BLDC) control board for Teensy 4.1.

Main goal for me is to learn things, so all help is welcome!

It is working quite good if I may say so. The control loops are running at 60 kHz, with the possibility to do an endless trace of 14 signals to the host PC.

Implemented:
Field oriented control
Torque and position control
3th order setpoints
2 ABI Encoders (differential via RS422)
2 motors (not using the 2nd one currently)
Sensorless control: backEMF
Sensorless control: silent HFI
FRF measurements: PRBS and single sine

Python:
Getting and setting of any signal, based on names
Tracing of 14 signals at full 60 kHz
Controller tuning with bode and nyquist plots
Terrible GUI

Code: https://github.com/ElwinBoots/Teensy_DualMotorBoard_V1
PCB: Not uploaded yet
Amplifier board: DRV8301 boards from aliexpress
Current sensors: Pololu board with ACS711EX (15.5 or 31 A)

I ran a motor to over 300000 erpm without issues at 99% duty cycle.

Note: by no means this is ready to be used by beginners in motor control

Some pictures:
Bodeplot.png300kerpm.png300kerpm2.jpgslow.jpgslow2.jpgnicetrace.jpgPCB.jpg
 
Interesting - not come across the DRV8301 before, seems quite complex but I can see the benefit of some of the protection features.

What motors have you managed to drive?
 
Very nice and complete project, I may have some tracing updates (tracing of vectors) if you are interested ;)
 
The board with the drv8301 is pretty simple to use. Not sure about the protection though, it seems most VESC designs no longer use these chips because they often fail (I guess due to overvoltage). I only had 1 fail, and that was totally my fault. My power supply cannot take energy in, so the bus voltage went up way to high when I was braking.

All motors I have tried work fine, just need to measure the parameters and set them.

Tested motors
Turnigy Rotomax 100cc
Pancake motor
Very small outrunner (the 300 kerm was on this one)
Small industrial servomotor Wittenstein MSSI 055G-045E-048C-0FN0-F2100
Medium sized industrial servomotor
 
The tracing function works very good, but I would like to make it even better.

I tried to increase the buffer size of the serial at the host side (Windows) but this doesn't seem to do anything. Anybody knows how this can be increased? When the buffer is not emptied in time the Teensy does very strange stuff (not good).

Maybe somebody has experience with implementing a background task or somethong like that in Python that grabs the data? This would also be very helpful.

PS. Nice job Paul, Teensy is very powerful!
 
So no 3-phase induction motor? That's the ultimate challenge - easier with an encoder.

Yes, a 4-quadrant motor controller needs a rail clamp circuit (braking circuit), that's pretty much essential for motor control at higher power due to back-feeding issue (battery supply avoids the problem, aka regenerative braking).
 
Correct, no induction motor yet. Don't have one either. Would be fun though to try.

Yeah since I blew up one of these chips I added a chopper resistor. Takes care of the regen issue nicely.
 
@PaulStoffregen

I am having some strange behaviour with the ADCs my Teensy 4.1's, I hope you can point me in the right direction.

I run both ADCs triggered from the flexPWM2 using FLEXPWM_SMTCTRL_OUT_TRIG_EN. Normally I trigger both when the timer is zero and when the timer is at the max value.

The problem I observe is that the ADCs are sometimes (seemly randomly after boot, about 50-50 whether it happens or not) more noisy, and contains a frequency spike at exactly 1/4th of the PWM frequency:

Schermafbeelding 2022-04-22 171047.jpg

When after bootup, it has this noise, it never goes away. Restarting Teensy by unplugging and plugging it back in resets the behaviour, and I again randomly get either the noisy situation or the non-noisy situation.

I already disconnected all other hardware, and tried two different Teensy 4.1's. I disabled the PWM outputs. Behaviour occurs independent of selected PWM frequency (Tried multiple frequencies between 10 kHz 30 kHz). Currently testing on Teensy 4.1 with the used analog ins connected directly to ground: same effect (this is used for the attached graphs).

One observation which I think is important is that when I trigger the ADC only once per cycle (instead of twice), and increase the PWM frequency by factor 2 to keep the same overall sampling frequency, the noise is still at exactly 1/4th of the PWM frequency. But since the PWM frequency is doubled the noise frequency has then doubles (although the sampling frequency remained the same).

Do you have any idea what could cause this behaviour?
Do you have ideas what I can do to further test this?

Thanks in advance!
 
Made some code that shows my issue in serial monitor.

Teensy 4.1
Connect pin 16 to ground

Look at serial monitor (and reboot a few times to see both situations occuring):
Good:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 2 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0
0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0
0 0 3 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 2 0 0 0
0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 3 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 4 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 0
0 0 0 0 0 0 0 1 0 2 0 0 0 1 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 0 0 0 3 0 2 0 0 0 0 0 1 0 0 0 1 0 0 0
0 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 2 0 0

Bad (noisy):
0 3 1 0 1 2 0 1 0 0 2 0 1 2 0 1 0 0 1 0 1 2 0 1 0 0 2 0 1 2 0 1 0 0 1 0 2 1 0 1 0 0 2 0 1 2 0 2 0 0
2 0 1 2 0 1 1 0 1 0 2 2 0 1 0 0 1 3 2 1 0 2 0 0 1 0 1 1 0 1 0 0 2 0 1 2 0 2 0 0 1 0 2 2 0 1 0 0 2 0
3 1 0 2 0 0 1 0 1 1 0 2 0 0 1 0 2 1 0 1 0 0 2 0 1 4 0 6 0 0 0 0 1 2 1 2 0 0 1 0 1 2 0 1 0 0 1 0 2 0
0 2 0 0 1 1 1 2 0 1 0 0 1 0 5 2 2 1 0 0 1 0 2 2 0 1 0 0 2 0 1 2 0 2 0 0 2 0 2 2 0 2 2 0 3 0 1 2 0 1
0 0 1 0 2 3 0 4 0 0 1 0 2 3 0 2 0 0 1 0 2 2 0 2 0 0 2 0 1 2 0 1 1 0 2 0 1 2 0 1 0 0 2 0 1 2 0 4 0 0
2 0 1 2 0 1 0 0 1 0 2 2 0 2 0 0 1 0 1 2 0 2 0 0 1 0 2 1 0 1 0 0 1 0 1 2 0 2 0 0 2 0 2 1 0 1 0 0 2 0
2 2 0 1 0 0 3 0 1 2 1 1 1 0 1 0 2 1 1 2 0 0 2 0 2 2 0 2 0 0 5 0 2 1 0 1 0 0 1 0 2 1 0 1 0 0 1 1 2 0
0 2 0 1 1 0 2 1 0 1 0 0 2 0 2 1 0 1 0 0 2 0 1 1 0 4 0 0 1 2 2 1 0 2 0 0 1 0 1 1 0 1 0 0 1 0 2 2 0 1
0 0 2 0 1 2 0 1 0 0 1 0 2 3 0 1 0 1 1 0 2 0 0 2 0 0 1 1 1 1 0 1 0 0 2 0 1 2 0 5 0 0 1 0 1 3 0 1 0 0
1 0 2 1 0 1 0 0 2 0 1 2 0 1 0 0 1 0 3 1 0 1 1 0 1 0 3 1 0 2 2 0 0 0 2 2 0 1 0 0 2 0 5 2 0 1 0 2 1 0
2 2 0 2 0 0 1 0 0 1 0 2 0 0 1 0 2 1 0 4 0 1 1 1 1 1 0 2 0 0 1 0 1 2 0 2 0 0 0 0 1 2 0 1 1 0 1 0 1 3
0 2 0 1 2 1 2 1 0 5 0 0 1 0 2 1 0 0 0 0 1 0 2 2 0 2 1 0 1 0 4 1 0 2 0 0 1 0 1 2 0 1 0 1 1 1 2 4 0 2
0 0 1 0 1 1 1 1 0 0 2 0 0 1 0 2 0 0 1 0 1 1 0 1 0 0 1 0 1 2 0 4 0 0 1 0 2 1 0 1 0 0 1 0 0 2 0 2 0 0
2 0 1 4 0 1 0 0 1 0 2 2 0 1 2 0 1 0 1 1 0 2 0 0 2 0 1 2 0 5 0 0 2 0 1 1 0 1 0 0 2 0 1 2 0 1 0 0 1 0
2 2 0 2 0 0 1 0 1 1 0 1 0 0 2 0 1 2 0 2 0 0 1 0 2 2 0 0 0 0 1 0 2 1 0 2 0 0 2 0 1 1 0 2 0 0 2 0 1 1
0 1 0 0 0 0 2 1 0 1 0 0 2 0 2 2 0 1 0 0 1 0 3 4 0 0 0 0 1 0 3 1 0 1 0 0 2 0 1 2 0 4 0 0 1 0 1 2 0 1
0 0 2 0 1 2 0 1 0 0 4 0 2 3 0 2 0 1 1 0 1 2 0 2 0 0 1 0 2 1 0 1 0 0 1 0 1 3 0 1 0 0 1 0 2 1 0 1 0 0
1 0 2 2 0 1 1 0 1 0 2 1 0 4 0 0 2 0 1 2 0 1 0 0 1 0 2 1 0 1 0 0 1 0 1 2 0 1 0 0 1 0 2 1 0 1 0 0 1 0
1 1 0 1 0 0 1 0 1 1 0 2 0 0 1 0 2 1 0 1 0 0 1 0 2 2 0 2 0 0 1 0 2 1 0 2 0 0 2 0 1 2 0 2 0 0 1 0 2 2
0 2 0 0 1 0 6 1 1 2 0 0 2 0 2 2 0 0 0 0 1 0 2 1 0 2 0 0 1 0 2 1 0 1 0 0 2 0 2 2 0 1 1 0 1 0 2 1 0 2
0 0 1 0 1 3 2 1 0 0 1 0 1 2 0 1 0 0 3 0 2 2 0 1 0 0 1 0 0 4 0 2 0 0 2 0 2 1 0 1 0 0 1 0 1 2 0 2 0 0
2 0 1 2 0 1 3 0 1 0 1 2 0 2 0 0 1 0 2 2 0 1 0 0 2 0 1 2 0 2 0 0 1 0 4 2 0 2 0 0 2 0 1 2 0 2 0 1 3 2
2 3 0 1 0 0 2 0 1 2 0 1 0 0 1 0 2 1 0 1 0 0 1 0 1 1 0 2 0 0 1 0 1 2 0 1 0 0 1 0 1 2 0 3 0 2 1 0 2 2
0 2 0 0 1 0 1 1 0 0 0 0 4 0 1 1 1 2 0 0 2 0 1 2 0 1 0 0 1 0 1 1 0 4 0 0 2 0 1 2 0 2 0 0 1 0 2 2 0 1
0 0 3 0 1 1 1 1 0 0 2 0 1 2 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 3 0 2 0 0 1 0 2 1 0 2 0 0 1 0 1 2 0 1 0 0
1 0 2 1 3 2 0 0 2 0 1 2 0 2 0 0 1 0 1 2 0 2 0 0 1 0 2 1 0 3 2 3 1 0 1 2 0 1 0 0 2 0 1 2 0 2 0 0 1 0
1 2 0 2 0 0 0 0 1 1 0 1 0 0 2 1 2 2 1 1 0 0 2 0 1 2 0 1 0 0 1 0 2 2 0 2 0 0 1 0 2 2 0 1 0 0 1 0 1 1
0 3 0 0 5 0 1 4 0 3 0 0 4 1 1 5 0 2 0 0 1 0 1 2 3 2 0 0 2 0 2 1 0 2 0 0 1 0 2 2 0 1 0 0 2 0 2 2 0 1
0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 0 0 1 3 0 2 0 0 2 0 1 1 0 1 0 0 1 0 1 1 0 2 0 0 1 0 2 2 0 1 0 0
1 0 3 1 0 1 0 0 1 0 1 4 1 1 1 0 0 1 1 4 2 2 0 1 4 0 1 2 0 2 0 2 1 0 1 5 0 0 0 0 1 2 1 1 1 2 0 0 1 0
2 1 2 2 0 0 3 0 2 3 0 0 3 0 1 2 1 4 0 1 0 0 1 0 4 2 0 1 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 0 1 0 1 2
0 1 0 0 1 0 2 2 0 2 0 0 1 0 2 1 0 1 0 0 2 0 1 3 0 2 0 0 1 0 1 2 0 2 0 0 1 0 2 1 0 2 0 2 2 0 1 1 0 1
0 0 1 0 1 2 0 1 0 0 1 0 1 2 0 2 0 0 1 0 1 2 0 1 0 0 2 0 2 2 1 1 0 3 1 0 1 1 0 1 0 0 1 0 1 2 0 2 0 0
2 0 2 2 0 1 0 0 1 0 2 1 0 1 0 0 1 2 0 0 2 4 0 0 3 0 2 2 0 1 0 0 1 0 2 1 0 1 0 0 2 0 1 3 0 1 0 0 1 0
1 0 0 1 0 0 0 0 1 2 0 1 0 0 1 0 2 1 4 2 0 3 2 0 3 2 0 2 0 0 2 0 1 2 0 2 0 0 1 0 4 1 0 1 0 0 1 0 1 2
0 2 0 0 1 0 1 2 0 2 0 0 1 0 2 1 0 1 0 0 1 0 1 3 0 2 0 0 3 0 1 3 0 1 0 0 2 0 2 2 0 2 0 2 4 0 1 1 0 1
0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 2 0 2 0 0 3 0 2 2 0 1 0 0 2 0 2 3 0 3 0 0 4 0 1 1 0 1 0 0
1 0 2 2 0 1 0 0 1 0 1 1 0 1 0 0 1 0 2 2 0 1 0 0 4 0 0 1 0 2 0 0 1 0 3 2 0 2 0 0 1 0 1 2 0 2 0 0 2 0
2 2 1 0 0 0 1 0 1 2 0 2 0 0 2 3 1 1 0 1 0 0 1 0 1 3 0 1 0 0 1 0 1 1 0 1 0 0 2 0 3 2 0 2 1 0 1 0 2 3
0 2 0 0 1 0 2 2 0 1 0 0 2 0 1 1 3 1 0 0 2 0 1 2 0 2 0 0 0 0 1 2 0 2 0 0 1 0 1 1 0 1 0 0 1 0 1 2 0 2
1 0 1 0 2 2 0 1 0 0 1 0 2 2 0 1 0 0 2 0 1 3 0 1 0 0 1 0 2 2 0 3 1 0 1 0 3 1 0 2 0 0 2 0 4 2 0 1 0 0
2 0 1 4 0 1 0 0 1 0 2 1 0 2 0 0 1 0 1 2 0 2 0 0 3 0 2 2 0 1 0 0 2 0 0 2 0 2 0 0 1 2 3 1 0 1 0 0 2 0
2 2 0 1 1 0 2 0 2 1 0 1 1 0 0 0 1 1 0 1 0 3 1 0 1 2 0 2 0 0 1 0 0 1 0 2 0 0 2 0 2 3 0 0 0 0 1 0 3 1
0 1 0 0 1 0 2 2 0 1 0 0 1 0 1 1 1 0 0 0 2 0 2 1 0 5 0 0 1 0 1 2 0 2 0 0 1 0 2 2 0 1 0 0 1 0 1 3 0 3
2 0 1 0 2 1 0 2 0 0 1 0 2 2 0 2 0 0 1 0 1 2 0 1 0 0 4 0 0 1 0 2 0 2 2 0 3 2 0 2 0 0 1 0 2 1 0 1 0 0




Code:
#define f_pwm 20e3
unsigned int curtime;
unsigned int sens1;
unsigned int cursample;


void setup() {
  Serial.begin(9600);
  Serial.println("Hi");
  xbar_init();
  adc_init();
  adc_etc_init();
  flexpwm2_init();
}

void loop() {
}

void adcetc0_isr() {
  curtime = micros();
  cursample++;
  ADC_ETC_DONE0_1_IRQ |= 1 << 20;   // clear
  FLEXPWM2_SM0STS |= FLEXPWM_SMSTS_CMPF(2); //Reset flag
  sens1 = (ADC_ETC_TRIG0_RESULT_1_0 & 4095);

  Serial.print(sens1 );
  Serial.print(" ");
  if (cursample == 50) {
    cursample = 0;
    Serial.println("");
  }
}


void xbar_init() {
  CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);   //turn clock on for xbara1
  xbar_connect(XBARA1_IN_FLEXPWM2_PWM1_OUT_TRIG0, XBARA1_OUT_ADC_ETC_TRIG00); //FlexPWM to adc_etc
}

void adc_init() {
  //Tried many configurations, but this seems to be best:
  ADC1_CFG =   ADC_CFG_OVWREN       //Allow overwriting of the next converted Data onto the existing
               | ADC_CFG_ADICLK(0)    // input clock select - IPG clock
               | ADC_CFG_MODE(2)      // 12-bit conversion 0 8-bit conversion 1 10-bit conversion 2  12-bit conversion
               | ADC_CFG_ADIV(2)      // Input clock / 4
               | ADC_CFG_ADSTS(0)     // Sample period (ADC clocks) = 3 if ADLSMP=0b
               | ADC_CFG_ADHSC        // High speed operation
               | ADC_CFG_ADTRG;       // Hardware trigger selected
  ADC2_CFG = ADC1_CFG;

  //  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_02 &= ~ (1 << 12) ; // disable keeper pin 14, as per manual
  //  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_03 &= ~ (1 << 12) ; // disable keeper pin 15, as per manual
  //  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_07 &= ~ (1 << 12) ; // disable keeper pin 16, as per manual
  //  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_06 &= ~ (1 << 12) ; // disable keeper pin 17, as per manual
  //  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_01 &= ~ (1 << 12) ; // disable keeper pin 18, as per manual
  //  IOMUXC_SW_PAD_CTL_PAD_GPIO_AD_B1_00 &= ~ (1 << 12) ; // disable keeper pin 19, as per manual

  //Calibration of ADC
  //  ADC1_GC |= ADC_GC_CAL;   // begin cal ADC1
  //  while (ADC1_GC & ADC_GC_CAL) ;
  //  ADC2_GC |= ADC_GC_CAL;   // begin cal ADC2
  //  while (ADC2_GC & ADC_GC_CAL) ;

  ADC1_HC0 = 16;   // ADC_ETC channel
  ADC2_HC0 = 16;
}

void adc_etc_init() {
  /* Must disable software reset first */
  ADC_ETC_CTRL &= ~(1 << 31); // SOFTRST

  /* Must clear ADC_ETC_CTRL_TSC_BYPASS bit if using ADC2 */
  ADC_ETC_CTRL &= ~(1 << 30); // TSC_BYPASS

  /* Enable the external XBAR trigger0 and trigger1. Trigger4 uses sync mode to get triggered */
  ADC_ETC_CTRL = 1;  // TRIG_ENABLE

  /* ADC channel, pin numbers
    7,  // 14/A0  AD_B1_02
    8,  // 15/A1  AD_B1_03
    12, // 16/A2  AD_B1_07
    11, // 17/A3  AD_B1_06
    6,  // 18/A4  AD_B1_01
    5,  // 19/A5  AD_B1_00

    12, // 16/A2  AD_B1_07  M1 Ia
    8,  // 15/A1  AD_B1_03  M1 Ib

    6,  // 18/A4  AD_B1_01  M1 Va
    5,  // 19/A5  AD_B1_00  M1 Vb

    11, // 17/A3  AD_B1_06 Vbus

  */

  ADC_ETC_TRIG0_CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(2); //TRIG chain length (0->1, 1->2, etc)

  ADC_ETC_TRIG0_CHAIN_1_0 =
    ADC_ETC_TRIG_CHAIN_IE1(0) |
    ADC_ETC_TRIG_CHAIN_B2B1 |
    ADC_ETC_TRIG_CHAIN_HWTS1(1) |
    ADC_ETC_TRIG_CHAIN_CSEL1(6) |
    ADC_ETC_TRIG_CHAIN_IE0(0) |
    ADC_ETC_TRIG_CHAIN_B2B0 |
    ADC_ETC_TRIG_CHAIN_HWTS0(1) |
    ADC_ETC_TRIG_CHAIN_CSEL0(12);

  ADC_ETC_TRIG0_CHAIN_3_2 =
    ADC_ETC_TRIG_CHAIN_IE0(1) |
    ADC_ETC_TRIG_CHAIN_B2B0 |
    ADC_ETC_TRIG_CHAIN_HWTS0(1) |
    ADC_ETC_TRIG_CHAIN_CSEL0(11);

  ADC_ETC_TRIG4_CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(2) | ADC_ETC_TRIG_CTRL_SYNC_MODE; //TRIG chain length (0->1, 1->2, etc), turn on sync mode
  ADC_ETC_TRIG4_CHAIN_1_0 =
    ADC_ETC_TRIG_CHAIN_IE1(0) |
    ADC_ETC_TRIG_CHAIN_B2B1 |
    ADC_ETC_TRIG_CHAIN_HWTS1(1) |
    ADC_ETC_TRIG_CHAIN_CSEL1(5) |
    ADC_ETC_TRIG_CHAIN_IE0(0) |
    ADC_ETC_TRIG_CHAIN_B2B0 |
    ADC_ETC_TRIG_CHAIN_HWTS0(1) |
    ADC_ETC_TRIG_CHAIN_CSEL0(8);

  ADC_ETC_TRIG4_CHAIN_3_2 =
    ADC_ETC_TRIG_CHAIN_IE0(2) |
    ADC_ETC_TRIG_CHAIN_B2B0 |
    ADC_ETC_TRIG_CHAIN_HWTS0(1) |
    ADC_ETC_TRIG_CHAIN_CSEL0(5);

  attachInterruptVector(IRQ_ADC_ETC0, adcetc0_isr);
  NVIC_ENABLE_IRQ(IRQ_ADC_ETC0);
}


void flexpwm2_init() {     //set PWM
  FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_CLDOK( 7 );//  Clear Load Okay LDOK(SM) -> no reload of PWM settings
  FLEXPWM2_SM0CTRL = FLEXPWM_SMCTRL_FULL | FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(0); //Fixed at no prescaler. Prescaler is only usefull for slow PWM
  FLEXPWM2_SM1CTRL = FLEXPWM_SMCTRL_FULL | FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(0); //Fixed at no prescaler. Prescaler is only usefull for slow PWM
  FLEXPWM2_SM2CTRL = FLEXPWM_SMCTRL_FULL | FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(0); //Fixed at no prescaler. Prescaler is only usefull for slow PWM
  FLEXPWM2_SM0VAL1 = (uint32_t)((float)F_BUS_ACTUAL / f_pwm - 1) / 2; //Set the modulus value (dictates the frequency)
  FLEXPWM2_SM1VAL1 = FLEXPWM2_SM0VAL1;  //Set the modulus value (dictates the frequency)
  FLEXPWM2_SM2VAL1 = FLEXPWM2_SM0VAL1;  //Set the modulus value (dictates the frequency)
  FLEXPWM2_SM0INIT = -FLEXPWM2_SM0VAL1; //Good for center aligned PWM, see manual
  FLEXPWM2_SM1INIT = -FLEXPWM2_SM1VAL1; //Good for center aligned PWM, see manual
  FLEXPWM2_SM2INIT = -FLEXPWM2_SM2VAL1; //Good for center aligned PWM, see manual

  FLEXPWM2_SM0VAL3 = FLEXPWM2_SM0VAL1 / 2; //50% duty cycle
  FLEXPWM2_SM0VAL2 = -FLEXPWM2_SM0VAL3; //50% duty cycle
  FLEXPWM2_SM1VAL3 = FLEXPWM2_SM0VAL1 / 2; //50% duty cycle
  FLEXPWM2_SM1VAL2 = -FLEXPWM2_SM0VAL3; //50% duty cycle
  FLEXPWM2_SM2VAL3 = FLEXPWM2_SM0VAL1 / 2; //50% duty cycle
  FLEXPWM2_SM2VAL2 = -FLEXPWM2_SM0VAL3; //50% duty cycle

  FLEXPWM2_SM0VAL4 = 0; // adc trigger 1
  FLEXPWM2_SM0VAL5 = FLEXPWM2_SM0VAL1; // adc trigger 2

  FLEXPWM2_MCTRL |= FLEXPWM_MCTRL_LDOK( 7 );// Load Okay LDOK(SM) -> reload setting again

  //This triggers twice per PWM cycle:
  FLEXPWM2_SM0TCTRL = FLEXPWM_SMTCTRL_OUT_TRIG_EN(1 << 4) | FLEXPWM_SMTCTRL_OUT_TRIG_EN(1 << 5); //  val 4 of Flexpwm sm0 as trigger;
  //This triggers once per PWM cycle:
  //FLEXPWM2_SM0TCTRL = FLEXPWM_SMTCTRL_OUT_TRIG_EN(1 << 5); //  val 4 of Flexpwm sm0 as trigger; )
}


void xbar_connect(unsigned int input, unsigned int output)
{
  if (input >= 88) return;
  if (output >= 132) return;
  volatile uint16_t *xbar = &XBARA1_SEL0 + (output / 2);
  uint16_t val = *xbar;
  if (!(output & 1)) {
    val = (val & 0xFF00) | input;
  } else {
    val = (val & 0x00FF) | (input << 8);
  }
  *xbar = val;
}
 
Problem doesn't seems to happen ever when I disable the code for the 2nd ADC:

Code:
//  ADC_ETC_TRIG4_CTRL = ADC_ETC_TRIG_CTRL_TRIG_CHAIN(2) | ADC_ETC_TRIG_CTRL_SYNC_MODE; //TRIG chain length (0->1, 1->2, etc), turn on sync mode
//  ADC_ETC_TRIG4_CHAIN_1_0 =
//    ADC_ETC_TRIG_CHAIN_IE1(0) |
//    ADC_ETC_TRIG_CHAIN_B2B1 |
//    ADC_ETC_TRIG_CHAIN_HWTS1(1) |
//    ADC_ETC_TRIG_CHAIN_CSEL1(5) |
//    ADC_ETC_TRIG_CHAIN_IE0(0) |
//    ADC_ETC_TRIG_CHAIN_B2B0 |
//    ADC_ETC_TRIG_CHAIN_HWTS0(1) |
//    ADC_ETC_TRIG_CHAIN_CSEL0(8);
//
//  ADC_ETC_TRIG4_CHAIN_3_2 =
//    ADC_ETC_TRIG_CHAIN_IE0(1) |
//    ADC_ETC_TRIG_CHAIN_B2B0 |
//    ADC_ETC_TRIG_CHAIN_HWTS0(1) |
//    ADC_ETC_TRIG_CHAIN_CSEL0(5);
 
Back
Top