Shop OBEX P1 Docs P2 Docs Learn Events
Help understanding XBee Tutorial Propeller code — Parallax Forums

Help understanding XBee Tutorial Propeller code

FalconFalcon Posts: 191
edited 2012-12-05 18:29 in Propeller 1
I'm a total noob to the Propeller. I'm studying the Propeller code in the XBee Tutorial before trying to modify it for my own project.

I understand that the "cognew(acceptData,@Stack)" command starts a new cog to run the acceptData method, and I know that "Send Control" is a Method within the Bot_Tilt_Controller OBJECT.

Question: What does the "SendControl" Command on the line after the cognew(acceptData,@Stack) for?

falcon
PUB Start

  ' Configure XBee
  XB.start(XB_Rx, XB_Tx, 0, XB_Baud)   ' Initialize comms for XBee
  XB.AT_Init                           ' Fast AT updates
  XB.AT_ConfigVal(string("ATMY"), MY_Addr)   
  XB.AT_ConfigVal(string("ATDL"), DL_Addr)
  
  offset := 90 * (clkfreq / 200)  ' offset for sensor data conversion
  scale  := clkfreq / 800         ' scale for sensor data conversion
  accel.start(Xout_pin,Yout_pin)  ' start accelerometer

  cognew(acceptData,@Stack)       ' start cog to accept incoming data
     SendControl
     
Pub SendControl
  repeat
    if ina[PB] == 1                    ' if button pressed
          XB.str(string("pppppp"))    ' send handful of p's for pan map
          XB.delay(500)
    else
        ' Read and calulate -90 to 90 degree for forward
        Forward := (accel.x*90-offset)/scale * -1
        
        ' Read and calulate -90 to 90 degree for turn    
        Turn := (accel.y*90-offset)/scale

        ' scale and mix channels for drive, 1500 = stopped
        Left_Dr := 1500 + Forward * 3 + Turn * 3
        Right_Dr := 1500 - Forward * 3 + Turn * 3

        ' send drive data(d) to bot
        XB.tx("d")
        XB.DEC(right_Dr)
        XB.tx(13)
        XB.DEC(left_Dr)
        XB.tx(13)
        
    XB.delay(100)
«1

