Lynxmotion Tech Support

www.lynxmotion.com
It is currently Thu May 23, 2013 4:04 pm

All times are UTC - 6 hours [ DST ]




Post new topic Reply to topic  [ 59 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
PostPosted: Wed Aug 11, 2010 6:02 pm 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Yes, I know I jump around a lot... But I have seen enough comments up on the forums of people wanting to have better control than they can get from the PS2 and don't want to go to the complete job of building the DIY remote and by chance may have an RC Transmitter/receiver laying around. The problem up till now was the amount of overhead to the system that reading in the 6-7 PPM channels was causing.

Why I thought of it today is while looking for something else my receiver fell out of the cupboard. So I did a little hunting around the web and found that it would not be hard to hack the receiver... I tried several searches, but the best one I found was "Arduino PPM". I looked at a few sites and decided it might not be hard. So I removed the receiver from the plastic housing and turned it over and found a shift out register. A quick look at the data-sheet showed that Pin 1 was a clock pin. So I hooked up my logic analyzer with a pin for each of the output PPMs and one on this clock pin. Mine looks like:
Attachment:
File comment: Hitec HFD-08RD receiver
Hitec-laser-6-receiver.jpg
Hitec-laser-6-receiver.jpg [ 29.29 KiB | Viewed 2821 times ]


I then plugged in a power/ground line to connect the receiver up to my BB2 such that the receiver had power and then turned on the transmitter and then did a logic scan so see what I got. Here is a sample output.
Attachment:
File comment: Logic scan of Hitec receiver
Hitec-laser6-logic-scan.jpg
Hitec-laser6-logic-scan.jpg [ 17.53 KiB | Viewed 2821 times ]

As you can see the one clock pin nicely clocks out each of the signals. For the fun of it I will probably try to solder on a test lead to bring this to the BB2 and write some code to receive this data. Let me know if anyone else is interested in this. Note the top line in my trace was for Ch7 and I have a Laser6 so it appears like it is high for the entire time between cycles...


Kurt

P.S. - Many of the examples I saw up on the web were for Futaba receivers.


Top
 Profile  
 
PostPosted: Wed Aug 11, 2010 6:38 pm 
Offline
Robot Guru
User avatar

Joined: Fri May 25, 2007 8:21 pm
Posts: 3868
Location: Central Coast, CA, USA
Hi Kurt,

Yes, it's interesting! In some ways, this problem sounds much like recovering the spark plug firings from a car engine. If you have a "sync" to the #1 plug, then a single line to the cap will give you all of the plug's firings. A/D and software take it from there to split up the individual plugs.

I don't have a Laser 6 anymore (just developed a 'bot for a friend with it), but I have some old 4-channel R/C to play with. If it was really promising for my use, I'd not hesitate to get an up-to-date R/C.

The limited number of channels in the "frame" are probably sufficient to allow you to extract the "#1 plug" timing.

Alan KM6VV

_________________
Visit:
http://groups.yahoo.com/group/SherlineCNC/
http://tech.groups.yahoo.com/group/HexapodRobotIK/


Top
 Profile  
 
PostPosted: Wed Aug 11, 2010 7:05 pm 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Yep it should be easy to resync. If the delta time is > than something like 2500 we know that we just measured the pause between RC frames so the next should be channel 1... Will try soldering in later tonight or tomorrow morning and write up some code. Will start with something simple like test program, than may build a Phoenix V2.x RC version. Will set up an interrupt pin and let it run in background always filling in array of pulse widths. Will disable interrupt when we do serouts to SSC as to not have interrupts screw it up.

Pluses are: Should minimize system overhead. Only one IO pin required.

Should be fun.
Kurt


Top
 Profile  
 
PostPosted: Wed Aug 11, 2010 7:47 pm 
Offline
Robot Guru
User avatar

Joined: Fri May 25, 2007 8:21 pm
Posts: 3868
Location: Central Coast, CA, USA
Only one I/O pin, and only one data stream to process!

What board (ARC / BB2) is this for? Both I hope!

Alan KM6VV

_________________
Visit:
http://groups.yahoo.com/group/SherlineCNC/
http://tech.groups.yahoo.com/group/HexapodRobotIK/


Top
 Profile  
 
PostPosted: Wed Aug 11, 2010 10:03 pm 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Yep, should work well for both boards :) . Will play with in the morning. s

Kurt


