Modifying a variable while the program is running

14 Jan 2014

I think this hello world forum was made for me.

While my program is executing on the Mbed, I would like to adjust a a couple variables to affect the way the program runs. Basically I have a feedback loop that moves an arm to hold it a constant Distance (D) from a moving object. D is currently just a variable that I initialize with the value as a float. I would like to be able to either type in a new value and press enter, or maybe increase/decrease the value with arrow keys. The only way I can think to do that is with a loop that waits for an input, but that makes the program stop and wait for the input. I dont want the program to stop. So is there a way to do this via programming? Thanks!

14 Jan 2014

Easiest way to do this is probably a Ticker that calls a function at regular intervals to execute your feedback control code. This code uses your global variable D.

The main program will then be a simple endless loop waiting for keyboard input that modifies the global variable D.

14 Jan 2014

Hi Wim, To my knowledge when I use pc.getc for keyboard input the program hangs there waiting for the keystroke. in fact i havent figured out how to use that for anyhting more than a single character of input. could you maybe post a generic example of what you are proposing? Thank You.

14 Jan 2014

The Ticker handbook page shows examples:

#include "mbed.h"
 
Ticker flipper;
DigitalOut led2(LED2);
Serial pc(USBTX, USBRX); // tx, rx
 
//change this into your controlloop
void flip() {
    led2 = !led2;
}
 
int main() {
   char ch;

    flipper.attach(&flip, 2.0); // the address of the function to be attached (flip) and the interval (2 seconds)
 
    // spin in a main loop. flipper will interrupt it to call flip and run your controlloop
    while(1) {
        // wait until key press
        ch = pc.getc();
        // do something with the ch

        wait(0.2);
    }
}
14 Jan 2014

Dave ° wrote:

The only way I can think to do that is with a loop that waits for an input, but that makes the program stop and wait for the input. I dont want the program to stop. So is there a way to do this via programming?

Hi Dave, welcome to the forums :)

There's a good function in the Serial API that can solve this - Serial::readable(). You can use this to check if the input buffer has anything in it before attempting to call getc(), which would avoid hanging the main program loop.

#include "mbed.h"
Serial pc(USBTX, USBRX);

int main() {
char c = 0x00;

while(1) {
if( pc.readable() )
  c = pc.getc();
//do other stuff
}
}

Cheers!

15 Jan 2014

Wim, thank you again for your input. I will take a pass at the ticker thing, but to me it looks like it will constantly hang in the getc loop. Are you saying that even when it is waiting for the character, it will continue to run the feedback loop?

Chris, Thank you, I think this option looks pretty good. I am about to go try it. At a glance it looks like it will only take 1 character at a time right? So maybe I have to use a buffer of some sort if I want to type "12"? Do I want to use pc.gets in this case?

15 Jan 2014

Correct, serial reads are done one char at a time using the mbed serial API.

If you're looking for an easy way to convert several chars into a number, you would store the input into a char array or other string and wait for some terminating character like the enter-key ('\r') then use a function like this to convert it into a number:

...
someStringClass str = "";
char tchar = 0x00;
int neko = -1;
...
        if( pc.readable() )
        {
                tchar = pc.getc();
                if( (tchar == '\r') && (str.length > 0) )
                        neko = someParser( &str );
                else
                        str += tchar;
                tchar = 0x00;
        }
