Futaba T7C Phoenix 1.3/2.0 code

You may want to add a little verification check after the call to the pulses to make sure everything looks legit. Something like: are all 7 values between the values of 700-2300 (Choose the range depending on the actual range of values for your receiver ± fudge). If not Ignore the values. Also we may still need some minor editing of which channels are processed by each pass…

Other options to maybe try:
Use Basic to read in the RC inputs. If Zenta’s logic analyzer output was correct awhile ago. you could try:

pulsin 0, 0, val0
pulsin 2,0, ...

In the order 0,2,4,5,1,3,6
This will take on the order of 2-3 full RC passes to get the data. The hack I did earlier will take 2 passes…

Or write a new version of the RC input that handles overlapping IOs. Earlier I wrote a version in basic, that would probably need to be converted to assembly language to work fully. Also I would probably change the beginning of the function that waits for all of the IOs to be low before starting as this could waste most of a complete cycle. Would probably need to grab the start IO mask and ignore the transition to low for all IOs that were high at the start…
In case you are interested this was the outline of code I had awhile ago:

[code]awPulsesIn var word(7)
bPulseTimeout var byte

;=============================================================================
; this is just the outline of a function. Should convert to assembly language.
;==============================================================================
wLoopCntr var word ; how many times we went through the loop
bMask var byte ; Our mask of the bits we are still interested in
bIOVal var byte ; The IO port value (masked)
bIOValPrev var byte ; The previous IO port value (masked)
bIODif var byte ; what changed - What IO bits were turned off

abIOStates var byte(15) ; what state we were at
awIOTimes var word(15) ; Value of the loop counter.
cSaveStates var byte ; index into our saved array.

;=============================================================================
; this is just the outline of a function. Should convert to assembly language.
;==============================================================================