Top
 Profile  
 
PostPosted: Thu Aug 12, 2010 10:15 pm 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Quick update, did not get as much done today as I wanted. We spent most of the day taking a drive...

I have soldered in wire to the point I mentioned that has a female plug on it that I then plugged into my BAP28 pin 19 (IRQ2).
I have started a test program, that I cut and pasted the TimerA code from the phoenix 2.x code. I made changes to it to currently increment TMA on clock/128 instead of clock/8192 or about 8us resolution. If I find that resolution not sufficient may convert to clock/32 instead or 2us. I am thinking the 8us may be sufficient as if our servos go from lets say 500-2500us, that is a delta of 2000us/8us gives us 250 values which is similar to what we are processing from the DIY... But will experiment.

I started off writing the interrupt handler in assembly code, but that I would first try things out in basic and then finish the assembly language. So far the test version of the interrupt handler is looking like:
Code:
Handle_IRQ2:
   toggle p4
   ;gosub GetCurrentTime - don't want to enable interrupts yet so do inline
   _lNewPulseTime = lTimerCnt + TCA
   ; see if timer is waiting to process interrupt.
   if IRR1.bit6 then
      _lNewPulseTime = lTimerCnt + 256 + TCA
   endif
      
   ; calculate the pulse width and convert to us and save away the pulse time
   _wPulseWidth = _lNewPulseTime - _lLastPulseTime      ; not scaled yet
#ifdef DEBUG
   if cRaw < 100 then
      awPPMsRaw(cRaw) = _wPulseWidth
      cRaw = cRaw + 1
   endif
#endif
   _wPulseWidth = (_wPulseWidth * (WTIMERTICSPERMSMUL * 1000)) / WTIMERTICSPERMSDIV
   _lLastPulseTIme = _lNewPulseTime;

   ; See if the value appears to be OK.
   if _wPulseWidth > 2500 then
      ; Where were we???
      if _bNextChannel < CNT_PPM_SIGNALS then
         ; We got a long value when we did not expect it...???
         fPPMsValid = 0;
      endif
      _bNextChannel = 0;    // Ok lets assume the next value will be for our first channel
   else
      if _bNextChannel < CNT_PPM_SIGNALS then
         awPPMs(_bNextChannel) = _wPulseWidth
         _bNextChannel = _bNextChannel + 1
         if  _bNextChannel = CNT_PPM_SIGNALS then
            fPPMsValid = 1      ; Let the main line know that we received a complete valid set of values
         endif
      endif
   endif
      
   resume


I have some simple main line code that simply checks to see if any of the values change and if so copy them to another array and print out the array... I am also printing out if I think the data is valid.
I am starting to get valid results...
Code:
1 1392 1552 1448 1576 1104 1920
1 1400 1552 1440 1584 1096 1920
1 1400 1552 1448 1576 1096 1920
1 1400 1552 1440 1576 1104 1912


Will experiment more tomorrow. Will play with different timer values and maybe make an Arc32/Bap40 version. This will be nice as I can user HSEROUT to output the debug information. Or maybe I will make a RC version of an input method for the phoenix...

Kurt

Kurt


Top
 Profile  
 
PostPosted: Fri Aug 13, 2010 10:03 am 
Offline
Lynxmotion Founder
User avatar

Joined: Mon Oct 31, 2005 10:46 am
Posts: 9325
Location: my quiet place
Awesome work! 8)

_________________
Jim Frye, the Robot Guy
http://www.lynxmotion.com
I've always tried to do my best...


Top
 Profile  
 
PostPosted: Sat Sep 25, 2010 3:47 pm 
Offline
Roboteer

Joined: Tue Feb 05, 2008 6:33 pm
Posts: 129
Hey guys,
I just bought the laser 6 over the summer and was trying to figure out how to get the atom 28 to read the ppm signals too. I tried out the code kurte post but i'm getting a lot of errors when compiling. Has this code been debugged yet?

bane


Top
 Profile  
 
PostPosted: Sat Sep 25, 2010 4:38 pm 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Hi,

I have not played with this much lately, been doing other stuff instead (as I do have the DIY remote control with XBees...), but plan to soon. I have most of a Control unit for the phoenix written but not tested yet. I was planning to do it on the Arc32, but may put it on my CHR-3 with the Bap28 instead... Hopefully soon.
Kurt


Top
 Profile  
 
