PWM/PPM Capture issue with Atom Pro 28

But even if there isn’t enough delay you could benefit by changing the order of the channels you read. For example if they are generated in order, 1,2,3,4 and there is no delay bewteen the pulses you could read them in the following order. 1,3,2,4. This should take alot less time to read as you only have to have one unnecessary cycle instead of 3.

Jim,
I can try it, but this approach may not work well with all receivers (different brands and models may have different sequence) involved in the project, that is why i think hardware solution is better. Im going to make some tests right now anyways, im working on it.

Ive just tested several sequences of PULSIN commands but no significant improvements. The more channels the more delay no matter the order. :angry: :angry:

If the pulses come in at the same time then there is no simple software way to do it with good accuracy. if polling is acceptable then you may be able to code a real tight loop in assembly but I still think this would be hard to balance so all 4 channels had accurate and repeatable results for any combination of inputs.

If you need to do it with hardware I think an important question becomes does the microcontroller used on the BAP actually have 4 capture/compare channels and 4 seperate hardware PWM channels?

There are just two hardware capture peripherals on the Atom PRO. As far as I know, all the DIP packaged PIC controllers and many, if not most, 8 but MCUs only have two hardware captures. I have not done much research into the 16 and 32 bit MCUs yet, so don’t know much about what they provide for capture peripherals. Most of the time, the capture pins are shared with hardware PWM and other peripherals. I believe I have seen some specialized controllers or peripherals with four hardware captures.

8-Dale

Actually on the AtomPro there are 4 hardware capture pins(P9-P12, also called FTIOA-D). The are also capable of compare operations(eg timing external events). FTIOB-D are also the HPWM pins.

The regular Atom only has 2 CCP capable pins(Capture/Compare/PWM).

Acidtech,
Ive been testing this code using the WKP service:

Code:

[code]
ONINTERRUPT WKPINT_0,MyWKPIntHandler0 ;point to where I want to go when an interrupt on WKP0 accurs.
PMR5.bit0 = 1 ;enables pin as WKP interrupt instead of normal I/O
IEGR2.bit0 = 0 ;this is the default so doesn’t have to be in your code. Pin will interrupt on a falling edge.
;Change to 1 to interrupt on a rising edge.
canal0 var word

enable WKPINT_0 ;sets the IENR1 bit to enable the WKP0 interrupt

main

debug "ch1 ",dec canal0 , 13]
goto main

MyWKPIntHandler0 ;On entry the IWPR bit for Wkp0 is automatically cleared.
disable ;with no arguments disable disables the global interrupt enable flag

rctime 0,1,canal0

enable ;re-enable global interrupt flag.

resume ;you must always resume(not return) from an interrupt or you will eventually crash.[/code]

It works erratic, sometimes returns weird readings…What i am doing wrong?

First are you running in debug. I see a debug statement. Debug mode will slow everything down and may cause rctime to not be started before the end of the pulse causing the rctime to get “weird” readings. SInce you are almost certainly running in debug mode(since you wouldn’
t get any feedback if you weren’t) I’d suggest using serout instead and running in normal mode.

Also an example of the data(both wierd and not weird) would be helpful.

Also, you are reading Servo pulses so you want to WKP on the RISING edge. Then rctime till the falling edge to get the pulse width. That may also be why you are getting “weird” readings sometimes.

Also another thing you can do instead of using rctime to read the remainder of the pulse is to setup timerw running at clk/8 speed. Then when the wkp happens clear TCNT and change the wkp int to int on the falling edge. When the second int happens read tcnt to get the time. THis has the advantage of not waiting around for the falling edge of the servo pulse using rctime.

Just to be clear:

  1. Setup TimerW to count at clk/8
  2. Set WKP to int on rising edge
  3. do other stuff.
  4. When WKP int happens, clear TCNT(TimerW timer reg) and set WKP to int on falling edge. Resume
  5. do other stuff.
  6. When WKP int happens, read TCNT and set WKP to int on rising edge.Resume
  7. Do stuff with pulse width read from TCNT. The value will be in .5us increments just like pulsin and rctime.

Note this will only work with one pulse at a time. If you need to get multiple pulses at the same time(eg they all start at the same time) you can’t clear TCNT. You’d need to store the value of TCNT at the rising edge of each pulse and then keep track of any overflows of TCNT and then when the falling edge int happens calculate the difference from the first TCNT to the last TCNT of each pulse.

Hmm, I may add an hpulsin command based on this method.

AcidTech,
Thanks for the kind assistance, im working on the code now. The r/c receiver im using for this test (cheap GWS 8 chs) triggers the int like in the code i posted above seems to output inverted pulses.
I imagined that debug statement was interfering with timings, i will output readings to terminal1 thru com1 (BB is connected to com1).

Thank you Very Much again

You might want to try Chuck’s “Servo Gismo”. As I recall, it is connected to an R/C receiver, and it “decodes” the PWM intended for R/C servos.

You might want to use a PIC chip like this ahead of your other uP, or maybe you can learn from it and incorporate it’s logic into your design.

Alan KM6VV

mcmanis.com/chuck/robotics/p … ervoGizmo/

Are you cennected directly to the servo outputs on the receiver? If it’s outputing inverted pulses I don’t see how it could possible control a servo unless there is something between the servos and ther receiver that re-inverts them back to normal.

Not exactly the above situation but i kept trying different things, i got stucked a little on Acidtech Int solution for capturing pulses so i went back to the pulsein solution to test other things until i fully understand the int approach.

