Shop OBEX P1 Docs P2 Docs Learn Events
Multiple Virtual Peripherals and serial comms to laptop — Parallax Forums

Multiple Virtual Peripherals and serial comms to laptop

chrisburgchrisburg Posts: 6
edited 2009-02-22 11:08 in General Discussion
Hi

I am working on modifying a radio controlled car using a Javelin stamp to allow lots of data to come back to my laptop and to allow sending of commands via serial to the car to drive it from my laptop.. but also want the car to be able to avoid obstacles and go to a GPS point itself..

The components I am using include:
I want to add a compass but not sure which is a good one or how to interface it

I know I have lots more code to do and so am focusing on the simple stuff first..

The stuff I need help on is:
  • Storing the raw data from the sensors/components in variables or some kind of state vector (which can update every second or something)
  • Sending the variables / state vector back through my serial port to my laptop (which has hyperterminal or some other app ready to report or react to the data)
  • Awaiting commands from the laptop via the same serial port (this has been part coded but is flakey)
  • - further down the line, coding some kind of class that depending on the variables/state vector drives the car without me interferring from one GPS point to another

I am struggling though.. this is all very new to me and I have spent days on google and forums trying to figure out the best way to do it, I have uploaded my code so far.. each individual class works if you set it as main using the ole while(true) loop.. but when i tried having all the sensors working and sending the data via the serial port it crashed :S I think I need to use a timer but am not sure if I have enough pins, virtual peripheral space or examples to get it to work

If you have any other questions please feel free to ask as I am really stuck and getting frustrated and am sure the javelin will allow me to do what I want.

Cheers