PostPosted: Sun Sep 26, 2010 5:51 pm 
Offline
Roboteer

Joined: Tue Feb 05, 2008 6:33 pm
Posts: 129
Hi Kurt,

Wow, I can't wait to how your DIY rc comes out (perhaps a future product for sale?) After doing some research on getting the atom to read PPM signals i realize it is much more complicated than i expected. I was hopping to use a simple pulsin function and get a number. Just out of curiosity, do you have any sample code that will take a single channel, read it, and set it equal to a variable?

Bane


Top
 Profile  
 
PostPosted: Sun Sep 26, 2010 6:12 pm 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Hi Bane,
I do have a lot of fun with the DIY stuff. I wish Robot Dude would package a lot of this into a kit, but there are a few of us now using it.

You can use pulsin command to read in one channel. If you wish to read in multiple channels, you can issue one for each channel. The order you issue these commands will greatly influence the speed of it... To improve on this earlier I wrote assembly language to read in multiple channels in one RC cycle. There are several threads on this including: viewtopic.php?f=8&t=6079&hilit=pulsein7

Will hopefully soon have a hacked up version of this stuff working. My current experiment for Bap28 only is to use IO pin 12 which also is an Input capture pin for TimerW...

More later
Kurt


Top
 Profile  
 
PostPosted: Sun Sep 26, 2010 7:16 pm 
Offline
Roboteer

Joined: Tue Feb 05, 2008 6:33 pm
Posts: 129
your level of program is out of the charts compared to mine lol. I just wrote some simple code after consulting the atom programming manual in an attempt to figure out whats going on. This code is supposed to read a single channel and display its reading. So far all it displays though are (what appears to be random) numbers between 0 and 17

is this even close to reading a ppm signal?
Code:
rcinput var word
rcch1 con p6

main
   pulsin rcch1,0,rcinput

   serout s_out,i9600,[dec rcinput,13]
   
pause 300

goto main


thnx, bane


Top
 Profile  
 
PostPosted: Mon Sep 27, 2010 8:58 am 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Hi Bane,
Thanks I have had many (more than I would like to admit) years of experience :lol:

I assume from your program that you have at least one of the channels plugged in from your receiver to the BB2/BAP and that one of them is on Pin 6. Preferably one of the channels 1-4 which are to the joysticks.

Also I am not sure, but you may need to have:
Code:
pulsin rcch1, 1, rcinput

That is I think you want to measure it starting at the transition when it goes from low to high. Could be wrong.
Kurt


Top
 Profile  
 
PostPosted: Tue Sep 28, 2010 10:45 pm 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
After the last posts I have made some progress on this. I have been playing with a Bap28 only version of this, that uses the input capture for one of the channels on TimerW. I decided to try this way as I have not tried the input capture and thought it would be fun and it should be reasonably accurate. I started off with a Basic interrupt handler but was having trouble getting reasonable results, so I converted to assembly language. I think I now have the interrupt handler working OK. So I am now trying a setup a simple set of functions for controlling the phoenix. Having it interrupt based, I had to generalize the disable interrupts function I had for the XBEE interrupts such that the serouts to the SSC-32 would work.

