Shop OBEX P1 Docs P2 Docs Learn Events
FullDuplexSerial and Servo32 Incompatible? — Parallax Forums

FullDuplexSerial and Servo32 Incompatible?

sharpiesharpie Posts: 150
edited 2006-07-25 06:14 in Propeller 1
So, I'm still a newbie to this and not entirely sure of the dynamics here... But I cannot seem to get a servo to move at the same time I am accepting data.· Everything I do it seems either one or the other...· It's got to be me..· Right now I just have a serial stream coming in at 57600, and trying to move a servo with a loop at the same time...
Here's a simple test I tried (one of about a hundred combinations..)
con
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000                 
  Out = %1
var
  long stack1[noparse][[/noparse]50]
  long stack2[noparse][[/noparse]50]
obj
  tx  : "FullDuplexSerial"
  txt : "tv_terminal"
  svo : "Servo32"
pub Main
  txt.start(12)
  tx.start(0, 1, 0, 57_600)
  svo.Set(3,1500)
  svo.start
  cognew(recvData,@stack1)
  cognew(moveServo,@stack2)  
pub recvData
  repeat
    txt.out(tx.rx)
    txt.str(string(13,10))
          
pub moveServo | temp
  repeat                                              
    repeat temp from 1000 to 2000
      waitcnt (cnt+125_000)
      svo.Set(3,temp)
    repeat temp from 2000 to 1000
      waitcnt (cnt+125_000)
      svo.Set(3,temp)