Comments

  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-02 20:04
    Without the "SendControl" call after the cognew statement, cog zero would stop (assuming this is the top object). Unlike PBasic the flow of the program wouldn't continue to the method "SendControl" without being explicitly told to do so. When the end of a method is reached the flow of the program returns to the calling method. Since there isn't a method higher up than Start (assuming it's the top object) the cog would stop running (which isn't a good way to stop a cog). The call to "SendControl" keeps the cog alive. Since the method "SendControl" doesn't ever end, the flow of the program never returns to the "Start" method and all is well.

    The "Start" method does the things the program only needs to do once; the method "SendControl" is the main loop of the program.

    Occasionally when testing a program it can be useful to keep a cog alive after some code has been executed. In this case a simple "repeat" will keep the cog alive.
  • FalconFalcon Posts: 191
    edited 2012-11-03 06:59
    Thank you Duane Degn. You hit the nail on the head.

    All of my experience is with PBasic and it's ingrained into my programming logic to make everything flow in a loop, and that Subroutines are just part of a continuing loop. This is where I'm having a problem wrapping my head around Spin. I can pick apart an individual Method and understand how it works but I still haven't grasped the overall flow logic. I do have the PE kit and am re-reading parts of it every day.

    Example: I'm working on an XBee/Propeller-based robot remote control. It will read three joysticks with an ADC0838 (because it's faster than 6 RCTime commands), read switch positions with a 74HC165 and send this data via XBee. I have all of these working on a breadboard individually. (Later on I plan to receive and display telemetry and switch position data from the robot using LEDs and a uOLED display.) I'm struggling with the "flow" of the TX code. My PBasic sense says do each in a big loop, but I know the Propeller will allow me to launch each (XBee, ADC0838 and 74HC165) into a separate cog so changes can be gathered and transmitted as soon as they occur. Would this be the best approach?

    falcon
  • Mike GreenMike Green Posts: 23,101
    edited 2012-11-03 07:22
    Yes, you're better off with separate cogs managing the 74HC165, ADC0838, and the overall processing, but not for the reason you think. You will be using something like FullDuplexSerial to talk to the xBee and that already uses it's own cog internally to provide a high speed buffered serial channel that can keep the xBee busy, so you don't need another cog for the xBee.

    1) With the Spin code for the 74HC165 just occupied with reading in the switch settings into a variable, the code is simple. You start it and forget it.

    2) Similarly with the Spin code for the ADC0838. Its only job is to cycle through the 8 channels of the ADC0838 and read each channel in turn into a variable. It's simple code, straightforward to write and debug, and interacts with nothing else.

    3) Your main routine continually takes the most recent values in the variables and packages them up into a packet that it gives to the FullDuplexSerial transmit routine (and, in the future, to the LEDs and uOLED module via another copy of FullDuplexSerial).

    4) There's a nice 4 channel serial I/O routine in the Object Exchange that uses a single cog for up to 4 serial channels and has a higher aggregate throughput than FDS ... also does flow control which you'll need at high speeds. You'd use one channel for the xBee and a 2nd for the uOLED.

    5) If you want to work with assembly, #1 and #2 could each be done in assembly. Again, they're each straightforward and interact with nothing else (other than the memory locations where they deposit their results).
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-03 10:25
    Falcon wrote: »
    All of my experience is with PBasic and it's ingrained into my programming logic to make everything flow in a loop, and that Subroutines are just part of a continuing loop. This is where I'm having a problem wrapping my head around Spin. I can pick apart an individual Method and understand how it works but I still haven't grasped the overall flow logic.

    Yes, you're not the first person I've seen try to write code for the Propeller in a similar fashion as they had with the Basic Stamp. Fortunately for myself, I had a lot of experience with C. The methods of Spin are very similar to the functions in C (IMO).
    Falcon wrote: »
    Example: I'm working on an XBee/Propeller-based robot remote control. It will read three joysticks with an ADC0838 (because it's faster than 6 RCTime commands), read switch positions with a 74HC165 and send this data via XBee. I have all of these working on a breadboard individually. (Later on I plan to receive and display telemetry and switch position data from the robot using LEDs and a uOLED display.) I'm struggling with the "flow" of the TX code. My PBasic sense says do each in a big loop, but I know the Propeller will allow me to launch each (XBee, ADC0838 and 74HC165) into a separate cog so changes can be gathered and transmitted as soon as they occur. Would this be the best approach?

    falcon

    I've got a similar project I've been working on for a while. I'm using one of Rayman's 4.3" touchscreens with a PlayStation 2 controller as a robot remote. The PS2 controller is nice since it takes care of digitizing joystick movements and button presses for you (not that I think it's a better method than the way you're doing it).

    I recently needed some 74HC165 chips for one of my projects. I'm sure there are lots of good objects for reading a 74HC165, but I wanted to make sure I understood how the chip worked so I translated the StampWorks example into Spin. Here's the thread (is it a thread if there's only one post?) with my version. If you haven't used a '165 before, my Propeller version of the StampWorks' program might be helpful in seeing how the '165 works (as Mike said, the code is simple).

    Have you seen Paul K's XBee remote? It's a thing of beauty.

    I think Prop to Prop communication can be very challenging. You need to decide what kind of protocol you're using. Are you using control characters to indicate beginnings and endings of messages or are you stating the length of the message as part of the message heading?(rhetorical, you don't have to answer) If you use control characters then you need to stick with ASCII characters for the data. IMO, if you're using ASCII characters it's easier to use ASCII hex since the numbers take fewer digits and you can have each data field always be the same width with each transmission. And if you use acknowledgements and error checking things get even more complicated. I don't want to scare you off but don't be surprised when you find making a remote isn't as easy as originally planned.

    One thing I really like about using a transceiver as a remote is not only are you giving the robot commands, but you can also receive data back from the robot. Only a few high end RC transmitters are starting to use telemetry and then you're limited to the parameters that the RC unit supports. By using a XBee or other transceiver (Nordic nRF24L01+) you can have any parameter you want sent back to your remote.

    Which OLED display are you using? I've had a lot of bad luck with OLEDs. I've killed at least two (probably more but I'm repressing the memories of blue smoke). I really like how they look and that they don't need a backlight. I'd like to find one that's reasonably durable (or maybe I just need to be more careful).

    As Mike says, a four port serial object will be very useful. I think the best version is Tracy Allen's FullDuplexSerial4portPlus_0v3. It watches for framing errors, has adjustable rx and tx buffers and fixes the flow control bugs in Tim Moore's original code.

    It's possible to have multiple cogs using the same serial object but you need to be very careful when you do. I think it's better to have all the serial communication take place from one cog and have the other cogs update variables and set flags to let the communication cog know when there's new data to send.

    BTW, if you or anyone else is interested in using a PS2 controller with a Prop, I have an improved (IMO) object for reading a PS2 controller (another single post thread). It's the only PS2 (Propeller) object I know of that reads the PS2's analog buttons (12 of them).
  • FalconFalcon Posts: 191
    edited 2012-11-03 11:44
    Duane Degn wrote: »
    I recently needed some 74HC165 chips for one of my projects. I'm sure there are lots of good objects for reading a 74HC165, but I wanted to make sure I understood how the chip worked so I translated the StampWorks example into Spin. Here's the thread (is it a thread if there's only one post?) with my version. If you haven't used a '165 before, my Propeller version of the StampWorks' program might be helpful in seeing how the '165 works (as Mike said, the code is simple).
    Actually the Stampworks code is what I have always based my BS2 code on so for the sake of familiarity I'll take a good look at your code.
    Duane Degn wrote: »
    Have you seen Paul K's XBee remote? It's a thing of beauty.
    Yeah...I've drooled over that one a few times. A lot of work in that design.
    Duane Degn wrote: »
    I think Prop to Prop communication can be very challenging. You need to decide what kind of protocol you're using. Are you using control characters to indicate beginnings and endings of messages or are you stating the length of the message as part of the message heading?(rhetorical, you don't have to answer) If you use control characters then you need to stick with ASCII characters for the data. IMO, if you're using ASCII characters it's easier to use ASCII hex since the numbers take fewer digits and you can have each data field always be the same width with each transmission. And if you use acknowledgements and error checking things get even more complicated. I don't want to scare you off but don't be surprised when you find making a remote isn't as easy as originally planned.
    I struggling with this now. I'm not sure which is the best way to ensure the RX knows exactly what each incoming variable is for. Based on the XBee Tutorial, the ASCII character "start-of-string identifier or delimiter" seems to be a stable option. And I've used that in all of my BS2 code.
    Duane Degn wrote: »
    One thing I really like about using a transceiver as a remote is not only are you giving the robot commands, but you can also receive data back from the robot. Only a few high end RC transmitters are starting to use telemetry and then you're limited to the parameters that the RC unit supports. By using a XBee or other transceiver (Nordic nRF24L01+) you can have any parameter you want sent back to your remote.
    I actually have a FrSKY TX/RX set-up on my Futaba 9C right now but I need more than 8 or 9 channels, and I like the telemetry but I agree that the limitations are a problem. The info that I want to return is nothing like what you'd need from an RC plane.
    Duane Degn wrote: »
    Which OLED display are you using? I've had a lot of bad luck with OLEDs. I've killed at least two (probably more but I'm repressing the memories of blue smoke). I really like how they look and that they don't need a backlight. I'd like to find one that's reasonably durable (or maybe I just need to be more careful).
    I've been eyeing one from 4D systems in Australia, and a Nokia that I saw an Object for, but that one from Rayman looks pretty good and should have good code examples since he's a frequent forum contributor.
    Duane Degn wrote: »
    *
    BTW, if you or anyone else is interested in using a PS2 controller with a Prop, I have an improved (IMO) object for reading a PS2 controller (another single post thread). It's the only PS2 (Propeller) object I know of that reads the PS2's analog buttons (12 of them).

    I'll take a look at that too. I've used a PS2 controller using some BS2 code from a N&V article.

    I appreciate you taking the time to help me along. I really want to learn the Propeller but my learning curve is pretty steep.

    falcon
  • FalconFalcon Posts: 191
    edited 2012-11-05 17:57
    Some Progress.
    I did get an XBee transmitting the three joysticks' scaled ADC readings to another XBee and then to the PST.

    I then modified the code to have the transmitted joystick data drive servos. I have just one connected for testing. I'm getting a few servo jitters but no controlled movements. Any ideas where I might be going wrong? I borrowed heavily from the XBee Tutorial code but I'm not sure I meshed it together correctly with the code I had working before the servo code was added.

    Transmitter Code
    CON 
      _clkmode = xtal1 + pll16x 
      _xinfreq = 5_000_000 
    
      US_005 = 80_000_000 / 1_000_000 * 5                           ' 5us
        
      XB_Rx     = 5    ' XBee DOUT 
      XB_Tx     = 6    ' XBee DIN 
      XB_Baud   = 9600 
      CR        = 13   ' Carriage Return value       
    
    con
    
      #0, CLS, HOME, #8, BKSP, TAB, LF, CLREOL, CLRDN           ' PST formmatting control
    
    
    var
    
       long stack2[50]
       word analog[6]                                                                        
    OBJ 
       ADC        : "jm_adc0838_ez"
       XB         : "FullDuplexSerial"
    
        
    Pub  Start 
    
            XB.start(XB_Rx, XB_Tx, 0, XB_Baud)                           ' Initialize comms for XBee
            XB.tx(CLS)
            ADC.init(0, 1, 2)                                            ' setup ADC
                 
            'waitcnt(clkfreq + cnt)
             
              repeat
                  XB.tx("A")
                  analog[1] := adc.read(0)
                  analog[1] := ADC.scale(analog[1], 750, 2250)
                  XB.dec(analog[1])
             
                  analog[2] := adc.read(1)
                  analog[2] := ADC.scale(analog[2], 750, 2250)
                  XB.dec(analog[2])
               
             
                  analog[3] := adc.read(2)
                  analog[3] := ADC.scale(analog[3], 750, 2250)
                  XB.dec(analog[3])
              
             
                  analog[4] := adc.read(3)
                  analog[4] := ADC.scale(analog[4], 750, 2250)
                  XB.dec(analog[4])
             
              
                  analog[5] := adc.read(4)
                  analog[5] := ADC.scale(analog[5], 750, 2250)
                  XB.dec(analog[5])
             
             
                  analog[6] := adc.read(5)
                  analog[6] := ADC.scale(analog[6], 750, 2250)
                  XB.dec(analog[6])
             
                  waitcnt(clkfreq / 10 + cnt)  
    


    Receiver Code
    CON 
      _clkmode = xtal1 + pll16x 
      _xinfreq = 5_000_000 
      ' Set pins and Baud rate for XBee comms   
      XB_Rx     = 0    ' XBee DOUT 
      XB_Tx     = 1    ' XBee DIN 
      XB_Baud   = 9600 
      ' Set pins and baud rate for PC comms  
      PC_Rx     = 31   
      PC_Tx     = 30 
      PC_Baud   = 9600
      ServoCh1 = 2                ' Servo to pin 2
      ServoCh2 = 3                ' Servo to pin 3
      ServoCh3 = 4                ' Servo to pin 4
      ServoCh4 = 5                ' Servo to pin 2
      ServoCh5 = 6                ' Servo to pin 3
      ServoCh6 = 7                ' Servo to pin 4 
    
    con
    
      #0, CLS, HOME, #8, BKSP, TAB, LF, CLREOL, CLRDN, CR           ' PST formmatting control
    
          
    Var 
      long stack[50]                                                   ' stack space for second cog 
      long stack2[50]
      word analog[8]                                                     
    OBJ 
     
      XB    : "XBee_Object"
      SERVO : "Servo32v7.spin" 
    Pub Start
      
      XB.start(XB_Rx, XB_Tx, 0, XB_Baud)                ' Initialize comms for XBee   
    
    
    
      cognew(SERVOControl,@stack2)                   ' Start cog for Servo positioning
      SERVO.Start
    
    
    PUB ServoControl  | DataIn
    
        SERVO.Start                                            ' Start servo handler
        
        repeat
           DataIn := XB.Rx      
           If DataIn == "A"                
                 DataIn := XB.RxDecTime(500)           'receive data
                 Analog[1] := DataIn                          'save to variable
                 Analog[1]    := XB.dec(analog[1])       ' get joystick data
                 SERVO.Set(ServoCh1, Analog[1])     ' drive servos based on data
    
                 DataIn := XB.RxDecTime(500)
                 Analog[2] := DataIn                     
                 Analog[2]    := XB.dec(analog[2])    
                 SERVO.Set(ServoCh2, Analog[2]) 
    
                 DataIn := XB.RxDecTime(500)
                 Analog[3] := DataIn                       
                 Analog[3]    := XB.dec(analog[3])    
                 SERVO.Set(ServoCh3, Analog[3]) 
    
                 DataIn := XB.RxDecTime(500)
                 Analog[4] := DataIn
                 Analog[4]    := XB.dec(analog[4])   
                 SERVO.Set(ServoCh4, Analog[4]) 
    
                 DataIn := XB.RxDecTime(500)
                 Analog[5] := DataIn
                 Analog[5]    := XB.dec(analog[5])   
                 SERVO.Set(ServoCh5, Analog[5]) 
    
                 DataIn := XB.RxDecTime(500)
                 Analog[6] := DataIn
                 Analog[6]    := XB.dec(analog[6])  
                 SERVO.Set(ServoCh6, Analog[6]) 
    
    
        
    
    
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-05 19:08
    I don't understand this line (and others like it) in your receiver code:
    Analog[1]    := XB.dec(analog[1])       ' get joystick data
    

    Based on the "XBee_Object" I have, I think you just set "analog[1]" to zero. I think your program has a better chance of working if you remove the line (and others like it).

    It would be helpful if you either attached an archive of your project or at least link to non-library objects you're using. I must have an old version of XBee_Object since it doesn't have the method "RxDecTime".

    IMO, I think your code would be easier to read if you were consistent with capitalization (or lack of capitalization) of variable names.
  • FalconFalcon Posts: 191
    edited 2012-11-07 15:52
    Duane Degn,
    I'm not sure what you meant by this reference to "an archive".
    Duane Degn wrote: »

    It would be helpful if you either attached an archive

    I re-wrote the code on both TX and RX to use a single variable: Analog on the TX and DataIn on the RX. See attached filesjm_adc0838_ez.spinRemote RX_11_07_2012.spinRemote TX_11_07_2012.spinServo32v7.spinXBee_Object.spin

    I was scaling the joystick data on the TX side but thought maybe sending the word-sized variable across the XBee was a problem so I moved the scaling function to the RX side. The TX now sends just the 0-255 byte representing the joystick positions.

    The RxDecTime command was part of the XBee Tutorial code I borrowed. I didn't fully understand it's use but I thought that it had to be there. I've removed it and did not see any negative effects.

    I tried to minimize and clean-up the code on both ends but added the PC.tx function to see the data on the PST.

    As you can see, my TX approach is to send a Delimiter (“A”) followed by each Byte of data as they are read by the ADC0838. On the RX side I am using the Delimiter to “align” the incoming data. I then scale it, send it to the Servo Method in it’s own cog, and send it to the PST to monitor the incoming data. Do you think this is a "workable" approach, or is there a more efficient way to go about this.

    I see the following on the PST:

    1038
    1044
    1061
    1038
    1044
    1085

    All six lines vary from +/- ~6 when joystick 1 is moved. That might be solved with some .01uF filter caps on the joysticks. I have one servo attached to P2. It jitters in response to joystick 1 movements but holds its position when I try to manually move it so it must be getting the pulse chain to keep it positioned..
    It looks like the servo is following the scaled joystick data but the data is not moving through the 750-2250 range I expected. Do you see anything in my code that would prevent the full 0-255 byte range to be transmitted? Or scaled?

    Thank you,

    falcon
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-07 18:15
    Falcon,

    I've looked at your code and see several problems.

    One of your big problems is your sending a single byte that's not the larger number scaled down to a byte but rather you're just sending the least significant byte digit (character) of the ADC value (and reading it in incorrectly).
    Edit: I see now that the ADC doesn't need to be scalled down since it's only 8-bits.

    First get rid of most byte variables. Only use them when your using ASCII characters which you wont be using many of (at least directly, the serial object will take care of these for you).

    So with analog a long in your TX code, add a carriage return to this portion of code:
    Analog := adc.read(0)                     'Read ADC                                 
                  XB.dec(Analog)                            'Transmit
                  [B]XB.CR
    [/B]
    

    Now when the XBee object converts the value of "Analog" to ASCII characters you can use the XBee object's rxDec method to convert the ASCII characters back to a variable.

    In your RX code also change "DataIn" to a long and use the following code:
        repeat                                                                                                                      
           DataIn := XB.Rx      
           If DataIn == "A"                                 'Delimiter
                 [B]DataIn := XB.rxDec                            [/B]'receive data
                 ' we'll drive servos based on data later
                 PC.dec(DataIn)
                 PC.tx(CR)
    
    

    By an "archive" I mean using the Prop Tool's archive feature. You need to compile (F9, F10 or F11) the project before you can archive it. Under File\Archive "name of object"\Project... This will add all the files in the project to a single zip file. I don't have "jm_adc0838_ez" so I don't know what the range of possible return values are. With an archive, I would have had this object.

    I doubt you'll need the ADC objet in your RX object. I'll try to find some code to help with converting joystick values to servo values. It basically a linear equation with the ADC value as "x" and the servo value the "y" in "y = mx + b". I usually have some sort of "dead zone" near the center of the joystick where small changes are ignored since many joysticks don't always return to the exact same center position.

    Edit: I see that the ADC your using is an 8-bit chip so you don't really need to use longs for "Analog" or "DataIn" (I still think it's a good idea).
  • FalconFalcon Posts: 191
    edited 2012-11-09 16:33
    That certainly made a difference. The 0-255 range joystick data is displayed and updated. I added a short delay after each ADC channel is read but I'm not sure if they are too long. The data is correct but jittery.

    I sure do miss all of the BS2 DEBUG formatting commands. It was way easier to get data displayed the way you want. I'm sure SPIN has even more formatting options but I've just not discovered them yet. That being said, the results of this code is always justified to the left whether its a 1-, 2- or 3-digit number. Is there a way to justify right?

    So, about those servos? I will actually use channels 1 & 2 to control a Sabertooth 2x25 motor controller that I have. That unit has several modes but the simple serial may be my choice. The first channel expects a 0-127 byte with 63 as the center, and 128 - 255 controls channel 2 with a 192 center. Channels 3 & 4, and 5 & 6 will control typical servos in pan/tilt mechanisms.

    falcon


    Remote RX_11_09_2012 - Archive [Date 2012.11.09 Time 18.04].zipRemote TX_11_09_2012 - Archive [Date 2012.11.09 Time 18.03].zip
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-09 18:17
    Falcon wrote: »
    I sure do miss all of the BS2 DEBUG formatting commands. It was way easier to get data displayed the way you want. I'm sure SPIN has even more formatting options but I've just not discovered them yet. That being said, the results of this code is always justified to the left whether its a 1-, 2- or 3-digit number. Is there a way to justify right?

    "Parallax Serial Terminal.spin" lists the control characters for formatting text sent to "Parallax Serial Terminal.exe". These control characters should work with other serial objects as long as you use "PST.exe" as the PC's terminal window.

    Here's the list of control characters (from "PST.spin"):
    CON
    ''
    ''     Parallax Serial Terminal
    ''    Control Character Constants
    ''─────────────────────────────────────
      CS = 16  ''CS: Clear Screen      
      CE = 11  ''CE: Clear to End of line     
      CB = 12  ''CB: Clear lines Below 
      HM =  1  ''HM: HoMe cursor       
      PC =  2  ''PC: Position Cursor in x,y          
      PX = 14  ''PX: Position cursor in X         
      PY = 15  ''PY: Position cursor in Y         
      NL = 13  ''NL: New Line        
      LF = 10  ''LF: Line Feed       
      ML =  3  ''ML: Move cursor Left          
      MR =  4  ''MR: Move cursor Right         
      MU =  5  ''MU: Move cursor Up          
      MD =  6  ''MD: Move cursor Down
      TB =  9  ''TB: TaB          
      BS =  8  ''BS: BackSpace          
               
      BP =  7  ''BP: BeeP speaker          
     
    

    The only way I know of to right justify is to move the starting position of the text based on its length. You could repeatedly divide a value by 10 to determine how many spaces to add before a number to make it right justified. There might be some text formatting objects available but I don't know where to find them (if they exist). There are other ways of determining the length of a number such as converting it to a string with the "numbers" object and then using "strsize" to find its size.
    Falcon wrote: »
    So, about those servos? I will actually use channels 1 & 2 to control a Sabertooth 2x25 motor controller that I have. That unit has several modes but the simple serial may be my choice. The first channel expects a 0-127 byte with 63 as the center, and 128 - 255 controls channel 2 with a 192 center. Channels 3 & 4, and 5 & 6 will control typical servos in pan/tilt mechanisms.

    While you could certainly communicate with the Sabertooth serially, I think it would probably be easier to just use pulses like the servos since you're already using the servo object.
  • FalconFalcon Posts: 191
    edited 2012-11-10 17:39
    I’ve made some more progress. The joystick data is being read, transmitted and displayed on the PST. I even have a servo working. I added a few lines to convert channels 1 & 2 to the 0-127 and 128 – 255 data expected by the Sabertooth 2x25. If that doesn’t work I will revert to the servo format.

    I’m now working on the 74HC165 code and using the 74HC165_120929e Object. I changed it to reflect the pins I’m using and commented out a lot of the PST commands because I didn’t need it to be displayed from the TX Object. I launch a new cog to read the 74HC165 under the top Method, then added a PUB Switch_Read Method . I added “XB.dec(xInputs)” to the end of the Start Method to transmit the 74HC165 data after the last ADC channel. I’m not sure if I should do that or use a different Delimiter and send the 74HC165 data separately.

    Problem: The joystick data is only displayed (and servo only reacts) if the “Switch_Read” command after the cognew statement in the TX code is commented out. I do get a "0" on the PST after the last ADC channel. Am I launching the 74HC165_120929e Object’s Method correctly?

    Question: What actually returns the data in the xInputs variable to the TX Object?

    Question: Would I be better off copying the applicable 74HC165_120929e code into my TX Object rather than make a call to it?


    Remote RX_11_10_2012 - Archive [Date 2012.11.10 Time 19.29].zip

    Remote TX_11_10_2012 - Archive [Date 2012.11.10 Time 19.27].zip

    falcon
  • FalconFalcon Posts: 191
    edited 2012-11-12 16:29
    More progress and a couple questions

    The joystick function is working 100%. Lots of reading and trail & error. I'll need to address "dead zones" at some point but the code is now functional.

    On the TX end, I have the 74HC165 Shift Register reading 8 pushbuttons and displaying the results correctly on the TX-end Prop Demo board P16-P23 LEDs. I'm having trouble getting that data sent over the XBees for display on the RX-end Prop Demo board.

    Questions:

    In the TX-end Object, I have one Method to read the joysticks via the ADC, and a separate Method to read the 74HC165. How do I get the results of the 74HC165 sent over the XBee?

    Since I have it as a Global variable, shouldn't it automatically be available to the Method that includes the XBee code?

    Do I need to (or is there even a way to) be sure the 74HC165 data is available when the XBee is ready to send it?

    I use a Delimiter to ensure the RX knows when the joystick/ADC data is being sent. Should I use a different Delimiter to signal the 74HC165?

    I appreciate any and all comments and responses.

    falcon

    Remote RX_11_12_2012 - Archive [Date 2012.11.12 Time 18.01].zip

    Remote TX_11_12_2012 - Archive [Date 2012.11.12 Time 18.01].zip
  • RforbesRforbes Posts: 281
    edited 2012-11-12 17:54
    Falcon,

    Here is a code snippet I use for receiving data. It checks for the delimiter, and repeats until it has a valid delimiter at the right spot, the right time.
    {{
      If XBIn[0] := "!" we have valid data incoming, so go ahead and accept it.
      If XBIn[0] is anything other than "!" we have a problem of some sort.
            -XBIn[0] is -1??  No data was received (timed out) so make the rest of the array 0's
            -XBIn[0] anything other than -1 or "!"? Not synchronized so make the rest of the array 0's
    
    }}
    
      xb.rxflush
      Repeat until XBIn[0]== "!"                            'Repeat until we get our start delimiter.
        
        XBIn[0] := XB.RxTime(TimeOut)                       'Wait for a byte with a timeout value.
    
        If XBIn[0] =="!"                                    'Did we get our delimiter?
    
          Bcnt:=1                                               'Set our counter to 1
          Repeat DataCnt-1
             DataIn[Bcnt]:= XBIn[Bcnt]:= XB.RxDecTime(500)      'Get our 1st chunk of data with a timeout 
             Bcnt++                                             'Increment our counter and repeat DataCnt# of times
        
        Elseif XBIn[0]== -1                                 'If we got nothing at all:
    
          Bcnt:=1                                               'Set our counter to 1
          Repeat DataCnt-1
            DataIn[Bcnt]:=XBIn[Bcnt]:= 0                        'Write 0's to all of our chuncks of data
            Bcnt++                                              
                                                                
          xb.rxflush
          pst.rxflush
          pst.NewLine
          pst.Str(String("No Data Received: Disabling Automatic Outputs...  "))
    
        Else                                                'If we got any data other than a "!" or -1
    
          Bcnt:=1                                               'Set our counter to 1
          Repeat DataCnt-1                                      
            DataIn[Bcnt]:=XBIn[Bcnt]:= 0                        'Write 0's to all of our chuncks of data
            Bcnt++
          
          xb.rxflush
          pst.rxflush
          pst.NewLine
          pst.Str(String("Base unit not synchronized...  "))
    

    I think any time you're trying to receive values from a data source via an Xbee (whether it's a shift register, a method, object, etc...) you should have a mechanism that fulfills the function of a start delimiter. This could be an actual delimiter like you're using, or a definitive "dead band" time that has to be present before transmitting/receiving, etc. I'm sure there are numerous ways a person could use to ensure the right data is transmitted/received at the right time, but it's always a good idea to use a start delimiter

    Which Xbee's are you using? Certain Xbee's cannot use the "AT_Init" method without modifying it in the Xbee_Object. Some models have a minimum time of 200 instead of 100ms to enter AT mode.

    And one other thing- if you need your comms to be a little more fail-safe, try this when you change any type of AT configuration setting:
     repeat while NewAddress<> Addy                         'Repeat until the NewAddress matches the required Addy
       xb.rxflush
       xb.AT_ConfigVal(string("ATDT "),Addy)                 'Set DT (destination address) 
    

    It just ensures your attempt to change the value "takes." I'm sure there are better ways to do this, but this one is pretty simple and helps.

    Oyeah- and... I'm a noob at this stuff too. So if you have questions or see something wrong, be sure to hear out the more seasoned vet's around here! :cool:
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-13 10:01
    Falcon wrote: »
    Questions:

    In the TX-end Object, I have one Method to read the joysticks via the ADC, and a separate Method to read the 74HC165. How do I get the results of the 74HC165 sent over the XBee?

    Since I have it as a Global variable, shouldn't it automatically be available to the Method that includes the XBee code?

    Do I need to (or is there even a way to) be sure the 74HC165 data is available when the XBee is ready to send it?

    I use a Delimiter to ensure the RX knows when the joystick/ADC data is being sent. Should I use a different Delimiter to signal the 74HC165?

    Yes, global variables are available to all methods within the object (spin file).

    When new 74HC165 data is available it could set a flag so the method in charge of sending data over the XBee knows there's something to send. The sending method could then clear the flag.

    As for delimiter and what not, that's a tough one. I still struggle with trying to find a good communication protocol.

    For now I use a header that includes a start of message character, then a character to indicate what kind of message is being sent followed by the actual data in ASCII characters (as you are doing by using the "dec" method). I tend to use ASCII hex since it's easier to have the values all the same length and I don't need delimiters between data values.

    Here are some notes from one of my Prop to Prop com projects:
      '' Communication protocol.  Board to board.
      '' Hard wired boards:
      '' _StartOfHeader _StartOfText (destination board letter*1) (origination board letter)(_Enquire, _Acknowledgment or _Command) 
      '' [type of E, A or C] [parameters] _CarriageReturn
      ''
      '' Wireless boards:
      '' _StartOfHeader _StartOfText (board letter*2)(origination board letter) (transmission count*3) (_Enquire, _Acknowledgment or _Command) 
      '' [type of E, A or C] [parameters] _CarriageReturn
      ''
      '' *1 Is this needed?  All wired com will go directly to one board.  Receiving board should be told the destination so it
      ''    knows if it needs to act on the communcation or just pass it on.  Probably leave in.
      '' *2 The transceiver may need to be configured to transmit to different boards.
      '' *3 Transmission count (use txCount) will increment by one each transmission so receiving board will know if data is repeated.
      ''    An ackowledgment will include the original count as a parameter.  (Use RxCountOld and RxCountNew)
     
    

    Since I want my remote to work on more than one robot, I include a destination identifier and origination identifier. If you use start and end of message characters, you're limted to sending ASCII characters since you want to make sure an end of message character isn't part of the data. This can easily double the about a data you need to send. If you use a protocol like the Dynamixel's AX-12a servos, you include the size of the transmission as part of the header so you don't have to worry if there's a control character in the data. There are several Dynamixel objects availble for the Propeller. If/when transmission speed becomes an issue (and you're more comfortable programming the Prop) you might want to take a look at them.
  • FalconFalcon Posts: 191
    edited 2012-11-13 16:06
    Rforbes wrote: »

    Which Xbee's are you using? Certain Xbee's cannot use the "AT_Init" method without modifying it in the Xbee_Object. Some models have a minimum time of 200 instead of 100ms to enter AT mode.
    I'm using the 1mW Series 1 units from the Parallax Store but I will use the 100mW Series 1 units when I built he bot.
    Rforbes wrote: »
    Oyeah- and... I'm a noob at this stuff too. So if you have questions or see something wrong, be sure to hear out the more seasoned vet's around here! :cool:
    You sure seem to have good understanding of Spin. I'm struggling but I'm trying to tackle this in small functional sections. I'm going to have to digest that code a bit.

    Thanks,

    falcon
  • RforbesRforbes Posts: 281
    edited 2012-11-14 13:42
    Haha!!! No, I don't have a good understanding of it. I'm definitely getting better than I was a month ago, but I'm a looooooooooong way from a lot of these other guys skill level. I've just been working hard and heavy with the Xbee Pro XSC (S3B) version is all. Lots of trial and error, and patience.

    I think you're doing the right thing with tackling small sections. If you look at my code snippet today, it might seem like it's "good code"... which it is, if you follow the golden rule of "If the code works as intended, it's good code." BUT- if you look at this same snippet a year from now you'll say "Oh man, that code is junk. I could do the same thing faster, better, with less code" and blah blah blah. It's all part of the learning curve. As you keep at it, more will sink in and you'll figure out better ways to do stuff.

    Best of luck to you, please keep us posted on how you're project is turning out!
    Robert
  • FalconFalcon Posts: 191
    edited 2012-11-14 18:08
    Duane Degn,
    Am I calling your 74HC165_120929e Method correctly? Do I need to pass it a variable? Shouldn't it continue to "ping" the 74HC165_120929e Mainloop Method the way I have it under the repeat command? I did change all instances of xInputs to Switches. 74HC165_120929e works perfectly by itself but I'm not sure I'm getting the variable back from it.

    I didn't like how my code was evolving into a BS2-like loop instead of making calls to the necessary Objects so I restructured the TX Object. I want a separate cog launched for the ADC, 74HC165, XBee and Demo Board LEDs [P16..P23]. If the ADC and 74HC165 are continuously updating their respective variables then the variables should always have the most current data when the XBee "collects" the data to transmit. The result is LED P23 lit constantly lit, and garbled text on the PST.

    Do I have the commands/statements in the Main Method in the proper order? Do the cognew commands have to be in a certain place?

    Remote TX_11_14_2012 - Archive [Date 2012.11.14 Time 19.39].zip

    Thanks again,

    falcon
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-15 00:18
    Falcon wrote: »
    Duane Degn,
    Am I calling your 74HC165_120929e Method correctly? Do I need to pass it a variable? Shouldn't it continue to "ping" the 74HC165_120929e Mainloop Method the way I have it under the repeat command? I did change all instances of xInputs to Switches. 74HC165_120929e works perfectly by itself but I'm not sure I'm getting the variable back from it.

    The '165 program I wrote was intended to be a simple program to show how the '165 could be used with a Propeller. It doesn't have the needed methods to use as a child object.

    I stripped away the debug code and made the object usable as a child object. I haven't tested it yet since I don't have a breadboard with any 74HC165 chips on it right now.
    Falcon wrote: »
    I didn't like how my code was evolving into a BS2-like loop instead of making calls to the necessary Objects so I restructured the TX Object. I want a separate cog launched for the ADC, 74HC165, XBee and Demo Board LEDs [P16..P23]. If the ADC and 74HC165 are continuously updating their respective variables then the variables should always have the most current data when the XBee "collects" the data to transmit. The result is LED P23 lit constantly lit, and garbled text on the PST.

    While using multiple cogs can greatly improve the way a program works, it's easy to run out of cogs. The program you posted actually used all eight cogs. I trimmed it down to four cogs (I think you could probably get rid of two more).

    Since I/O pins are "or"ed together, if one cog sets an I/O pin high, another cog can not set it low. I try to make it a point of setting all I/O states of a pin from a single cog. I also call "Start" and "Init" methods from within the cog that will be calling methods in the child object. Many objects don't require you to only call its methods from a single cog, but there are few that do so I just make it a habit of making all calls to an object from within a single cog (this is just a good idea, not always necessary).

    Variables in one object can not be read from a different object directly. You need to use return values or pass pointer between the objects to let them share memory locations.

    I added a return value to the '165 object so the parent object needs to call the "ShiftIn" method each time it wishes to read from the shift register.

    I also added a "newDataFlag" I had mentioned previously. The method send information over the XBee waits until there is new data before sending a transmission.

    It makes me nervous to post a program I haven't tested, but I don't have all the hardware you are currently using wired up to a Propeller right now.
  • FalconFalcon Posts: 191
    edited 2012-11-17 14:25
    Duane Degn,
    I wasn't able to get the LEDs to display the switch data read from the 74HC165 using the child Object you included. I didn't actually check any other part since I want to get this bit working first. I pared my TX Object down to what I believe are the bare essentials to "use" your 74HC165_121114a Object to no avail. I did verify that all my components work using my code from 12 Nov.

    Do you see any obvious inconsistencies that would prevent the TX code from correctly calling your 74HC165 child Object? I did see that the TX code uses the command Switches := SR165.ShiftIn(BITS_IN) to call the 74HC165 while the 74HC165 child Object code includes the line PUB ShiftIn(bitsToRead). Should they be the same?

    TX code
    CON 
      _clkmode = xtal1 + pll16x 
      _xinfreq = 5_000_000 
    
      US_005 = 80_000_000 / 1_000_000 * 5                           ' 5us
        
      XB_Rx     = 3    ' XBee DOUT 
      XB_Tx     = 4    ' XBee DIN 
      XB_Baud   = 9600 
      CR        = 13                                        ' Carriage Return value       
      CLOCK     = 5                                         ' Connected to pin 2 of 74HC165
      LOAD      = 6                                         ' Connected to pin 1 of 74HC165
      DATA      = 7                                         ' Connected to pin 7 of 74HC165
      BITS_IN   = 8
      PC_Rx     = 31   
      PC_Tx     = 30 
      PC_Baud   = 9600
    con
    
      #0, CLS, HOME, #8, BKSP, TAB, LF, CLREOL, CLRDN           ' PST formmatting control
    
    var
       long Switches
                                                                             
    OBJ 
    
       SR165      : "74HC165_121114a" 
            
    Pub  Main
    
            SR165.Init(CLOCK, LOAD, DATA)                   ' Initialize 74HC165                               
            dira[16..23] := outa[16..23] := %11111111
            Read_Sensors                                    ' Use original cog (#0) to read sensors.
            
    PUB     Read_Sensors
               
              repeat
                Switches := SR165.ShiftIn(BITS_IN)          ' Read 74HC165
                outa[16..23] := Switches
    

    Your 74HC165_121114a Object
    CON
    {{
       Based on StampWorks v2.1 page 141.
       Program: SW21-EX24-74HC165-2.BS2
    
       Adapted for Propeller
       by: Duane Degn
       date: September 29, 2010
    
       As described in the StampWorks manual, the CLK INH (pin 15) should be connected to ground.
       I used the non-inverted data from pin 9 rather than the inverted data from pin 7.
    
       If powering the 74HC165 with more than 3.3V, a 4.7K &#937; series resistor should be used between the
       74HC165 chip and the Propeller chip. The other connections may remain the same as shown in
       the StampWorks manual.
    
       Version 121114a: Change to be a child object.
             
    }}
    CON
    
      MAX_BITS_TO_READ = 8         ' The limit is 32 since that limit of a long.
                                    ' It's possible to chain up to four 74HC165 chips together
                                    ' to read 32-bits.
                                                      
    VAR
    
      byte clockPin, loadPin, dataPin
      
    PUB Init(clock, load, data)
    
      clockPin := clock             ' Assign pins to global variables so the
      loadPin := load               ' object "remembers" the temporary local
      dataPin := data               ' variables.
      dira[clock] := 1              ' Set needed pins to outputs.
      outa[load] := 1
      dira[data] := 1
      
    PUB ShiftIn(bitsToRead)
      
      bitsToRead <#= MAX_BITS_TO_READ                        
      outa[loadPin] := 0            ' load the bits into the shift register
      outa[loadPin] := 1
      repeat bitsToRead
        result <<= 1                ' shift previous bit up one position
        result += ina[dataPin]      ' read the data one bit at a time
        outa[clockPin] := 1
        outa[clockPin] := 0
       
    

    Thanks,

    falcon
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-17 15:34
    I just noticed I never set the load pin to an output.

    Change this section of the Init method:
    dira[clock] := 1              ' Set needed pins to outputs.
      outa[load] := 1
      dira[data] := 1
    

    To:
    dira[clock] := 1              ' Set needed pins to outputs.
      outa[load] := 1
     [B] dira[load] := 1
    [/B]  dira[data] := 1
    

    As I mentioned, I haven't tested the code I posted which is almost asking for it not to work.

    If the above change doesn't fix things, I'll try out the '165 code myself. I found I still have some '165 chips wired up on one of my breadboards so it shouldn't be too hard to test now.
  • FalconFalcon Posts: 191
    edited 2012-11-17 18:14
    Duane Degn,
    I was able to get the switches to display on the TX Demo Board LEDs by commenting out the line repeat while newDataFlag . Since the newDataFlag will be initially set to 0, the code should drop through the repeat while newDataFlag command the first time through. It seems to hang there.

    The 74HC165_121114a Object includes the following and returns the data as it should

    dira[clock] := 1 ' Set needed pins to outputs.
    outa[load] := 1
    dira[load] := 1

    Will the XB_Send Method automatically run after the cognew(XB_Send, @stack3) command is executed? Or do I have to direct the code there?


    falcon

    Remote TX_11_17_2012b - Archive [Date 2012.11.17 Time 19.59].zip
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-17 18:49
    Sorry,

    I forgot to add the call to the Start method of for the XBee serial.

    I moved the display serial start to the same location.

    It wouldn't matter in this case, but I like to call the start method of an object from the same cog that will be accessing the object. There are some objects that don't play well when more than one cog makes calls to them.

    The cognew statement starts the XB_Send method. You don't need to call it elsewhere.
  • FalconFalcon Posts: 191
    edited 2012-11-20 17:19
    More progress and some questions

    I have the joysticks and switches displaying correctly on the PST off of the RX. The Demo board LEDs light corresponding to the switches. However, I cannot get the RX Demo board LEDs to light.

    It should be as simple as adding this to the Start Method

    dira[16..23]~~
    outa[16..23]~


    and

    outa[16..23] := DataIn

    to light them, but the LEDs do not light. Any ideas about that?



    I also added code in the RX Object to use a 74HC595 (that will eventually connect to a ULN2803 Darlington Array and 8 relays.) Should the "jm_595_ez" Object have it's own cog?

    As I have it written, the 74HC595 is not lighting the LEDs to match the switch actions on the TX side. Will the command "SR595.out1(DataIn)" not send DataIn to the "jm_595_ez" Object?

    Remote TX_11_20_2012 - Archive [Date 2012.11.20 Time 18.46].zip

    Remote RX_11_20_2012 - Archive [Date 2012.11.20 Time 18.46].zip

    falcon
  • RforbesRforbes Posts: 281
    edited 2012-11-20 17:47
    Heya Falcon,

    Your remote RX_11_20_20 object is a little odd?
    Pub Start
      PC.start(PC_Rx, PC_Tx, 0, PC_Baud)                    ' Initialize comms for PC         
      XB.start(XB_Rx, XB_Tx, 0, XB_Baud)                    ' Initialize comms for XBee   
      SR595.init(dpin, cpin, lpin)
      dira[16..23]~~
      outa[16..23]~                                   'set I/O pins from cog using the pins                           
    '  dira[16..23] := outa[16..23] := 1
      
      cognew(SERVOControl,@stack2)                          ' Start cog for Servo positioning
      SERVO.Start                                                                                                                       ****this object started here...
    
    
    
    PUB ServoControl
    
        SERVO.Start                                         ' Start servo handler                                      ****This same object started again here....
    
        repeat                                                                                                                      
           DataIn := XB.Rx      
    

    Is this intentional? (I've put a **** where it seems odd in the code snippet) You've started this same object in 2 different cogs. Just wasn't sure if you intended to?
  • RforbesRforbes Posts: 281
    edited 2012-11-20 17:54
    Oh, and to fix your output problem, try this ( I think. )
    PUB ServoControl
      dira[16..23]~~
      outa[16..23]~                                   'set I/O pins from cog using the pins 
    

    And remove those two commands from your Start method. I think you need the cog that's running the ServoControl method to set up the dira and outa... once that's done, the last bit of your code (at the bottom of your ServoControl method) should be able to drive the pins.
  • FalconFalcon Posts: 191
    edited 2012-11-20 18:44
    Rforbes wrote: »
    Heya Falcon,

    Your remote RX_11_20_20 object is a little odd?
    Pub Start
      PC.start(PC_Rx, PC_Tx, 0, PC_Baud)                    ' Initialize comms for PC         
      XB.start(XB_Rx, XB_Tx, 0, XB_Baud)                    ' Initialize comms for XBee   
      SR595.init(dpin, cpin, lpin)
      dira[16..23]~~
      outa[16..23]~                                   'set I/O pins from cog using the pins                           
    '  dira[16..23] := outa[16..23] := 1
      
      cognew(SERVOControl,@stack2)                          ' Start cog for Servo positioning
      SERVO.Start                                                                                                                       ****this object started here...
    
    
    
    PUB ServoControl
    
        SERVO.Start                                         ' Start servo handler                                      ****This same object started again here....
    
        repeat                                                                                                                      
           DataIn := XB.Rx      
    

    Is this intentional? (I've put a **** where it seems odd in the code snippet) You've started this same object in 2 different cogs. Just wasn't sure if you intended to?

    I based that on reply #2, although I might not have gotten that totally correct. I assumed the cognew command would need to be told where to continue, but I guess that's not needed since the ServoControl Method directly follows the cognew(SERVOControl,@stack2) command.

    just tried it with the first "SERVO.Start" commented out and it ran good.

    Thanks,

    falcon
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-20 18:45
    Falcon wrote: »
    More progress and some questions

    I have the joysticks and switches displaying correctly on the PST off of the RX. The Demo board LEDs light corresponding to the switches.

    That does sound like progress. Great!
    Falcon wrote: »

    However, I cannot get the RX Demo board LEDs to light.

    It should be as simple as adding this to the Start Method

    dira[16..23]~~
    outa[16..23]~


    and

    outa[16..23] := DataIn

    to light them, but the LEDs do not light. Any ideas about that?

    I think Rforbes has this figured out.
    Rforbes wrote: »
    I think you need the cog that's running the ServoControl method to set up the dira and outa... once that's done, the last bit of your code (at the bottom of your ServoControl method) should be able to drive the pins.

    That sounds kind of familiar for some reason?
    Duane Degn wrote: »
    Since I/O pins are "or"ed together, if one cog sets an I/O pin high, another cog can not set it low. I try to make it a point of setting all I/O states of a pin from a single cog.

    The "or"ing of the I/O pins was done for a good reason, but it makes it easy to write buggy code for the Prop. I think setting I/O pins from the wrong cog has got to be one of the most common mistakes made by Prop programmers.

    I can't tell you how many times I've seen bugs caused by setting I/O pins from the wrong cog. Not all of these observed bugs were in my own code.
    Falcon wrote: »
    I also added code in the RX Object to use a 74HC595 (that will eventually connect to a ULN2803 Darlington Array and 8 relays.) Should the "jm_595_ez" Object have it's own cog?

    As I have it written, the 74HC595 is not lighting the LEDs to match the switch actions on the TX side. Will the command "SR595.out1(DataIn)" not send DataIn to the "jm_595_ez" Object?

    It doesn't look like the '595 object needs to be run in its own cog. I haven't used JonnyMac's '595 object so I cann't answer your other questions about it.

    I assume there was some demo code that came with the object to show how to use it?

    I looks like Rforbes caught a couple of other errors.

    I hope you're having fun. To me this is really fun stuff.
  • Duane DegnDuane Degn Posts: 10,588
    edited 2012-11-20 18:48
    As your code is now the initial cog (#0) stops at the end of your Start method.

    You could should change:
    cognew(SERVOControl,@stack2)                          ' Start cog for Servo positioning
      SERVO.Start
     
    PUB ServoControl
        SERVO.Start                                         ' Start servo handler
    
    

    To:
    SERVOControl
     
    PUB ServoControl
        SERVO.Start                                         ' Start servo handler
    
    

    If you don't have an endless loop in your start method (in the top object) you ought to call another method (with an endless loop) before the start method ends in order to keep the cog (cog #0) alive.
  • FalconFalcon Posts: 191
    edited 2012-11-20 18:56
    Rforbes wrote: »
    Oh, and to fix your output problem, try this ( I think. )
    PUB ServoControl
      dira[16..23]~~
      outa[16..23]~                                   'set I/O pins from cog using the pins 
    

    And remove those two commands from your Start method. I think you need the cog that's running the ServoControl method to set up the dira and outa... once that's done, the last bit of your code (at the bottom of your ServoControl method) should be able to drive the pins.

    That helped too. Thanks. The RX Demo board LEDs are now responding. However, random LEDs are lighting up on the RX end when a TX switch is pushed, and the RX PST data is "jumpy" too. The LEDs on the TX end are stable. I might have to put some small caps on the RX LEDs to try to eliminate that. I'd like to use a second Delimiter for the switch data but I'm not sure exactly how to have the two different data streams transmitted without stepping on each other. Duane Degn added the NewDataFlag to the TX code. Maybe that (or that concept) could be used to have each data stream take its turn.

    falcon
Sign In or Register to comment.