Shop OBEX P1 Docs P2 Docs Learn Events
User interface theory for the Prop — Parallax Forums

User interface theory for the Prop

joeldjoeld Posts: 49
edited 2008-04-05 03:08 in Propeller 1
I've got all the output pieces for one of my first propeller projects working and have been thinking on how to program the user interface. It will be a very simple interface. The display is an LCD and there will need to be the ability to set a time and date, the desired set points for the closed loop controller and a few misc options. I'm thinking a couple of push buttons and maybe a rotary knob.

I'm coming from an interupt background and am looking for some theory with the Prop. Do most of you write a user interface·object that runs continually in a separate COG constantly checking pins and storing the results in variables that will be returned to the top object for the appropriate actions to be taken? Or is it a better practice to keep the top object very simple and have it check for inputs and call other objects to act on them.

Joel

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2008-03-27 01:08
    Depends what is best for the application but many of my interfaces respond keystroke by keystroke rather than sit and wait for input. Considering that you have 8 cogs to play with it makes a lot of sense to devote one to user interface that looks after the lcd and keypad. We all know that a program that takes up 16K would only take "1K" if it didn't need a user interface smile.gif

    So I like to keep my main runtime task free from the user interface. Have you seen my idea for using four buttons for a user interface?
    http://forums.parallax.com/showthread.php?p=715868
    Maybe it's a bit too radical for normal operators.

    *Peter*
  • joeldjoeld Posts: 49
    edited 2008-03-27 04:01
    Looks interesting I'll try running your sample code tomorrow. May work for my project.

    I like the idea of the LCD and the user input running in the same COG. I had it in my mind that i would need to call some function outside the user input object when an input ocurred. If I'm getting your concept, the user interface object could just sit and wait for input and operate the LCD. If inputs were made it would just store the new numbers in variables and the process control object could just check every so often to see if any of the set points had changed. I'd also have to send info to the user interface for LCD display.

    Would it be smart to set up a common block of memory that the different objects could share this common information in?
  • Paul BakerPaul Baker Posts: 6,351
    edited 2008-03-27 05:46
    When I create a program which requires a user interface, I do the coordination of everything in the master (cog 0). This includes interpretation of user input and performing the response. The other cogs are used as drivers serving as the conduit to the peripherals connected to the Prop or for tasks which require precise or fast execution. Since human input is very slow in the world of microprocessors, the relative slowness of spin isn't an issue at all.

    The reason why I do it this way is because of the single level object accessibility in spin (since it·has no inheritance). Having the supervisor function in a place where it has easy access to everything makes programming much simpler.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Paul Baker
    Propeller Applications Engineer

    Parallax, Inc.

    Post Edited (Paul Baker (Parallax)) : 3/27/2008 6:10:04 AM GMT
  • Nick MuellerNick Mueller Posts: 815
    edited 2008-03-27 10:53
    A very general software architecture oriented answer is "MVC".
    Initially more work, but as soon as you start to make changes, it pays off.
    The multiple COGs are a nice fit to that concept.

    <http://en.wikipedia.org/wiki/Model-view-controller&gt;


    Nick

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Never use force, just go for a bigger hammer!

    The DIY Digital-Readout for mills, lathes etc.:
    YADRO
  • RaymanRayman Posts: 14,229
    edited 2008-03-27 12:52
    I'm assuming that by "LCD" you mean a small display and not an LCD VGA monitor.· But, if I'm wrong, check out my GUI here:

    http://www.rayslogic.com/propeller/Programming/BasicWindowForm/BasicForm.htm
  • joeldjoeld Posts: 49
    edited 2008-03-27 18:11
    Correct, it will just be a 2x16 LCD. I had toyed with the idea of using the uOLED prop as well but that would be overkill and I'd have to deal with the I/O pin limitations.

    I'm afraid I'm not familiar with the term "MVC". I can see where the main Cog 0 concept Paul uses would definitely simplify keeping track of all the variable values in one place and just passing them to other "drivers" as arguments. My input will definitely be low bandwidth, just buttons so I don't believe timing will be a problem.

    One thing that troubles me is that I see some of the things you guys are doing with a prop and on this relatively simple project doing some PID control of a couple values with motor control and a very simple UI I'm eating up most of the available cogs. Makes me think I'm being very inefficient and missing some of the basic concepts of working with the prop.

    I appreciate the thoughts. I'd rather get started on the right track.

    Joel
  • Mike GreenMike Green Posts: 23,101
    edited 2008-03-27 18:41
    MVC stands for Model / View / Controller. See the Wikipedia link that Nick gave for details.

    Cogs are used to provide speed and/or tightly controlled timing for specific functions like video generation, floating point arithmetic, buffered serial port I/O, multiple servo control, stepper motor driver, etc. They're also used for things where isolating a function to an independent processor might simplify programming like some kinds of I/O device support.

    Often people mix up the notion of object and cogs which really are independent. Often it makes sense to isolate certain code to a separate object and to have that object communicate with the main program through a specific interface, but none of the code in the object really needs to execute on a separate processor. Similarly, some very small functions are made much simpler by letting a separate cog execute them. For example, servicing a PING ultrasonic distance sensor. It just takes a small amount of Spin code to do it, but the main program can initiate the operation and come back to it later. The separate cog initiates the operation, waits for the return of the echo, and computes the transit time and distance, then stops its cog (freeing it for other uses) after storing the result.
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-03-28 00:34
    Hi joeld -
    I have not done many interfaces that are embedded, but what I have done I structured with a case statement.· What I mean is that in COG 0, the main cog, is all the code that glues everything together.· From that cog drivers are launched, variables initialized, etc.· Then I drop into the "game loop" as those in video games may call it.·
    The game loop·is just an infinite loop that watches variables and responding accordingly.· Erase, move, and draw.· That simple - sort of.· At the top of the loop the·off screen buffer is cleared.· Then the various "events" are processed from the other cog/drivers.· The·GUI is·drawn based on case statements.· I setup a case statement for each screen and each time through the loop the screen is drawn.· Also in the case statement is where specific tasks are handled like moving a cursor or changing a value.· The limits are checked and the proper variables adjusted.· Finally the last thing done is the off-screen buffer is copied to the on-screen buffer.
    I hope this helps.· I need to produce some code that I am allowed to post, the applications I have done are available for posting.
    On a side note, you mentioned the limited I/O of the uOLED by 4D Systems.· I created an accessory that I call the uOLED-IOC which adds 16 GPIO through an I2C interface for the uOLED-96-PROP.· You can checked it out at www.brilldea.com.· Let me know what you think.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter

    www.brilldea.com·- check out the uOLED-IOC, an I/O expansion for the uOLED-96-PROP
    www.tdswieter.com
    One little spark of imagination is all it takes for an idea to explode
  • joeldjoeld Posts: 49
    edited 2008-03-28 02:54
    Mike I do see that I have fallen into that trap in the first things I've programmed. I can see where I could switch to using objects that could just run code without starting a cog. It seems like where I really start eating up cogs is when I need full duplex serial, float, float to string, clock, PID ect. In the first draft of my program, I just fired all these objects up at the beginning of my main program and left them running for use. I guess if I ran short of cogs I could start some of these functions just before needed then stop them. I would be doing a lot of cog starting and stopping, not sure if that would eat up time and power.

    I looked at the MVC info. I'm not sure I have the brain cells available to comprehend it all right now.

    I'm eager to try out some of these ideas. I need to pull the pieces off the breadboard and get them onto the proto board. The only item I haven't tried yet is the RTC.

    Timothy, I have looked at your uOLED-IOC before. I'm still trying to convince myself the uOLED is overkill as far as displays go for this project. I just ordered 2 for the next project I have planned. I like the easy access for plugging in the prop-plug. I guess if you needed some high bandwidth pins you could use the prop pins available in extended mode and use the I2C pins for things that didn't need full speed. I'm assuming there has to be a considerable loss in speed during the I2C translation.

    Thanks all for the ideas.

    Joel
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-03-28 05:09
    I understand, the uOLED-IOC can be overkill. You raise a good point about the I2C speed. I made a note to invetigate that and create an APP Note about it. In the future I will have an ASM driver for the device.

    So, have you chosen a direction for your design? Have you coded it yet? Let us know how it goes.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter

    www.brilldea.com·- check out the uOLED-IOC, an I/O expansion for the uOLED-96-PROP
    www.tdswieter.com
    One little spark of imagination is all it takes for an idea to explode
  • joeldjoeld Posts: 49
    edited 2008-04-04 03:30
    Timothy

    I think I'm going to give the main CASE loop running in COG0 and calling other objects a try. I've started to rewrite the main object along these lines, just getting started. I'm trying to think of the most efficient way to use a CASE loop to read a bank of three buttons. I could read all the pins into the lower bits of a byte then use a variable assigned the number in that byte as the expresion. I.E if the button assigned to the second significant bit were pressed then the CASE for X=2 would run. Using this method I could have conditions run based on multiple buttons being held during one loop.

    Sound feasible?
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-04-04 06:15
    joeld -

    I think I need to reread your post a couple more times for the logic of what you are proposing to sink into my mind.·· In the mean time allow me a moment to describe what I did.· Perhaps I should work up example code that I can post since the code I am referencing isn't open for posting on the forum.

    In my system I have a seperate cog that is reading data from a GPIO expander chip.· That cog is also debouncing the button inputs connected to the GPIO and placing the data in the HUB Ram.· Processing of the button input is important for debouncing and for detecting a change of the button (single shot, strobe, edge, what ever you want to call it)

    In the "main" cog, usually Cog0, the psuedo code for the case statement stuff is something like this:

    ·· -Initiate objects, variables, etc
    ·· -Enter Infinite loop (repeat)
    ····· -Clear the screen (or screen buffer)
    ····· -Case currentScreen (currentScreen is a variable for the screen to be displaying)
    ········· -Screen1:
    ············ -draw the screen, text, numeric values, etc
    ············ -If forward button press (edge detected)
    ················· -nextScreen++
    ············ -if previous button press (edge detected)
    ················· -nextScreen--
    ········· -Screen2:
    ············ -draw the screen, text, numeric values, etc
    ············ -If forward button press (edge detected)
    ················· -nextScreen++
    ············ -if previous button press (edge detected)
    ················· -nextScreen--
    ......
    ········· -ScreenX:
    ············ -draw the screen, text, numeric values, etc
    ············ -If forward button press (edge detected)
    ················· -nextScreen++
    ············ -if previous button press (edge detected)
    ················· -nextScreen--

    (case is finished, but still within the infinite loop)
    ···· If currentScreen <> nextScreen
    ······ -logic for copying nextScreen to currentScreen and checking for wrapping around

    ···· Any other logic you need to do per "frame"

    ···· Copy offscreen buffer to onscreen buffer


    Maybe that will help.· There is a lot to it that I could expand on.· I defined constance for all my screennames so the case statements are easier to read than a bunch of numbers.· If you have a screen in which you have a cursor and variables changing you can also define those.· Inside each case statement you check for the cursor buttons and move the cursor appropriately and draw the screen.· If you have animation that is to occur, usually I setup a "FrameCnt" variable that increments each time through the infinite loop.· I then base the animation off of that instead of getting stuck in a loop within a case statement.· The system is unresponsive then.

    Let me know if you have more questions or thoughts.· My post isn't well laid out, but there is a lot here to digest and I could clarify better.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter

    www.brilldea.com·- check out the uOLED-IOC, an I/O expansion for the uOLED-96-PROP
    www.tdswieter.com
    One little spark of imagination is all it takes for an idea to explode
  • Timothy D. SwieterTimothy D. Swieter Posts: 1,613
    edited 2008-04-04 06:16
    I should point out that the method I describe above is something I came up with. I browsed around teh web, I have done Visual Basic programming, and I read Andre's book about the Hydra. It was combination of these sources and my own thinking that chose the structure. Maybe there is a better way to do it, but I like how the system is laid out. It can easily be applied to many projects and can be customized as needed.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Timothy D. Swieter

    www.brilldea.com·- check out the uOLED-IOC, an I/O expansion for the uOLED-96-PROP
    www.tdswieter.com
    One little spark of imagination is all it takes for an idea to explode
  • joeldjoeld Posts: 49
    edited 2008-04-05 03:08
    Thanks for taking the time to describe your idea. I'll have to ponder that over. I will have only a couple of different screens. Some how I will have to enter a set mode to enter values such as set the time, date enter the desired set point.

    I haven't had much time to program on this much yet. Work keeps getting in the way. Hopefully I'll have a little time to work on it in the next few days.
Sign In or Register to comment.