This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi all,
I'm trying to use the N2HET SWAG on the TMS570LS1224 (N2HET at 80 MHz) to interface a toothed wheel (1 missing and 7 actual teeth), simulated as a 50% duty cycle 4 KHz signal generated through the RTI.
If I set gapstart and gapend both at 0, the individual teeth-cycles are detected correctly (the missing tooth is seen as an extension of the 7th tooth). However, with a stepsize of 8, the correct gapstart and gapend should be 8 * (7 - 1) + 1 = 49 and 8 * 8 - 1 = 63, according to SPNU515b.
In my understanding, the following code should produce a switch on N2HET pin 20 every revolution (8 teeth):
; Angle Counter L00 APCNT { next=L01,irq=OFF,type=RISE2RISE,prv=ON,period=0,data=0}; L01 SCNT { next=L02,step=8,gapstart=49,data=0}; L02 ACNT { next=OUT20,edge=RISING,gapend=63,data=0}; ; Change OUT20 OUT20 ACMP { next=L00,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=20,action=SET,reg=B,data=0}; ; Switch OUT20 OUT20_PULSE_LOW MOV64 { next=L00,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_HIGH,pin=20,comp_mode=ECMP,action=CLEAR,reg=B,data=0}; OUT20_PULSE_HIGH MOV64 { next=L00,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=20,comp_mode=ECMP,action=SET,reg=B,data=0};
However, the switches on pin 20 take 11 or 12 teeth instead of 8. The last 3 days I've tried several gapstart and -end settings, several numer of teeth per revolution, with or without missing teeth, but the revolution/gap detection seems to produce inconsistent results. I found https://e2e.ti.com/support/microcontrollers/hercules/f/312/p/411737/1497955, but it quickly goes into the HWAG, while I would like to stay with the SWAG. I ordered a new USB stick and when that arrives, I will add scope traces.
Does anyone know how to get the gap/revolution detection working correctly?
Edit: added scope traces for gapstart == 49 and gapend == 63
Hi Tim,
Think I just got the HET IDE issue fixed - some of the stimulus commands were being dropped between the GUI and the backend simulator ... simulator wasn't assuming commands could be split across multiple recv() calls.
Anyway got this picture now for stimulus:
The stimulus is setup to repeat at 2ms so there's 7 teeth, gap and then two teeth from the next cycle in the picture (more would appear if I ran the sim longer).
Here's a picture numerically of the stimulus - all are set to repeat at 2000us intervals even though it doesn't show the repeat in this top level view:
So pls. let me know if this stimulus matches your expectation. If so we can trace through your SWAG program execution and figure out what's going on.
Best Regards,
Anthony
Hi Anthony,
Thanks for the effort, the stimulus pattern indeed matches what I generated with the RTI. I only have the free version of WaveViewer, so I think I cannot generate a custom stimulus.
Best,
Tim
Hi Tim,
So far, here's what I see when I run your program in the HET IDE, along with some of my personal 'commentary'.
Note the NAF (het.flag_naf trace) and how angle increments are counted off too fast during the initial interval..
I think the program needs some 'startup help'. For example the PCNT instruction (not sure why I don't see this for APCNT) has a reminder that the measurement captured at the first edge has to be discarded. It's measuring an interval (rise 2 rise) at every rising edge, but the measurement at the first rising edge is from an unknown reference and needs to be discarded.
You can see that the step count during the interval in red seems to be counting off angle ticks too fast. So that's one issue.
I think this could be corrected by adding an instruction or two that protects angle counter during the startup interval, i.e.. waits until the 2nd edge on the angle input is detected before executing the SCNT, ACNT, ACMP.
The other place that the counter may need startup help is in the synchronization to the intial GAP. This could be done with the help of the CPU or the HET again, and I'm sure there's a bit of an art form to how this is handled in real world situations which I don't claim to be an expert on. But I'm suspecting that just starting out the GAP may not be in the right place either during the sync up period.
I still haven't digested the waveforms that you sent ... on silicon you've probably run a lot more cycles than I just ran in the simulator and it may have sync'd itself by the time you got you capture - so these things may be completely unrelated. Not sure if the bad startup will continue to propogate, but in any case it's interesting.
The screen shot is about all that I can simulate with the free license for Synapticad. We've purchased a floating license but the server needs a reboot so gotta wait till that happens to simulate more cycles. Looks like unforutunately we only get 1 rotation within the memory limit of the viewer.
If we can speed up the angle input say by a factor of 10 and still have the experiment in the simulator be 'valid' though -- that might be something to try.
Best Regards,
Anthony
Hi Anthony,
I adjusted the HET program to discard the first several NAFs:
L00 APCNT { next=NAF_STARTUP_PROTECTION,irq=OFF,type=RISE2RISE,prv=OFF,period=0,data=0}; NAF_STARTUP_PROTECTION MCMP { brk=OFF,next=NAF_BR,request=NOREQ,hr_lr=LOW,angle_comp=OFF,savesub=OFF,control=OFF,en_pin_action=OFF,cond_addr=L01,pin=2,order=REG_GE_DATA,reg=S,data=2}; NAF_BR BR { next=L00,prv=OFF,cond_addr=NAF_INC,pin=2,event=NAF}; NAF_INC ADD { src1=IMM,src2=S,dest=S,next=L00,remote=NAF_INC,data=1}; L01 SCNT { next=L02,step=8,gapstart=49,data=0}; L02 ACNT { next=OUT20,edge=RISING,gapend=63,data=0}; OUT20 ACMP { next=L00,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=20,action=SET,reg=B,data=0}; OUT20_PULSE_LOW MOV64 { next=BACKUP_REG_A,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_HIGH,pin=20,comp_mode=ECMP,action=CLEAR,reg=B,data=0}; OUT20_PULSE_HIGH MOV64 { next=BACKUP_REG_A,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=20,comp_mode=ECMP,action=SET,reg=B,data=0};
This resulted in not getting output on the launchpad if NAF_STARTUP_PROTECTION.data != 0. In the simulator, if NAF_STARTUP_PROTECTION.data != 0, it seems NAF_BR always evaluates to true though, even if the NAF flags are false.
If I drive hetm.watch_2.in with "((250us=1 250us=0)*7 500us=0) * 10", I see the waveform, but no response on pin 20 as I expected. I tried to speed up the simulation by 10x, with "((25us=1 25us=0)*7 50us=0) * 10" as input, but I still got no output, so I assume my method for signal input is incorrect (hetm.watch_2.in -> edit selected signals -> set to drive -> enter equation). How do I correctly generate input for the simulator?
Hi Tim,
Sorry - I think the simulator is a dead-end at the moment when it comes to SWAG instructions (APCNT, SCNT, ACNT, ACMP)- the SWAG instructions are likely not completely functional. I got pretty deep into a simulation yesterday and SCNT was not counting for long periods (in the simultor - which we *know* doens't match hardware). Then we looked at the validation suite and noted that the angle instructions are notably absent from the validation. Not sure what the history is there. I'm sure we can fix this but it'll take some time.
If you *see* the stimulus you enter in the simulator show up in the waveform, then it's happening. So from what it sounds like the issue is in the output. I did get output from pin 20 with your program the other day but it was at seemingly odd times and took quite a while to appear (multiple cycles of the wheel before output started), and this I tracked down to SCNT not working in the simulator.
The good news from all this is that one of my colleagues Charles Tsai has done some work on the SWAG and has a test case that will generate angles-reference outputs correctly provided he synchronizes to the GAP. He used the CPU and a 2nd N2HET to do this.
This should be able to be done in the N2HET as well. But I think there's two issues. First the initial APCNT result needs to be always discarded as it's not a full period / interval measurement. Then, we need to loop comparing the next 3 apcnt results till a gap is detected. To detect the gap we would actually measure the intervals and do some math rather than relying on the gap start / gap end instrucitons of the SWAG. Then after that we'd count off teeth until the next gap and if that occurs in the correct location - let the ACMP loose.
Will work on some code for this... what I've got so far is below in case you want to experiment with it, but it's not working yet.
As it is the code multiples the middle tooth by a factor 1.75 but it should be multiplying by 1/1.75 so I am working on a mod right now for that ..
NTEETH .equ 7 STEP_FACTOR .equ 8 GAP_START .equ (NTEETH-1)*STEP_FACTOR + 1 GAP_END .equ (NTEETH+1)*STEP_FACTOR - 1 ; Angle Counter L00 APCNT {irq=OFF,type=RISE2RISE,prv=ON,period=0,data=0, next=G00}; L01 SCNT { step=STEP_FACTOR,gapstart=GAP_START,data=0}; L02 ACNT { edge=RISING,gapend=GAP_END,data=0, next=G01}; ; Change OUT20 OUT20 ACMP { next=L00,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW,pin=20,action=SET,reg=B,data=22}; ; Switch OUT20 OUT20_PULSE_LOW MOV64 { next=L00,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_HIGH,pin=20,comp_mode=ECMP,action=CLEAR,reg=B,data=40}; OUT20_PULSE_HIGH MOV64 { next=L00,remote=OUT20,en_pin_action=ON,cond_addr=OUT20_PULSE_LOW, pin=20,comp_mode=ECMP,action=SET, reg=B,data=22}; ; Gate to SCNT, ACNT G00 DJZ {cond_addr=L01, next=S00, data=1} ; Gate to ACMP G01 DJZ {cond_addr=OUT20, next=L00, data=1} ; Synchronize start of SWAG ; NB: DJZ doesn't modify Z Flag, so BR S00 BR {event=NZ, cond_addr=CG00, next=S01} S01 DJZ {cond_addr=S02, next=CG00, data=1} ;discard 1st APCNT - it is invalid ; FIFO holding last three measurements (S02 is oldest, S04 is newest) S02 ADD {src1=REM, src2=ZERO, dest=IMM, data=0, hr_data=0, remote=S03} ;N2 S03 ADD {src1=REM, src2=ZERO, dest=IMM, data=0, hr_data=0, remote=S04} ;N1 S04 ADD {src1=T, src2=ZERO, dest=IMM, data=0, hr_data=0} ;N ; Calculate 0.057 * N1 ; NB: compute 0.057 * N1 = (8192*N1 + 1024*N1 + 128*N1) / 16384 S05 ADD {src1=REM, src2=ZERO, dest=R, data=0, hr_data=0, remote=S03, smode=LSL, scount=7} S06 ADD {src1=R, src2=ZERO, dest=S, data=0, hr_data=0, smode=LSL, scount=3} S07 SUB {src1=S, src2=R, dest=R, data=0, hr_data=0, smode=LSR, scount=2} ; Test N2 < 1.75 N1 S08 SUB {src1=REM, src2=R, dest=NONE, data=0, hr_data=0, remote=S02} S09 BR {event=N, cond_addr=S11, next=S13} ; Test 1.75 N-2 > N S10 SUB {src1=R, src2=T dest=NONE, data=0, hr_data=0} S11 BR {event=N, cond_addr=S14, next=S12} ; Not a GAP ; If first gap has not been detected, we are done. ; Otherwise, execute between gaps count S12 ADD {src1=IMM, src2=ZERO, dest=NONE, data=0, hr_data=0} S13 BR {event=Z, cond_addr=CG00, next=S18} ; GAP Detected ; First gap or second gap? S14 ADD {src1=IMM, src2=ZERO, dest=NONE, data=0, hr_data=0} S15 BR {event=Z, cond_addr=S16, next=S19} ; First Gap ; Set flag in S14 to indicate 1st gap has been detected ; And initialize Between Gap Counter S16 MOV32 {type=IMTOREG&REM, reg=NONE, data=1, hr_data=0, remote=S14} S17 MOV32 {type=IMTOREG&REM, reg=NONE, data=0, hr_data=0, remote=S18, next=CG01} ; Between Gaps ; Increment Gap Count (NB: Subtract -1 to increment) S18 SUB {src1=IMM, src2=ONES, dest=IMM, data=0, hr_data=0, next=CG01} ; Second Gap ; Did we detect the correct number of teeth between the first and 2nd gap? S19 SUB {src1=REM, src2=IMM, dest=NONE, data=0, hr_data=NTEETH} S20 BR {event=Z, cond_addr=S21, next=S22} ; Second Gap As Expected - Start Angle Count at end of 1st tooth S21 MOV32 {type=IMTOREG&REM, reg=NONE, remote=L02, data=STEP_FACTOR, hr_data=0, next=L00} ; Second Gap Not As Expected ; Start Sync Again.. S22 MOV32 {type=IMTOREG&REM, reg=NONE, remote=S12, data=0, hr_data=0} S23 MOV32 {type=IMTOREG&REM, reg=NONE, remote=S14, data=0, hr_data=0, next=CG00} ; Close 1st and 2nd Gates CG00 MOV32 {type=IMTOREG&REM, reg=NONE, remote=G00, data=1, hr_data=0} ; Close 2nd Gate Only CG01 MOV32 {type=IMTOREG&REM, reg=NONE, remote=G01, data=1, hr_data=0, next=L00}
EDIT: pasted code in a couple times to get it to look ok. Also note that the code is in transition from a factor of 1.75 to 1/1.75 (0.57)..
Hi Anthony,
With the following settings I got it to work, more or less:
NTEETH .equ 8
STEP_FACTOR .equ 8
GAP_START .equ ((NTEETH - 3) * STEP_FACTOR + 1)
GAP_END .equ ((NTEETH - 1) * STEP_FACTOR - 1)
I changed the event of NAF_BR to rise instead of NAF and
skipped an extra first (NTEETH - 1) * 2 rising edges (+ the first complete rotation, which is always skipped):
It works at different speeds, although I still have to try the slowly adjusting the speed and see if it stays in sync. The disadvantage is the relatively slow start up. I wonder if the starter engine will be able to provide three rotations before the ignition kicks in?
The first rotation was always skipped anyway, but with only NTEETH - 1 rising edges skipped extra, it sometimes worked correctly and sometimes the signal would lag behind and get in sync after around 8 rotations. This would result in misfires, hence the 3 skipped rotations.
I adjusted the stimulus to accelerate 5% per revolution after 10 constant revolutions to give it chance to sync, which resulted in the characteristic lagging we saw before:
Even with 1%, the same behaviour was observed:
Has anyone successfully used the SWAG? Especially for variable speed measurements?
Hi Anthony,
Any updates on this? I do not want to use the ISR to sync the N2HET, because I have other interrupts on the system and do not want to delay those/risk missing a sync. The main reason for using the N2HET was its relative independence. It would be a shame to change that.
Best regards, Tim