This time I used the bit banged pulsin function to read 3 pins and scale the readings for driving 3 servos attached to pins 10-12 using HPWM function. It works ok when only one HPWM sentence is present, if you add a second the three servos start oscillating, here it is the code:

[code]

canal1 var word
canal2 var word
canal3 var word

control_loop

PULSIN P4,0,canal1
PULSIN P5,0,canal2
PULSIN P6,0,canal3

serout S_OUT,i9600,"ch1 ", dec canal1, " ", "ch2 ", dec canal2, " ", "ch3 ", dec canal3,13]

canal1 = (canal1-900)*12+16000
canal2 = (canal2-900)*12+16000
canal3 = (canal3-900)*12+16000

HPWM 10,320000,canal1 ; if only one HPWM sentence it works ok
HPWM 11,320000,canal2 ; adding this new HPWM line generate jitters in all 3 servos
HPWM 12,320000,canal3 ; same as above

goto control_loop[/code]

Alan,
Thanks for the interesting link! but i need the serial channel free for telemetry tasks

ps. I also discovered that HSERVO interferes in some way with PULSEIN reading, is there any way to stop the HSERVO service while executing PULSEIN and then reactivate it?

Working on the code to capture pulses using WKP.
I did it on a single pin just to ensure it is working…it works…BUT: HSERVO function doesnt work anymore…
Here it is the code…

[code];Interrupt init
ONINTERRUPT WKPINT_0,handle_intp0

PMR5.bit0 = 1 ;enables pin as WKP interrupt instead of normal I/O
IEGR2.bit0 = 0 ;0 = Pin will interrupt on a falling edge, 1 to interrupt on a rising edge.

; TimerW regs
TCRW.bit5 = 1 ;TIMERW counts on clk/8
TCRW.bit4 = 1 ;TIMERW counts on clk/8
TCRW.bit7 = 0 ;TCNT free running counter
TMRW.bit7 = 1 ;TCNT free running counter

ENABLE WKPINT_0
ENABLEHSERVO

;Variable declaration
pulse_ch1 var long
pass0 var byte

pass0 = 0

control_loop

HSERVO [P10\pulse_ch1*10]

;HPWM 10,320000,pulse_ch110
serout S_OUT,i2400,"ch1 ", dec pulse_ch1, 13]
;pulsout 10, pulse_ch1
2
;servo P10, (pulse_ch1-1500)*2, 2
goto control_loop

handle_intp0
If pass0 = 0 then
TCNT = 0
IEGR2.bit0 = 0 ;interrupt on a falling edge
pass0 = 1
elseif pass0 = 1
pulse_ch1 = TCNT/2 ; divide by 2 to obtain us
IEGR2.bit0 = 1 ;interrupt on a rising edge
pass0 = 0
endif
Resume[/code]

As you can see i also tried other ways to drive servos but none seems to work, seems to be a timing problem caused by the capture code.
ACIDTECH come to help!!! :stuck_out_tongue: :stuck_out_tongue:

The 8.0.1.0 HSERVO had a bug. It was causing pulses on unrelated pins. The reason for this is probably related to the problem you are having. Iv’e fixed that and gave the customer the updated files to confirm. If he confirms I’ll updat ethe 8.0.1.0 release to 8.0.1.1.

The problem you are see is caused because HPWM does not wait until the end of a pulzse before it will change the period and duty you specify. This will cause glitching in the pulse signal. The next release of AtomPro basic will have a new version of HPWM that has a new argument to tell it to wait until the end of the current pulse before changing the period and duty. This will alow smooth pulse width changes. The new syntax is HPWM pin,period,duty{,wait}. “Wait” is zero to not wait or non-sero to wait. 8.0.1.1 will have this optional argument when it is released.

Acidtech,
That HSERVO bug was probably causing glitches when i tested PULSIN to capture pulses from the rc receiver, i have detected that. Good to know it is a known bug soon to be solved! (may I have 8.0.1.1 release NOW? :smiley: )

Is it possible that setting different TCRW and TMRW values for TimerW (like i did in the above code to activate the 16bit TCNT clock) is deactivating the HSERVO function, because that is the problem im having now.

Thanks a lot for your help Acidtech

Edit:
Just read the above post about HPWM, you posted it while i was typing this one.

As soon as I hear back from the other customer I’ll be making the new 8.0.1.1 release available(assuming I’ve fixed the problem). As for the other, do not mess with TimerW registers if you are using HSERVO. It uses TimerW so you will screw up HSERVO. HPWM and HSERVO are mutually exclusive since both want to use TimerW.

I think the test version may have fixed the problem. It fixed the problem in my first test program. I had a problem with a second test program, but found problem was in the test program.

There was a problem That I can not link my full blown BRAT code, but assuming that the updated lib fixes that, I think it may be good to go!

Kurt

Acidtech,
So if I use TimerW for pulse counting i wont be able to use HSERVO and HPWM, any other solution for interrupt capturing pulses (other than TimerW) and still be able to use HSERVO and/or HPWM?
Thank You

To read a pulse you could use the WKP pins and one of the other timers. Setup timerA int to keep track of time. Then when WKP trips on the front edge of your pulse save the current time. Then set WKP to trip on the falling edge and resume. When WKP trips on the falling edge take the difference from the first reading from the second. There’s your pulse width in whatever time base you setup TimerA to run at. Siz WKP pins means upto six different pulse signals could be read.