Tried it with and without tv_terminal in there too...· Anybody able to provide some insight into this for me?

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2006-07-21 13:56
    One obvious bit is that the wait time in the servo loop is short (1.5ms) compared to the response time of the servos (20ms). The cycle from one end of the servo range to the other is on the order of 1.5 seconds and you should see movement. The servo routines are designed to put out repeated pulses every 20ms or so of the last set width and normally servos expect at least a few pulses of the same width before moving slightly to another.

    I would move the "svo.start" to before the first "svo.Set(". I'm not sure it really matters in this case, but that's what's assumed. No pulses are produced on a pin until the first "svo.Set(".

    Your serial stream is pretty fast (200us/char roughly). You're asking a lot of the tv_terminal object to act on 3 characters (xx,13,10) at that rate. It's based on a graphics object and I don't think it can run that fast. You could try "tv_text" instead which is character cell based and faster.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2006-07-21 16:07
    sharpie,

    I ran your code, and scoped pin A3 and the servo pulse is doing what it is supposed to. I tend to agree with Mike in that your serial stream is pretty fast,
    but I'm not sure that the graphics object should be effected by this.

    As far as the order of "svo.start" vs "svo.Set"... it really does not matter. The original thinking was that you needed to preset the value before you initiated
    the "svo.start"... logically it makes no difference, since the pin will not output anything anyway unless/until "svo.set" has been called.



    I don't have a way at the moment to test 57.6Kbaud, but substituting the line that reads...

    txt.out(tx.rx)
    
    



    ...with...

    txt.out(65)
    
    



    ...I see the letter "A" (ASCII 65) displayed on the TV screen at the same time I see the proper servo pulsewidth on pin A3.
    This indicates to me that the "tv_terminal" and "Servo32" objects are working properly. I would try to lower the baud rate
    and see if your results are different.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2006-07-21 16:21
    Sharpie,

    You're initializing tx and svo in one cog, but using them in different cogs. If the tx.start and svo.start record their settings in VARs, these settings won't be reachable when svo.SET and tx.rx are called from the other cogs. It will be as if they were never started. I would put the calls to start in the cogs that use the objects' routines.

    -Phil
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2006-07-21 16:46
    Sharpie,

    Phil is right.....


    [b]con[/b]
      [b]_clkmode[/b] = [b]xtal[/b]1 + [b]pll[/b]16x
      [b]_xinfreq[/b] = 5_000_000                
      Out = %1
    [b]var[/b]
      [b]long[/b] stack1[noparse][[/noparse]50]
      [b]long[/b] stack2[noparse][[/noparse]50]
    [b]obj[/b]
      tx  : "FullDuplexSerial"
      txt : "tv_terminal"
      svo : "Servo32"
    [b]pub[/b] Main
      [b]cognew[/b](recvData,@stack1)
      [b]cognew[/b](moveServo,@stack2)
       
    [b]pub[/b] recvData
        txt.start(12)
        tx.start(0, 1, 0, 57_600)
        [b]repeat[/b]
          txt.out(tx.rx)
          txt.[b]str[/b]([b]string[/b](13,10))
             
    [b]pub[/b] moveServo | temp
        svo.Set(3,1500)
        svo.start
        [b]repeat[/b]                                             
          [b]repeat[/b] temp [b]from[/b] 1000 to 2000
            [b]waitcnt[/b] ([b]cnt[/b]+125_000)
            svo.Set(3,temp)
          [b]repeat[/b] temp [b]from[/b] 2000 to 1000
            [b]waitcnt[/b] ([b]cnt[/b]+125_000)
            svo.Set(3,temp)
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • Mike GreenMike Green Posts: 23,101
    edited 2006-07-21 17:17
    Beau,
    I don't believe this is necessarily true. The VARS reside in the object, not the cog. It doesn't matter which cog is running the SPIN code that references the VARS except for the usual caveats that two cogs shouldn't try to use the same information without some planning for the interaction. In this case, the initialization of the other objects was over with before the new cogs were started and none of the running cogs were using the same object at the same time.
    The way you did it is cleaner and clearer though.
    Mike
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2006-07-21 17:56
    Mike, you're right. My bad.

    As long as an object's routines are called using the same object declaration as the call to start, the same instance of the object's VARs gets used, regardless of whether the calls were made from different cogs. Apparently, it's only when an object is declared more than once, either within the same object or across object boundaries, that separate instances of the VARs get created. (At least I think that's right.)

    Thanks much for the insight!
    -Phil
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2006-07-21 18:54
    It's still a learning process for all of us.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • sharpiesharpie Posts: 150
    edited 2006-07-23 00:29
    I more than appreciate all the input on this.. I have some leads to try now. I wasn't as concerned with the text output to the monitor(just had that in there for debugging), and have tried it with and without... And it will ultimately be removed when I get this all working.. Also, I am running the servo with a 5v regulated 2amp supply..

    In the code example I provided above, the servo runs fine, the serial data coming in has more errors than not. If I comment out the servo stuff, the serial works great. I have tried sending a serial stream with a value that is passed to the servo for position, I have not got this to work. Ultimately, what I would like to do is have two propellers talking to each other... One telling the other one what to do so to speak.. One that has sensors, user interactions, etc.. and processes that data and tells the other propeller to move the servos connected to it in corresponance to the data it's sending.. So there is a constant stream of information flowing between the two as the second prop is responding with acks, and feeback etc... I'd also like to send these commands in sentences, but I haven't mastered the fdxserial stuff and handling variables, strings, etc. well enough yet to get that done...
  • sharpiesharpie Posts: 150
    edited 2006-07-23 02:00
    So, I have tried a slightly new approach...
    With the controlling prop, I am sending a simple "+" to increase the servo position, and "-" to decrease...· Using the following code, I attempt to move the servo based on the received information...· the controlling prop sends a constant stream of +'s and -'s at 57.6k.· I get limited success with this, very sporadic movement.· When I output to the tv so I can see what it's getting...· I can see the serial object is stumbling just as it had with the previous attempt.· I'd reaaaallllly rather not drop the baud rate, and I have actually tried as low as 38.4k...·
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000                 
      
    var
      long sp
      
    obj
      tx  : "FullDuplexSerial"
      svo : "Servo32"
      
    pub Main
      tx.start(0, 1, 0, 57_600)
      svo.Set(3,1500)
      svo.start
      sp := 1500
      repeat
        if tx.rx == "+"
          sp := sp + 10
        if tx.rx == "-"
          sp := sp - 10      
        waitcnt (cnt+1_000_000)
        if sp > 2000
          sp := 2000
        if sp < 1000
          sp := 1000
        svo.set(3, sp)
    
    
    
    


    I would like to have more than just servo data going back and forth..· This doesn't seem that it should be that challenging for the propeller..
    I've had great success with another project using a different micro accepting serial data through a mini webserver over ethernet..· But I don't want to use that configuration on this project, the propeller is so much better.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2006-07-23 03:38
    Sharpie,

    Don't forget, every time you invoke tx.rx it gets another character from the input. That may be the reason you're missing inputs. Better to do something like this:

    [b]repeat[/b]
      ch := tx.rx
      [b]if[/b] ch == "+"
        sp := sp + 10 <# 2000
      [b]elseif[/b] ch == "-"
        sp := sp - 10 #> 1000
      ...
    
    
    


    This will get one character for each loop interation, and compare that character to "+" and "-". Note that I've also included your limiter in the increment and decrement using <# and #>

    Also, you've got a 12.5ms delay in there (assuming an 80MHz clock). That's enough for 72 characters at 57,600 baud, if they're coming full bore. Without some sort of handshaking, they'll end up in a black hole.

    -Phil
  • sharpiesharpie Posts: 150
    edited 2006-07-23 03:45
    Thanks Phil! I didn't take note that each tx.rx accepts a character.. I put the extra delay in there just for safety, with only two possibilities for characters I didn't figure it too important if I missed a few since they are coming in constantly... Thanks for the extra info about the limiter as well.. I'm working on understanding that stuff as much as I can.. I will be sure to take your code advice.
    The results I get from what I had done above was waaay more successful than what I'd tried before.. However, I am still getting serious delays in servo movement.. Although, at least I can see it move in the direction I expected. I am currently adding rts/cts lines between the two processors as well, in a hope to get some handshaking going.
  • sharpiesharpie Posts: 150
    edited 2006-07-23 08:43
    Ok, to eliminate any serial quirks I may have introduced I wrote this bit of code as a test... Using two identical setups (Propeller Demo Boards), and a serial connection between the two...... I run this on each and it is FAST, with no visible errors.

    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      rts = 3
      cts = 2
      high = 1
      low = 0
      Out = %1
      In = %0
      rx = 0
      tx = 1
    var
      long stack1[noparse][[/noparse]50]
      long stack2[noparse][[/noparse]50]
      long ch
      byte rcv
    obj
      ser : "FullDuplexSerial"
      txt : "tv_text"
    pub main
      dira[noparse][[/noparse]cts] := In
      dira[noparse][[/noparse]rts] := Out
      txt.start(12)
      ser.start(rx, tx, 0, 57_600)
      txt.str(string("Begin"))
      cognew(transmit,@stack1)
      cognew(receive,@stack2) 
    pub transmit
      ch := 32
      repeat
        if ina[noparse][[/noparse]cts] == low
          ser.tx(ch++)
          if ch > 126
            ch := 32
            ser.str(string(13,10))
        
    pub receive
      repeat
        rcv := ser.rx
        txt.out(rcv)
        
    



    This is without the introduction of any servo object or anything.. Looks to me as if it runs perfectly..·My next step is to add a loop where the servo goes back and forth to see if my hunch is right and the serial object will start stumbling.· If this happens, can someone give me some insight as to why it will?·



    Post Edited (sharpie) : 7/23/2006 8:47:53 AM GMT
  • sharpiesharpie Posts: 150
    edited 2006-07-23 09:02
    Ok, and I change the code on one end (with the servo) to the following and I get very bad results with the serial data... Very sporadic.. Not many errors, just LONG pauses and quick spirts of data flow....· The servo moves fluidly, with no interruption.· Anyone have an idea as to why???
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
      rts = 3
      cts = 2
      high = 1
      low = 0
      Out = %1
      In = %0
      rx = 0
      tx = 1
    var
      long stack1[noparse][[/noparse]50]
      long stack2[noparse][[/noparse]50]
      long stack3[noparse][[/noparse]50]
      long srv
      long ch
      byte rcv
    obj
      ser : "FullDuplexSerial"
      txt : "tv_text"
      svo : "servo"
    pub main
      dira[noparse][[/noparse]cts] := In
      dira[noparse][[/noparse]rts] := Out
      txt.start(12)
      ser.start(rx, tx, 0, 57_600)
      svo.start
      svo.Set(0, 4, 1500)
      txt.str(string("Begin"))
      cognew(transmit,@stack1)
      cognew(receive,@stack2) 
      cognew(moveServo,@stack3)
    pub transmit
      ch := 32
      repeat
        if ina[noparse][[/noparse]cts] == low
          ser.tx(ch++)
          if ch > 126
            ch := 32
            ser.str(string(13,10))
        
    pub receive
      repeat
    '    outa[noparse][[/noparse]rts] := high
        rcv := ser.rx
        txt.out(rcv)
    '    outa[noparse][[/noparse]rts] := low
    pub moveServo
      srv := 1000
      repeat
        repeat 1000
          waitcnt (cnt+500_000)
          srv := srv + 1
          svo.set(0, 4, srv)
        repeat 1000
          waitcnt (cnt+500_000)
          srv := srv - 1
          svo.set(0, 4, srv)
    
    
  • IAI-CaptainIAI-Captain Posts: 33
    edited 2006-07-23 22:13
    Hi, Sharpie
    Just one thought! Being more of a Hardware, rather than software, Guy.
    Also I noticed that you have covered the software end of it. knowing that the problem only seams to occur when the servo is hooked up, It might not be software related.
    It has been My experience that when ever you get weird results while interfacing Inductive Loads with digital electronics that you might want to consider Noise coming in though your power supply or directly though / into your pulse out pin. Ether of these can be receiving inductive surges. Even If there is no noise coming in through ether of these two methods.· there can still be Electro magnetic interference. coming out of the servo going right into the Propeller IC at radio wave lengths / frequencies.
    Maybe your timing is so high as to be affected by low strength stray EMI.
    You might want to add some Low uf Caps / Shielding and/or ferrite beads to your Servo control and power Leads.·
    ·cool.gif
    Hope It helps,
    IAI Captain



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    IAI (Indigenous Alien Intelligence),
    The New View on Machine Intelligence.
    Because There is nothing Artificial about it!
  • sharpiesharpie Posts: 150
    edited 2006-07-24 00:07
    IAI-Captain, originally I wasn't convinced it was a power/interference issue... But after reading your post, thinking about it and deciding to try running the code with the servo actions that cause the interruption and taking note of the problem.... then disconnecting the servo and running the exact same code I see no interruption in serial transfer..... I don't have a scope on hand right now to look at the pwm signal, but I am guessing you are probably right and I need to take a closer look at least. Any ballpark suggestions on cap values?

    Thanks for the input!!
  • sharpiesharpie Posts: 150
    edited 2006-07-24 00:26
    Embarassing as it is, that was the problem. Case closed. Hate that...
    Better grounding, couple of caps.. Well, two good things came of it... It forced me to go ahead with the serial handshaking, which turned out to help ALOT, and I got it all to work together.
    Like you said Beau, it is still a learning process for all of us....
    Thanks to everyone for the helpful words.
  • IAI-CaptainIAI-Captain Posts: 33
    edited 2006-07-24 08:16
    Hay Sharpie, Don’t be Embarrassed it happens to all of us at one time or another. devil.gif
    I'm just glad to know that I helped solve the problem.
    ·
    ·Like I said, I'm a hardware guy. When it comes to software,·you are·a lot further along than myself, So I keep on going and I will Keep on learning from each new post.
    ·
    (I know that this may not be the place)
    · But It does seem at least on the surface, that a bunch of Prop Issue could be solved if everyone would first realize that the Propeller is hardware first And therefore must follow the rules of Digital I/O.
    ·· ··(I.E.·A lot of the threads are Questions about Interfacing Mem.·All mem follow the same Hardware I/O Rules(non I2C & SPI). there Are (A0-A12 (Address Lines and most of the time D0-D7 (Data Lines) then there are the control lines). If one were to just read any of the spec sheets that are out there on Mem,(Ram, SRam, SDRam, Rom, EPRom, EEProm, ect.. It's all the same I/O Connections). The Hard part is not selecting the right port to use on the Prop. who cares it's all the same, but the data manipulation is a different Question all together. what to do once you get the hardware hooked up correctly?) (The Software)!
    ·
    · So, I guess my point was, look, If you think in terms of hardware I/O first and then build the software around the hardware project chances are you will always have less problems with any given project because at least you’ve lessened the chance of it being hardware by an order of magnitude.
    ·
    Sorry to let it all out on you Sharpie.
    ·
    Hope that this helps.scool.gif
    ·
    Cap size: 0.01uf or smaller if you are·getting high freq noise. 10uf - 100uf cap if low freq noise on the Power supply lines. (give a try to a range of values.)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    IAI (Indigenous Alien Intelligence),
    The New View on Machine Intelligence.
    Because There is nothing Artificial about it!
  • sharpiesharpie Posts: 150
    edited 2006-07-24 08:45
    I agree, me for example.. I was in a hurry to get this part going, and didn't pay close enough attention to the hardware details. Funny too, you'd think I'd have learned.. My reluctance to beleive it was a power/interface issue and focus that it had to be a coding problem even though I'd experienced a similar issue back in like '99 building my first quadraped using rc servos.. Had some problems on that thing that it worked great at home, but every time it was around flourescent lights it FREAKED out.. Hehe..

    Anyway, thanks again..
  • IAI-CaptainIAI-Captain Posts: 33
    edited 2006-07-25 06:14
    Sharpie,
    U R Welcome.
    cool.gif
    Just glad 2 help

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    IAI (Indigenous Alien Intelligence),
    The New View on Machine Intelligence.
    Because There is nothing Artificial about it!
Sign In or Register to comment.