Shop OBEX P1 Docs P2 Docs Learn Events
cognew help — Parallax Forums

cognew help

ispearispear Posts: 20
edited 2011-03-28 20:22 in Propeller 1
I have attached the code. I am trying to launch cogs using a series of IF statements that repeats indefinitely. I have commented out all the pieces of code that i haven't written all the parts to but I dont understand what is wrong with what i have. The program runs great until the IF statements.

Thanks for your help,

-Isaaccognewhelp.spin

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 19:46
    So what exactly doesn't work? What is supposed to happen but doesn't?

    A few things, if you keep keep calling cognew in a loop you'll will eventually run out of cogs (lcdsteer will exit but it starts up a serial driver which isn't shut down and consumes a cog). Stack space for cognew/coginit starts at index 0, i.e. cognew(lcdsteer, @stack4[30]) will definitely corrupt VAR memory (use cognew(lcdsteer, @stack4{0} instead).
  • ispearispear Posts: 20
    edited 2011-03-26 20:22
    Kuroneko,

    When the program gets to the point where the IF sequence should loop, everything goes crazy (lights flash, lcd displays weird characters and it freezes). I have a 4 way rotary switch next to an LCD. The LCD will display different data when the switch is in different positions. (the if sequence) When I change the stack value to 0, the lcdselect works the new cog is not launched.

    thanks so much for the help,

    -Isaac
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 20:32
    From that I assume it's still not quite right. Did you change all the other cognew commands to use their stacks starting at 0? E.g. stack3 is used starting at 20 which may affect stack4.

    Choosing stacks needs a bit of fiddling around. It's best to start with a bigger value (personally I use 32 longs) and go down from there if memory gets tight (but not below the minimum value for that method).

    As for the loop, you'll still have to do something to counter the LCD.start call. As I said, this simply starts a serial driver consuming a cog. Once lcdsteer exits it doesn't stop the LCD driver. Meaning you just lost/leaked a cog.
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 20:42
    You also start at least two cogs driving the LCD (one in lcdinit the other repeatedly in lcdsteer). May I suggest you take a step back and sort out which cog does what exactly? Not everything has to be done in a new cog for the sake of it.
  • ispearispear Posts: 20
    edited 2011-03-26 20:42
    Ok, I understand what you are saying about the LCD.start but how would you suggest doing that. I am fairly new to the propeller platform if your couldn't tell.

    thanks,

    -Isaac
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 20:49
    Easiest way is to call LCD.stop before lcdsteer exiting. You should wait a bit though to make sure that the serial data in the buffer has been sent. I haven't determined your total cog usage yet but have you considered leaving the LCD cog running (endless loop) and just pick up a command from a global variable to do stuff? OTOH if you know you run out of cogs depending on your switch settings then you'll have to shut them down occasionally.

    For example:
    repeat
      repeat until command <> 0
      ' do something in here if/else/case
      command := 0                   ' done, ready for next task
    
  • ispearispear Posts: 20
    edited 2011-03-26 20:53
    Here is what I am trying to accomplish, maybe this will make more sense. I have a control box for a tractor with an LCD, rotary switch, and single axis joystick (potentiometer). The joystick will drive a motor controller for the steering. The LCD is strictly for informational purposes for the tractor driver. He needs to be able to scroll through different programs for the LCD (stopwatch, steering display accelerometer readings and diagnostics) The steering display is a custom character that moves across the bottom line of the LCD based on the position of the wheels. (That is what i am trying to launch with the first IF) The diagnostic tell the driver if the brake is not pressed when he tries to start the engines, or not in neutral etc. I figured that a single COG should be used for the IF sequence, a single cog used for the steering (since they both need to always be able to work) and one cog to handle the rest of the tasks.
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 21:00
    That sounds like a finite number of cogs to me. So start them all in the main method and later tell them what to do, e.g. the main method starts a cog for the steering. This particular method would initialise the LCD (it's the only cog talking to it) and then wait for commands issued by your IF sequence. After having started all the other helper methods in separate cogs the main method could just drop into the IF sequence itself.
    PUB main
    
      ' start helper method 1
      ' start helper method 2
    
      repeat   ' [COLOR="red"]IF sequence[/COLOR]
        ' sample inputs and distribute commands to helper methods
    
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 21:15
    On a side note - it doesn't seem to be my day - re-starting the LCD will automatically stop the the used cog as it's the same object instance. Sorry about that. Still, there should only be one user.
  • ispearispear Posts: 20
    edited 2011-03-26 21:23
    that makes sense. how would i tell the LCD cog to wait till it gets a command from the IF cog, and, how do I tell the LCD cog what to display
  • kuronekokuroneko Posts: 3,623
    edited 2011-03-26 21:36
    Something like his should do. Basically each helper function has a command index assigned H_*, this is used for stack and command slot usage. helper_0 has the name lcdsteer. In the IF sequence (main function) if pin 12 is high and the previous display command has finished the buffer is filled with whatever you want to display, then the command is issued which is then picked up by the lcdsteer method. This is just quick and dirty to give you an idea for command handshake. HTH
    CON
      #0, H_0, H_1, N
    
      stack_size = 32
      
    VAR
      long  command[N], stack[N*stack_size]
      byte  buffer[64]
    
    PUB main
    
      cognew(lcdsteer, @stack[H_0*stack_size])
      cognew(helper_1, @stack[H_1*stack_size])
    
      repeat
        if ina[12] and not command[H_0]
          ' copy stuff to buffer
          command[H_0] := TRUE                              ' not equal 0 -> parameters valid
    
        if ina[13] and not command[H_1]
          ' prepare parameters
          command[H_1] := TRUE                              ' not equal 0 -> parameters valid
          
    PRI lcdsteer
    
      ' init LCD
    
      repeat
        repeat until command[H_0]                           ' wait for command
      ' LCD.str(@buffer)
        command[H_0] := FALSE                               ' ready for next command
        
    PRI helper_1
    
      repeat
        repeat until command[H_1]                           ' wait for command
      ' do stuff
        command[H_1] := FALSE                               ' ready for next command
    
    DAT
    
  • StefanL38StefanL38 Posts: 2,292
    edited 2011-03-26 23:58
    if I'm allowed to chime in,

    you have already a quite complex program but - from what you ask - I assume you knowledge about programming is quite medium. Espessially about programming the propeller with parallal working processes.
    So IMHO there are two ways to get your application finished: one that takes a real long time and one that takes only a medium long time.

    The real long time way is to hurry up trying to do everything at the same time and do almost no testing. This will end up in a lot of hidden bugs and it will take a long time to find them because they can be all over in the code
    bug a causing bug b casuing bug c only if .....

    The other way seem to decelerate the progress of the project. It will need more time at the beginning but it will pay of 10 times at the end.
    This way is to code in a certain style. This style is to divide things into senseful units.(=methods) each method does ONE thing. This is what you already do maybe not consequent in every case but most of the time.
    Then writing one method at a time and after finishing writing the code do extensive testings of just this single method until it works properly.
    Only after finishing these tests start with the next method. This will assure that bugs are in most cases in the actual method (and nowhere else). This will make it much easier to find bugs.

    Especially about the LCD: if more than one cog sends directly to the LCD it will happen that two or even more cogs send data at the same time. And then all the data gets mixed up.

    How to solve this? By using a buffer. Your LCD has a finite number of characters. Define two buffers for each character as a bytearray. Then there will be one method that compares each character of buffer1 with buffer2.
    If a value has changed send buffer2 to LCD actualise buffer1 with value from buffer2.

    All other methods write into the buffer at well defined positions
    example:
    temperature-value write into buffer at first line columm 1 - 6
    joystick position write value into buffer at fourth line colum 1- 20

    now the temperature-value and the steer-character can be written into the buffer at any time as often as you want.

    whenever the the LCD-write-method detects a difference in any byte of the buffer it will send all bytes ALWAYS in sequence and nothing gets mixed up anymore.


    for other methods you define constants with different values

    c_idle = 0

    c_LED1_on = 1
    c_LED1_of = 2

    define a global variable and check this variable for its value

    repeat
    if MyVar <> c_idle then
    case MyVar
    c_LED1_on : ....

    c_LED1_off : ....

    the basic concept for all is to detect CHANGES (LCD_buffer vlaue changes, MyVar-value changes etc.
    and then do something apropriate depending on the value.
    After finishing this action set MyVar := c_idle again

    best regards

    Stefan
  • ispearispear Posts: 20
    edited 2011-03-28 18:37
    Stefan and Kuroneko,

    I apologize for such a late response. This information is so very helpful. I am going to do just as you both have suggested with the buffer. I am going to Kansas State University currently and this program is for a tractor pull. This advice helps so much. I would be delighted if you both would let me contribute parts to a project you are working on as my thanks. I'm sure i will have more questions but for now this will get me started.

    Thanks,

    -Isaac
  • bennettdanbennettdan Posts: 614
    edited 2011-03-28 19:28
    @ispear I think what you are trying to do is veiw 4 Different LCD screens with the 4 position rotary swicth.
    One question is the Stering character at the bottom of the screen need to be seen in each of the 4 screens?
    I looked at yoru code and it looks like you have 8 cogs you want to start so start the cogs at the first of the main program like kuroneko said to do then each of your cogs will have global variables for the data like Stefanl38 suggested, you want to read by the LCD cog and inside the LCD cog setup your 4 position rotary switch input loop to clear and veiw the global variable from the cog you want to veiw.
    This should keep each cog running and instead of starting and stoping the cogs which does take a little time and then should work like you envision.
    By the way this sounds like a really fun project..
  • ispearispear Posts: 20
    edited 2011-03-28 20:22
    bennettdan,

    Thanks for the input. I am still learning the propeller platform but I'm getting there. This is a neat project. Creating the global variables for the LCD cog to read makes sense but how would you suggest I use the variables to run the LCD cog. What you are saying makes complete sense, i just need a bit more detail still, I'm not that familiar yet.

    Thanks,

    -Isaac
Sign In or Register to comment.