Chris

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-05-12 15:53
    Chris,

    You have too many simultaneously active Virtual Peripherals:
    2 ADC
    3 Uart
    2 PWM

    You can only have 6 active VP's at any time.
    If you want to use the Timer VP, which really cannot be stopped,
    that leaves you with 5 slots to run different VP's.
    All transmit uarts can occupy one slot, as can all the ADC.
    PWM must of couse keep running.

    1 Timer (always active)
    2 PWM (always active)
    1 Uart receive (always active)
    leaves 2 slots to run either ADC or Uart transmit/receive.

    regards peter
  • chrisburgchrisburg Posts: 6
    edited 2008-05-12 16:07
    Hi Peter, thanks for you prompt reply..

    Could the timer which I have always active go to each class and update the variables every second - and with each update start and stop vp's where required?

    If I have 1 example I could probably code up the rest.. the only timer example I found was on page 146 of the javelin stamp manual but I couldn't figure out how to include that in my code to process each sensor..

    If I have the uart receive always active, that can wait for commands from the laptop I think.. then I guess I could use a variable to store the current command if any and according to that command drive the vehicle when it checks to see what PWM is required.. lol this is where I get lost again.. if its checking every half second for new commands it should be quick enough to control the car
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-05-12 16:31
    You can use as many timers as you need, because only the first declared timer
    occupies a vp slot. I suggest you create the first timer before any other VP.

    public class CarMain {

    · static Timer mainTimer = new Timer(); //first VP
    ··static·ADC xAccm2g;······· //placeholders declared but no VP slots occupied yet
    ··static·ADC yAccm2g;
    · static Uart txBaseStation;
    · static Uart rxBaseStation;
    · static Uart sio;
    · static GPS_Parallax mygps;
    · static Accelerometer accx;
    · static Accelerometer accy;

    · static void main() {
    ····xAccm2g = new ADC(xPin1, xPin2); //create ADC
    ··· xAccm2g.stop(); //and stop it to free VP slot
    ····yAccm2g = new ADC(yPin1, yPin2); //ditto
    ··· yAccm2g.stop();
    ····accx·= new Accelerometer(xAccm2g); //create 2 accelerometer objects
    ··· accy =·new Accelerometer(yAccm2g);
    ··· //more intialisation here
    · }

    }



    In the accelerometer class, you can do the following:
    //Class for the accelerometer 2g dual axis
    import stamp.core.*;

    public class Accelerometer
    {
    · private ADC adc;

    · public Accelerometer(ADC adc) {
    ··· this.adc = adc;
    · }

    · public int value() {
    ··· adc.start();
    ··· int value = adc.value();
    ··· adc.stop();
    ··· return value;
    · }

    }

    Whenever you request a value from the ADC, it is first started and after a value has
    been grabbed, it is stopped, freeing a VP slot.

    You can do something simular with Uarts, espacially uarts that operate in half duplex,
    that is, there is no receive required until some command has been sent.

    regards peter
  • A. ColeyA. Coley Posts: 4
    edited 2008-05-13 03:34
    I'm having problems trying to get the range-finder and stepper-motor to work simultaneously as VP's for the Javelin Stamp. I need to constantly read the distance from the senor, pass that data serially (which I'll worry about later), while it is rotated by the stepper motor. Any help is greatly appreciated. Here is the code I have so far:



    //***************************************
    // Sensor & Stepper-Motor Test Program
    //***************************************



    import stamp.core.*;


    public class SensorAndStepper
    {
    ····· static Stepper motor = new Stepper(CPU.pin4, CPU.pin5, CPU.pin6, CPU.pin7);
    ····· static Sensor srf02 = new Sensor(CPU.pin0, CPU.pin1);

    ····· public static void main()
    ····· {

    ··········· while(true)
    ··········· {
    ··················· srf02.measureDistance();
    ··················· motor.rotate();
    ··········· }
    ····· }
    }


    //============================================>


    public class Stepper
    {
    ······· private int stpIdx = 0;··········· // current step index

    ······· private int ph1Pin;··············· // phase 1 control pin
    ······· private int ph2Pin;··············· // phase 2 control pin
    ······· private int ph3Pin;··············· // phase 3 control pin
    ······· private int ph4Pin;··············· // phase 4 control pin

    ······· public static final int STEPS_PER_REV = 48;

    ······· public Stepper(int ph1Pin, int ph2Pin, int ph3Pin, int ph4Pin)
    ······· {
    ··············· this.ph1Pin = ph1Pin;
    ··············· this.ph2Pin = ph2Pin;
    ··············· this.ph3Pin = ph3Pin;
    ··············· this.ph4Pin = ph4Pin;
    ······· }

    ······· private void setFullStep(int theStep)
    ······· {
    ··············· switch(theStep)
    ··············· {
    ······················· case 0:
    ······························· CPU.writePin(ph1Pin, true);
    ······························· CPU.writePin(ph2Pin, true);
    ······························· CPU.writePin(ph3Pin, false);
    ······························· CPU.writePin(ph4Pin, false);
    ······························· break;

    ······················· case 1:
    ······························· CPU.writePin(ph1Pin, false);
    ······························· CPU.writePin(ph2Pin, true);
    ······························· CPU.writePin(ph3Pin, true);
    ······························· CPU.writePin(ph4Pin, false);
    ······························· break;

    ······················· case 2:
    ······························· CPU.writePin(ph1Pin, false);
    ······························· CPU.writePin(ph2Pin, false);
    ······························· CPU.writePin(ph3Pin, true);
    ······························· CPU.writePin(ph4Pin, true);
    ······························· break;

    ······················· case 3:
    ······························· CPU.writePin(ph1Pin, true);
    ······························· CPU.writePin(ph2Pin, false);
    ······························· CPU.writePin(ph3Pin, false);
    ······························· CPU.writePin(ph4Pin, true);
    ······························· break;
    ··············· }
    ······· }

    ······· public void stepFFwd(int steps, int msDelay)
    ······· {
    ··············· while(steps-- > 0)
    ··············· {
    ······················· stpIdx = (stpIdx + 1) % 4;
    ······················· setFullStep(stpIdx);
    ······················· CPU.delay(msDelay * 10);
    ··············· }
    ······· }

    ······· public void stepFRev(int steps, int msDelay)
    ······· {
    ··············· while(steps-- > 0)
    ··············· {
    ······················· stpIdx = (stpIdx + 3) % 4;
    ······················· setFullStep(stpIdx);
    ······················· CPU.delay(msDelay * 10);
    ··············· }
    ······· }


    ······· public void rotate()
    ······· {
    ··············· while(true)
    ··············· {
    ······················· CPU.delay(20000);
    ······················· stepFFwd(STEPS_PER_REV, 60);····· // one rev clockwise
    ······················· CPU.delay(10000);······················ // wait for 1 second
    ······················· stepFRev(STEPS_PER_REV, 15);····· // one rev counter clockwise
    ······················· CPU.delay(30000);······················ // wait for 3 second
    ··············· }
    ······· }
    }

    //=======================================>

    public class Sensor
    {
    ··· private int pinTX = CPU.pin0;··············· // pin for data 'out' to sensor
    ··· private int pinRX = CPU.pin1;··············· // pin for data 'in' from sensor
    ··· private Uart srfTX = new Uart(Uart.dirTransmit,pinTX,Uart.dontInvert,Uart.speed9600,Uart.stop2);
    ··· private Uart srfRX = new Uart(Uart.dirReceive,pinRX,Uart.dontInvert,Uart.speed9600,Uart.stop2);
    ···
    ··· int data;

    ··· public Sensor(int pinTX, int pinRX)
    ··· {

    ··· }

    ··· public void measureDistance()
    ··· {
    ········· srfTX.sendByte(0x00);··············· // address
    ········· srfTX.sendByte(0x50);··············· // command Real Ranging Mode (result in inches)

    ········· while(true)
    ········· {
    ············· CPU.delay(5000);··············· // wait 1 second
    ············· srfTX.sendByte(0x00);··············· // address
    ············· srfTX.sendByte(0x53);··············· // command Get Range, returns 2 bytes automatically

    ············· data = srfRX.receiveByte() << 8;··············· //receive MSB
    ············· data += srfRX.receiveByte();··············· //receive LSB

    ············· System.out.println(data + " - Inches");
    ············· CPU.delay(5000);
    ········· }
    ··· }
    }


    Post Edited (A. Coley) : 5/13/2008 3:41:18 AM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-05-13 07:26
    Coley,
    Your problem is that your rotate() uses a while(true) loop that never exits.
    Split it up like this:

    ······· public void rotateCW() //rotate clockwise
    ······· {
    ·········· stepFFwd(STEPS_PER_REV, 60);····· // one rev clockwise
    ······· }

    ······· public void rotateCCW() //rotate counterclockwise
    ······· {
    ··········· stepFRev(STEPS_PER_REV, 15);····· // one rev counter clockwise
    ······· }

    In your mainloop

    ··············· while(true)
    ··············· {
    ······················· srf02.measureDistance();
    ························CPU.delay(20000);
    ······················· motor.rotateCW();····· // one rev clockwise
    ······················· CPU.delay(10000);····· // wait for 1 second
    ······················· motor.rotateCCW;····· // one rev counter clockwise
    ······················· CPU.delay(30000);···· // wait for 3 second
    ··············· }

    That at least lets you measure distance while rotating the steppers.
    You can insert multiple measureDistance() calls in this while (true) loop.
    Alternatively, you can setup a timer to replace the CPU.delay() calls.
    Timer t = new Timer();
    int state = 0;
    t.mark();
    ··············· while(true)
    ··············· {
    ······················· srf02.measureDistance();
    ······················· switch (state) {
    ·························· case 0: //CPU.delay(20000);
    ····································· if (t.timeout(2000)) {
    ······································· motor.rotateCW();····· // one rev clockwise
    ······································· t.mark();
    ······································· state++;
    ····································· }
    ······································break;
    ·························· case 1: //CPU.delay(10000);
    ····································· if (t.timeout(1000)) {
    ······································· motor.rotateCCW();····· // one rev counter clockwise
    ······································· t.mark();
    ······································· state++;
    ····································· }
    ······································break;
    ···························case 2: //CPU.delay(30000);
    ····································· if (t.timeout(3000)) {
    ······································· t.mark();
    ······································· state = 0;
    ····································· }
    ······································break;
    ······················· }
    ··············· }

    This way measureDistance() gets called many times while waiting for a stepper event.

    regards peter
  • chrisburgchrisburg Posts: 6
    edited 2008-05-13 16:16
    Peter

    I have applied the code example and expanded it to send commands back to my laptop application.

    I have also got it so that I can receive commands from the laptop to start sending me accelerometer data

    I keep getting an error after a bit of time which seems to be a memory leak but I cant find where it is?

    [noparse][[/noparse]Error IDE-0028] Unhandled exception in JVM: java.lang.OutOfMemoryError

    regards

    Chris
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-05-13 16:57
    The OutOfMemory error is because you concatenate strings using '+'.
    This leads to temporary·strings whose memory cannot be reused because
    the javelin does not support garbage collection.
    I have split the statements that used this concatenation.

    A second error is that you stop a uart transmitter directly after sending the last byte.
    Since it takes time to actually transmit the bytes, you need to wait until the
    transmitter buffer is empty and nothing is being sent. I added this to the code
    as well.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-05-13 17:06
    Note that Integer.toString() also allocates a new string, so its use
    will also lead to OutOfMemory errors.
    You may want to consider the Format class. That can convert integervalues
    into a string for any base (binary,octal,decimal,hexadecimal) using a declared
    char array. So that will not lead to OutOfMemory errors.
    http://tech.groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/util/text/

    The Format.java goes into folder ...\lib\stamp\util\text

    regards peter
  • chrisburgchrisburg Posts: 6
    edited 2008-05-15 16:08
    Peter

    thanks again for your help, I am going to integrate all the other sensors in the same way now so fingers crossed [noparse]:)[/noparse]

    I will keep this post up todate with my progress!

    Cheers

    Chris
  • chrisburgchrisburg Posts: 6
    edited 2008-06-12 11:42
    I used the format class and got int to string working when sending ints through serial.. this has stopped that specific memory leak..

    Now any ints I want to send go through:

    ·· private static void sendint(int b)
    ·· {
    ···· char[noparse]/noparse mystring = new char[noparse][[/noparse]7];
    ···· int i=0;
    ···· Format.sprintf(mystring,"%d",b);
    ···· while (mystring[noparse][[/noparse]i]!=0) txBaseStation.sendByte(mystring[noparse][[/noparse]i++]);
    ·· }

    How would I use the same format class to change a string command into an int for PWM?

    i.e. command comes in as a string commvalue = "235" and I want that to be int 235.. and most importantly without memory leaks!

    Thanks in advance
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-06-12 11:50
    You can use:

    char[noparse]/noparse buf = new char[noparse][[/noparse]7]; //hold incoming signed decimal number + closing null, -32768 to +32767
    int[noparse]/noparse value = new int[noparse][[/noparse]1]; //placeholder for binary value

    Format.sscanf(buf,"%d",value);
    //now value[noparse][[/noparse]0] is the decimal value

    If the number is stored at an offset in your receive buffer,
    you can use
    Format.bscanf(buf,offset,"%d",value);
    See the descriptions in the Format class.
    Note that sscanf and bscanf both use atoib() function.

    regards peter
  • jmspaggijmspaggi Posts: 629
    edited 2008-06-12 12:27
    Also, I will recommand you to put "mystring" outside of the methode, to avoid multiple creations and so "memory leak". Like that:


       private static char[noparse][[/noparse]] mystring = new char[noparse][[/noparse]7];
    
       private static void sendint(int b)
       {     
         int i=0;
         Format.sprintf(mystring,"%d",b);
         while (mystring[i]!=0) txBaseStation.sendByte(mystring[noparse][[/noparse]i++]);
       }
    [/i]
    
  • chrisburgchrisburg Posts: 6
    edited 2008-06-13 16:41
    I think I might be going about this the long way..

    on a timer I check to see if there is any data in teh buffer.. if there is then I process it for commands and action any commands that exists:


    static char commandType;
    static StringBuffer commandValue;
    static char c;

    static void getCommand()
    · {
    ··· c = 0xff; //init char
    ··· commandType = 0xff; //init char
    ··· commandValue.clear();
    ··· //check the ole byte available to see if it is a start command
    ··· if (rxBaseStation.byteAvailable())
    ··· {
    ····· c = (char)rxBaseStation.receiveByte();
    ····· if(c == '{')
    ····· {
    ······· commandType = (char)rxBaseStation.receiveByte(); //get the type of command
    ······· //gather the additional value of the command
    ······· while (c != '}')
    ······· {
    ·········· if (rxBaseStation.byteAvailable())
    ·········· {
    ············ c = (char)rxBaseStation.receiveByte();
    ············ if(c != '}')
    ············ {
    ··············· commandValue.append(c);
    ············ }
    ·········· }
    ······· }
    ······· processCommand();
    ····· }
    ··· }
    · }


    The commandValue is then used further along

    static String commValue = ""; //string based command value
    static int icommValue; //integer based command value
    static int[noparse]/noparse value = new int[noparse][[/noparse]1]; //placeholder for binary value
    static char[noparse]/noparse buf = new char[noparse][[/noparse]7]; //hold incoming signed decimal number + closing null, -32768 to +32767

    static void processCommand()
    · {
    ··· //command has been gathered.. now do something with it..
    ··· commValue = commandValue.toString();
    ··· switch (commandType)
    ··· {
    ····· case '0': //start sending sensor data·to laptop
    ······· if (commValue.equals("true"))
    ······· {
    ········· sendsv = true;
    ······· }
    ······· else
    ······· {
    ········· sendsv = false;
    ······· }
    ····· break;
    ····· case '1': //Update engine pwm

    ········buf = commValue;
    ······· Format.sscanf(mystring,"%d",value);
    ······· icommValue = value[noparse][[/noparse]0]; //now value[noparse][[/noparse]0] is the decimal value
    ······· engine.update(icommValue, 2304);
    ······· engineVar = icommValue;
    ····· break;
    ····· case '2': //Update Steering PWM
    ······· Format.sscanf(mystring,"%d",value);
    ······· icommValue = value[noparse][[/noparse]0]; //now value[noparse][[/noparse]0] is the decimal value
    ······· steering.update(icommValue, 2304);
    ······· steeringVar = icommValue;
    ····· break;
    ··· }
    · }

    I am not sure how to get the string into teh char array in order to convert it to an int for use?

    ········buf = commValue;
    ······· Format.sscanf(mystring,"%d",value);
    ······· icommValue = value[noparse][[/noparse]0]; //now value[noparse][[/noparse]0] is the decimal value
    ······· engine.update(icommValue
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-06-13 17:29
    You could do
    commandValue.append(0); //add closing null
    Format.sscanf(commandValue.toCharArray(),"%d",value);
    I think that will work.

    regards peter
  • koyali143koyali143 Posts: 1
    edited 2009-02-22 11:08
    Hi this is koyali now a days so many computers are available in the market that is pc
    computers but most of the people need laptop computers because it is carried who want
    to go so i will provide information about laptops visit that.most of the people want to buy a new model laptops but that laptops are not much better so this link helpful that type of people.
    =============
    koyali

    Laptop Computers
Sign In or Register to comment.