; like 2 but setup to use timerW instead of loop ctr
MPulseinV3:
; Make sure all 7 IOs are set to input.
PMR5 = 0 ; all IO lines are general IO
PCR5 = 0 ; All are input (may want to leave bit 7 alone…

bMask = 0x7f		; what we are still looking for...

; first wait until all of the IOs are low 
while (PDR5 & bMask )
    ; 
wend 

; setup timerW
TCRW = 0x30	; setup for clock/8
TMRW = 0x80	; make sure it is running
TCNT = 0	;

; initialize for our main loop
cSaveStates = 0		; no saved states
bIOValPrev = 0x0	; no bits were on.

; main loop - to be used as actual values all code paths through this loop would need
; to have a consistent timings...
while bMask and (cSaveStates < 15)
	bIOVal = (PDR5 & bMask )				; get the masked value
	if bIOVal <> bIOValPrev then
		abIOStates(cSaveStates) = bIOVal	; save away the new value
		awIOTimes(cSaveStates) = TCNT		; save away the time from timerW
		cSaveStates = cSaveStates + 1		; increment how many states we have saved
		
		; Turn Off any bits in our mask that were on that are now off...
		bMask = bMask & ((!bIOValPrev) | bIOVal)
		bIOValPrev = bIOVal					; remember the previous value
	endif
	wLoopCntr = wLoopCntr + 1				; increment our loop counter
wend		

; Now to post process the data
for wLoopCntr = 1 to cSaveStates-1
	; Assumes that not two will end at the same time... Could handle this as well
	bIOVal = abIOStates(wLoopCntr-1) & !(abIOStates(wLoopCntr))  ; I think should give us a mask of the bits that turned off
	
	if bIOVal then
		
		; reuse bMask
		bMask = wLoopCntr-1
		while (bMask > 0) and (abIOStates(bMask) & bIOVal)	; loop back to find out when this bit was turned on.
			bMask = bMask - 1
		wend
		if !(abIOStates(bMask) & bIOVal) then
			bMask = bMask + 1
		endif
			
		; figure out which bit...
		bIOValPrev = 1
		while ((bIOVal & 0x1) = 0)
			bIOValPrev = bIOValPrev + 1
			bIOVal = bIOVal >> 1
		wend
		awPulsesIn(bIOValPrev) = (awIOTimes(wLoopCntr) - awIOTimes(bMask)) / 2 ; End - start /2 as clock is /8 
	endif
next	

; now print out masks and timers to see what is happening...
for wLoopCntr = 0 to cSaveStates-1
	serout s_out, i9600, [hex abIOStates(wLoopCntr), ":", dec awIOTimes(wLoopCntr), " "]
	if (wLoopCntr & 0x7) = 0x7 then
		serout s_out, i9600, [13]
	endif
next
serout s_out, i9600, [13]

return [/code]
Note: some of the stuff toward the end of this is debug stuff to see how it was working…

Kurt

Wow I just got lost!

So from your assembly code earlier you wrote prior to it outputting all zero’s your assembly worked good, I saw 7 values all changed where they should have when they should have so I don’t feel that is the problem. I think if its possible, tell me if I’m wrong here, but for some reason when its placed within the 1.3 code I have it seems to have problems “I’m not sure why”

So the latest code you posted above I’m not sure what this is?? Is it a new method to read pulsin data?

I guess I’m kinda confused as to what you would like me to try now?? Am I correct in coming to the conclusion you want me to try using Pulsin again with that 2 line code bit above, as well as try the lower code and having it spit out serial data to the com port as the bot is running the code.

Thanks,
–Aaron

Since I had received a logic analyzer in the mail a while back I decided to use it on my receiver just for fun, and it appears that the results that Zenta posted a while back show that channels 6 and 7 overlap with channel 1 and 2. In this photo they show that the channel order should be captured 6, 7, 1, 2, 3, 4, 5

Attached is the photo.
http://img855.imageshack.us/img855/7107/t7clogic.jpg
The one Zenta shared is below.
http://img263.imageshack.us/img263/6681/filewp.jpg

Kurt could you advise me on what I should try? I was kinda lost on your last post,
Thanks a bunch!

From your picture I ca not tell for sure if there is overlap or not. In Zentas case you could easily see that Input 6 and 7 overlap. Also 6 overlapped with 1. I am not seeing this in your trace, so not sure what to tell you.

What I was saying in the previous post. If you are having to take 2 full passes through the RC assembly code to get them all in, you may not being saving enough time to warrant the use of the assembly code. That is it will take 2+ 20ms RC cycles to receive your input. Given that if you use the pulsin command in the right order it will also take 2+ RC loops. The code will probably be slightly slower, but only by a portion of an RC cycle… That is you could simply try:

pulsin 6, 0, awPulsin(6)
pulsin 0, 0, awPulsin(0)
pulsin 2, 0, awPulsin(2)
pulsin 4, 0, awPulsin(4)
pulsin 5, 0, awPulsin(5)
pulsin 1, 0, awPulsin(1)
pulsin 3, 0, awPulsin(3)

With this code the first pulsin, may take up to a full RC cycle (if you just missed the up transition for pin 6), but after that as we skip every other pulse, the basic should be able to keep up, and we should complete the inputs at about the same time.

The other stuff in the previous post was showing some basic code that is the approach I was thinking of taking as to be able to read all of the input in one pass, even if they may overlap each other. If I needed it I would then write an assembly language version of it, but I am not currently doing anything with the RC remote as all of my robots now work with XBee…

Kurt

Well my logic sniffer isn’t anything special although I’m very curious why it didn’t pick up the overlap like in zenta’s.
Would it be possible for you to adjust your assembly to read the channels in that order via 1 pass?

So your method posted previously looks like it just reads the channels and stores them in an array vs individual variables, different then how I was doing it just running them in order.

Perhaps I would be better running pulsin commands with the 2.0 code vs the 1.3 code? due to 1.3 requiring much much more cpu time to run.

Thanks for your help so far… Let me know what you can do.

–Aaron

The assembly language code does not care about what order the pulses come in. What it does not handle is when two of the pulses overlap. It waits for a signal to go high and then measures how long it takes to go low. It then removes that pin from the list it is waiting for and when there are no more pins to wait for it returns.

The issue is if while it is waiting for a signal to go low another one goes high, it does not see that transition and only starts measuring the width of the new pulse when the first pulse goes low…

Kurt

So when I ran your latest assembly code on its own to check the outputs of all 7 channels they appeared to be within the ranges pulsin commands were so with that said, what are the chances that somehow using your assembly code and xan/zenta’s 1.3 phoenix code is messing with variables within your asm?

Maybe I should put a serout command within the MAIN loop in the 1.3 code and see if the results are different?

Is it possible that your assembly routines or just the 1.3 code alone take up a lot of cpu power to run?

On a side note it seems like the more and more we dive into this it seems like I should be leaning towards the 2.0 code and ditch the 1.3 stuff since its really dated…
Thoughts on this Kurt?

Maybe I can get away with using pulsin and 2.0 code and not have any cpu limitations… OR HEY Maybe they should make a 32mhz atom pro? !! The Microchip facility is about 10 minutes away from work maybe I should go knock on their door? hahah.
–Aaron

RC Input is SLOW regardless of version 1.3 or 2.x… That is if you look at this quick and dirty image I hacked up:

If the code started where I put the red S, if the single pass code worked properly it would complete about where the 1 is marked. If using the hacked up 2 pass version, it will take probably where the 2 is marked but maybe worse… If you use the pulsin command, it will take to about where the P is marked, which is not much worse and potentially in some cases may turn out better than the 2 pass. Again each of those RC passes is 20ms in time, so if it takes lets say 3 RC pulse streams to get all of them, that is about 60ms or about 96000 clocks to complete… That is just the nature of it. This is one of the reasons why I moved away from RC. Or Zenta added a second processor that read in the inputs and gave a quick way for the main processor to read in the inputs.

Yes the other parts of the 2.0 code is faster than the 1.x code as for example the calculations were converted from floating point to fixed point which is significantly faster. I am not sure what else to tell you here.

Kurt

Well I understand that RC input is quite slow. I found that out when I fiddled with RC when Zenta provided me with his source code and experimented with individual leg control.
It’s worth trying the 2.0 code, last time I tried using it I was unable to get it working “User error on my part” so I’ll have to go that route.

So really… I’ll admit I’m pretty screwed without knowing your assembly and my lack of helping other then going back and forth trying different edits with your time.

It seems to me I’m at a point where I make my own controller with the xbee or ditch the T7C or buy another bb2 and AtomPro and put the read code on it. Or perhaps develop some small compact device similar to that size of a RC receiver and have it accept all 7 inputs and spit out serial without the use of an additional bulky atom Pro and bb2 combo. maybe a pic? maybe some other small dev board, I’m positive if I have a chance to learn C++ I think it would be a cool little device, although the market for that kinda stuff seems very limited… anyone want to chime in?

I will need to touch bases with Xan and Zenta to see what they recommend for a Lipo battery setup as my 5400NiMih battery pack I made 2 years ago is worthless unfortunately! I guess its been sitting too long or something.

As for the logic output seeing yours and Zenta’s and then seeing mine, I’m really curious as to why mine shows no overlap and yours does… “Which one is accurate ???” I guess like what if you wrote your assembly to read the inputs in 1 pass, but set it up so it reads channel 7, 6, 1, 2, 3, 4, 5 in that order? and I’ll run another test and check to see if the values are all accurate? This would determine if my logic sniffer is inaccurate or vise versa…

Since you now have al logic analyzer you can easily play around with seeing timings. That is if you have an unused IO pin (example P16), hook up your 8th input to your analyzer to it and just before you start the group of pulsin commands (or calls to assembly language or…), do HIGH p16 and right after it completes, do a low P16. Now simply measure look at the pulses in your analyzer and see how long it took…

I think I can do this, I have a bunch of test clips i got on the cheeps.

So I’m very very tempted to buy one of thesehttp://arduino.cc/en/uploads/Main/ArduinoNanoTop.jpg and learn C++ Its either that or maybe a cheep PIC and have the pic do all the pwm ->serial conversion or some other format.
If I used the pic I would probably try and use some easy basic pic language “somehow” not sure yet.

Actually I need to figure out what kind of Lipo battery to use in the Phoenix.

Alright! I’m a bit of a slacker but here’s what I have done.

I have decided to build a PWM --> PPM converter from this website jreise.de/PPM/R617FS.html Translate this into English via chrome
I emailed the person who helped me quite a bit! I programmed it with my BusPirate, it’s really cool the bus pirate will program these things in circuit and the pins used for programming aren’t used for this schematic. I wanted this thing really tiny, I was considering not using a pcb at all and heat shrinking it all although I had some headers and I bought a bunch of pre made 6 inch wires with the female ends on each.

This is what I made

The whole thing cost me 3 bucks to build, the chip alone I bought at sparkfun, it’s programmed I have not tested it, just waiting for my DSOQuad O-scope from china land… Although I should use my open source logic sniffer to see if its putting out the correct signals. it’s kinda weird the guys code only reads channels 1-3-5, 6, 7 and it figures out what 2 and 4 are by the time in between channels 1 and 3 and 3 and 5… pretty ingenious if you ask me.

SO! once that mess is figured out, I went ahead and took Zenta’s advice and picked up a Turnigy Ubec along with the discussion of how great Lipo’s are and picked up a 2 cell 5000Mah pack
All these electronic components are going to be a bitch to get fitted on the Phoenix I managed to get the Ubec in a great spot. Just need to mount the reciever and connect that pcb to it and figure out where it goes onto the spider without it looking horrible…

Attached are some photos!




Kurt!

I’ll probably hit you up soon for that code to read PPM and hopefully get this thing rocking and rolling.

Very interesting! :smiley:

Great work putting it all together.
The photo resistor with red color filter between for detecting error (no RF connection) was pretty creative! :laughing:
Did you need to do any corrections for calibrating the photo resistor sensitivity?

Or is the photo resistor part really needed, if I assume correct you are not using it?

Zenta,

I did not use the photo resistor option, I really didn’t like how the circuit board looked flipped over like that, however I like the plug and play option. I had spoken to Jorg via email and he had mentioned that I can simply leave that pin disconnected.

It should be interesting getting this thing back together… eventually I know a lot less wires will be going to the botboard, I would like to see anyone who does RC stuff use this PPM method instead seems to be cleaner looking, its just unfortunate that the receiver I have and I believe you have the same one does not have ppm output apparently it only outputs 5 of the 7 channels via ppm. Either way in a couple of days hopefully I’ll have this together and grab kurts ppm reading code and run some tests.

–Aaron

Whoo Hoo!

As my previous post I have programmed an Atiny 2313 Atmel chip with the Bus Pirate. You can program Pic’s with the bus pirate in circuit! and with only 4 wires.
The Bus pirate is also a low speed oscilloscope.

The first time I programmed the chip I was getting zero output, I reflashed the device last night and it is outputting PPM.
I’m at the point where I could probably have Kurt share his PPM code with me.

Also would you like a screenshot of the timings? from a real logic probe to make sure its compatible with the code you wrote for one of your other projects…