...
int someParser( someStringClass *str )
{
        int idx = 1; // used change the '5' in 52 to 50
        int meow = 0; // the resulting number

        for(int i = str.length-1; i >= 0; i--)
        {
            if( !(str[i] < 48) && !(str[i] > 57) )
            { 
                meow += ((int)str[i]-48) * idx; // ascii numbers start at '0' = decimal 48, so subtract 48
                idx = idx*10; // scan backwards and increase the number of 0's for the next number read
            }
        }
...

There's a better (single-liner) way to do this using a power function, but this works just as well ... also that single-liner is on a laptop with a dead battery under my couch... but yes - works just as well :)

Let me know if you would like more example code, I just finished dusting off some of my older c-style strings code and made a parser for splitting serial API input like "set_frequency 52300" into strings and ints - would be happy to share that with you ^^

15 Jan 2014

Also have a look at MODSERIAL, then you can for example get an interrupt when \n is detected, and then read all the received characters at once.

15 Jan 2014

Erik - wrote:

Also have a look at MODSERIAL, then you can for example get an interrupt when \n is detected, and then read all the received characters at once.

wow... that's some serious code. i wish i knew about this earlier o_O

off-topic, but does this work with the mbed's USB-Serial driver or does it need level converters for using it with a PC's RS232?

15 Jan 2014

It works with the regular USB connector of the mbed: that one is connected to the interface chip, which does the translation from serial to USB, so for the code you write that one is just a regular serial.

It doesn't work if you run a USBSerial connection directly from your microcontroller, so the KL25 USB port on the KL25Z for example, or the D+ and D- pins on the LPC1768 and LPC11u24.

15 Jan 2014

Dave ° wrote:

Wim, thank you again for your input. I will take a pass at the ticker thing, but to me it looks like it will constantly hang in the getc loop. Are you saying that even when it is waiting for the character, it will continue to run the feedback loop?

Yes, the feedback loop will be called at the set intervalrate whatever the mainloop is doing. Obviously, you should make sure that the call completes before it gets called again or you will not get the desired update rate.

15 Jan 2014

Erik - this is some of the best code i've seen on this site. Incredible contribution and great documentation! i'll be importing it a lot, thanks :)

15 Jan 2014

is this a good reference for modserial? https://mbed.org/users/AjK/code/MODSERIAL/

Erik modserial looks very interesting but may be a bit out of me league at this point! but please continue to discuss.

Chris thanks for that sample code, it makes sense and I will give it a try.

15 Jan 2014

That is indeed the normal MODSERIAL. Mine is exactly the same, don't worry ;). Only difference is that mine supports the KL25Z: Andy made MODSERIAL, and it is very useful, however it was written when only the LPC1768 was around. He kinda hacked in LPC11u24 support, since their UARTs (serial peripherals) look very much alike. However the KL25 has a completely different UART, so in order to support that I first had to split the target dependent and target independent code, which causes them to look quite different, but in the end they use the same commands.

That said I doubt I will add more targets to it, despite the hard work being done: there is also now BufferedSerial, which I wouldn't be surprised if it ends up in the official mbed lib, which has the same idea as MODSERIAL, only it does everything with standard mbed serial functions. For you it is not very relevant now, it lacks many of the nice things of MODSERIAL, and apparantly doesn't work on the LPC1768. However for the future it is easier to have one that just uses standard library functions, even if it is a bit less efficient, than code which needs to be updated with every new target platform.

16 Jan 2014

...and now I just learned how to publish my program! It is unlisted so you can find it in my profile if you guys are interested. I have not yet implemented anything per this discussion, so will revise and commit it as I make progress. Thanks again for your support guys, this mbed experience has been really great so far.

edit..just finished adding the pc.readable() section to the code (lines 159-171). So far just using a single character to increase/decrease the variable value. It works beautifully! The multi character parsing technique Chris posted is a bit over my head at the moment. I will have to make a small sample program to figure it out.

And here is a picture of my cardboard 1DOF robot arm :) The sensor is pointing at the wall, and the arm moves until the sensor reaches the target value. So now I can change the target value real time to reposition the arm. /media/uploads/CATPart/testrig.jpg

15 Mar 2014

how about using a simple menu structure? Using a switch case. Movement can be defined in functions or classes.

menu

#include "mbed.h"
Serial pc(USBTX, USBRX);
 
void showMenu()
{
     pc.printf("0) Move Arm (X,Y,Z)\n");
     pc.printf("1) Move Arm left/right\n");
     pc.printf("2) Move Arm up/down\n");
     pc.printf("3) Preset Move\n");
     pc.printf("4) Exit\n");
     pc.printf("Please make a choice =>");
}


int main() 
{
pc.baud(9600);
char command;
bool running=true;

showMenu();

    while(running)
    {
        if(pc.readable()) 
        {
            command = pc.getc();               
            pc.printf("\n\n");         
         
            switch (command) 
            {
            case '0' :  
                     arm_XYZ(); 
                     showMenue();
                     break;
          
            case '1' :
                     arm_LR();
                     showMenue();
                     break;
                    }
             case '2' :
                     arm_UD();
                     showMenue();
                     break;
                     }
          
            case '3' :
                     arm_PRE();                    
                     break;
                     
            case '4' :
                      pc.printf("Bye Bye");
                      running = false;                    
                      break;

            default :
                        pc.printf("Thats not an option stupid!/n");
                        showMenue();
                        break;
           } //switch                                                                            
       } //if
   } //while
} //main