I am now playing with how/when to get the inputs. When I disable the inputs I invalidate the data and only after a complete new pass to I say the data is valid. Currently I disable the input through the calls to the ServoDriver and more or less call off to ControlInput before it had a chance to do a complete new pass. I have a couple of options. I could simply wait a certain amount of time for the data to become valid or I could detect if I had new valid data just before the servo driver commit and use it. I will probably go the later route. The data should be very current anyway and it would mean that the input processing should not slow down the code much at all. Can minimize this to only have the code running while in the sleep waiting for the current step to complete. Just in case anyone wishes to see the interrupt handler :lol:
Code:
;------------------------------------------------------------------------------
; HANDLE_TIMERW_IMIED handler - The idea is to capture our current time
;       value when the interrupt happens and then calculate a delta from the
;      previous one.  If > some max we know that we are starting up a new run
;      of timings, else save away in the appropriate index value in our array
;      of timing with 1 per logical channel.
;------------------------------------------------------------------------------
BEGINASMSUB
HANDLE_TIMERW_ASM:
ASM {
   ; First see why we woke up.
   push.l   er0
   push.l   er1                  ; save away the registers we are using
#ifdef DEBUG_LA
;   bset   #4, @PCR5:8            ; make sure it is set for output
;   bnot   #4, @PDR5:8            ; DEBUG - togle P4...
#endif
   bld      #3, @TSRW:8            ; See if GRD match...
   bcc      _RCHTW_CLEANUP:8      ; not ours
   bclr   #3, @TSRW:8            ; clear it out.
   mov.w   @GRD:16, e1            ; Get the new GRD value
   mov.w   @_WGRDPREV:16, r1      ; get the saved value to use
   mov.w   e1, @_WGRDPREV:16      ; Save away the new one
   sub.w   r1, e1               ; subtract the prev from the new to get delta - I think it handles wrap OK...
   bcc      _RCHTW_NGRD:8         ; NO Carry so assume no wrap.
   bld      #7, @TSRW            ; see if it shows a wrap happened
   bcc      _RCHTW_NGRD:8         ; Did not have overflow so fine
   mov.w   #0xffff, e1            ; set high value ...
_RCHTW_NGRD:   
   shlr.w   e1                  ; divide by 2 to get uS
   xor.w   r0,r0               ; zero out r0
   mov.b   @_BNEXTCHANNEL:16, r0l   ; Load which channel we are using into r0l
   cmp.b   #CNT_PPM_SIGNALS+1, r0l ; See if this is the first interrupt ...
   beq      _RCHTW_INITMODE:8         ; we are in the init phase...
   cmp.w   #499,e1               ; see if the value is lower than expected
    bls      _RCHTW_LESS500:8      ; < 500 assume an error again

   cmp.w   #2500, e1            ; see if > 2500
   bls      _RCHTW_LT2500:8         ;
   ; So exceeds what we think should be a valid signal
   cmp.b   #CNT_PPM_SIGNALS-1, r0l   ;
   bhi      _RCHTW_SARTNEWRUN:8   ;
_RCHTW_LESS500:
   mov.b   r0h, @FPPMSVALID:16      ; say we are not valid   r0h should be zero
;   bra      _RCHTW_CLEANUP:8      ; go to cleanup
#ifdef DEBUG_LA
;   bnot   #7, @PDR5:8            ; P7...
#endif
_RCHTW_INITMODE:
   mov.b   #CNT_PPM_SIGNALS, r0h   ; Hack - reuse code below to set channel value...
_RCHTW_SARTNEWRUN:
#ifdef DEBUG_LA
   bnot   #5, @PDR5:8            ; DEBUG - togle P5...
#endif
   mov.b   r0h, @_BNEXTCHANNEL:16   ; next one should be channel 0
   bra      _RCHTW_CLEANUP:8      ; go to cleanup

_RCHTW_LT2500:
   cmp.b   #CNT_PPM_SIGNALS-1, r0l   ; see if we are working on a proper channel
   bhi      _RCHTW_CLEANUP:8   ;
   mov.b   r0l, r1l            ; save the value
   extu   r0                  ;       
   shll.w   r0                  ; *2
   mov.w   e1,@(AWPPMSINPUT, er0)   ; save away the new pulse width into the array
   inc.b   r1l                  ; increment our counter
   mov.b   r1l,@_BNEXTCHANNEL:16   ; save away the updated count
   cmp.b   #CNT_PPM_SIGNALS, r1l   ; see if we got a complete set
   bne      _RCHTW_CLEANUP:8
   mov.b   #1, r0l
   mov.b   r0l, @FPPMSVALID:16      ; let caller know we have a complete set
#ifdef DEBUG_LA
;   bnot   #6, @PDR5:8            ; DEBUG - togle P6...
#endif
_RCHTW_CLEANUP:
   pop.l   er1                  ; restore the registers we used
   pop.l   er0               
   rte                        ; return from the exception.
}
ENDASMSUB

Kurt


Top
 Profile  
 
PostPosted: Wed Sep 29, 2010 11:35 am 
Offline
Robot Guru
User avatar

Joined: Sat Apr 15, 2006 1:42 pm
Posts: 4414
Minor road block... I was testing on my test board which was an ABB, but decided to try on my CHR-3 with BB2. No longer works. Why? BB2 has pull-up resistor on P12 for PS2 controller, so signal always high, Hitec receiver outputs nothing as the clock pulses don't work. Hopefully no big issue. Will move to P10 or P11 and move the SSC-32 communication pins...

Kurt


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 59 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC - 6 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group