Shop OBEX P1 Docs P2 Docs Learn Events
code?? — Parallax Forums

code??

WaldoDTDWaldoDTD Posts: 142
edited 2005-08-31 16:36 in General Discussion
Hello,
I have a program that sends control signals to a com port will this code work for the stamp so that all i have to do is turn it and the computer on and run the program on the computer that sends the signals to the stamp?

//Adam Brooks' Hack
import stamp.core.*;

public class Wintermute_Mrk_I {

static PWM servo1 = new PWM(CPU.pin12,173,2304);
static PWM servo2 = new PWM(CPU.pin13,173,2304);

public static void helpMessage() {
System.out.println("Valid commands are:");
System.out.println(" help - print this message");
System.out.println(" r1 - right servo 1");
System.out.println(" c1 - center servo 1");
System.out.println(" r2 - right servo 2");
System.out.println(" c2 - center servo 2");
}

public static void prompt() {
System.out.print("\n> ");
}

public static void main() {

while ( true ) {
char data;
StringBuffer cmd = new StringBuffer(20);
prompt();
while ( (data = Terminal.getChar()) != '\r' ) {
cmd.append(data);
}
System.out.print('\n');

if ( cmd.equals("help") ) {
helpMessage();
}
else if (cmd.equals("r1") ) {
servo1.update(64,2304);
}
else if (cmd.equals("c1") ) {
servo1.update(173,2304);
}
else if (cmd.equals("r2") ) {
servo2.update(64,2304);
}
else if (cmd.equals("c2") ) {
servo2.update(173,2304);
}
else {
System.out.print("\nUnknown command: ");
System.out.println(cmd.toString());
}


cmd.clear();
}
}
}
«1

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-01 22:33
    That won't work using the Javelin programming port.

    You must use·a receive and transmit Uart on two I/O pins.

    The programming port puts out additional meta-databytes

    and also cannot receive at will (that is, the PC may only

    send a byte after it received a byte of value 0x12).

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-03 20:39
    Wait didn't you write a program for this using two pins with uart classes in a previous topic for me? Would this program be loaded on to the javelin or adapted to a program on the computer that i am using to communicate to the javelin? The javelin in my project is a servo controller for a program that i am modding which is written in java. I would like to know if this program should be adapted to the programming on the computer end or the microcontroller end. Thanks-Adam
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-03 21:09
    Yes, you could use the programming port BUT ONLY if you have

    the ability to change the PC program. That PC program

    must act according to·the Javelin protocol.

    The main() in the file you attached would be part of the mainloop of your PC program.



    The other thing you must be aware of is that if you exit your PC program, the Javelin

    will wait forever for a byte from the JIDE port. In my experience you can better disconnect

    the cable from the JIDE port. Then there is a chance the Javelin merely times out on the JIDE port.

    For that reason you really should have a blinking led on the javelin identifying the mainloop

    is still executed. If that led stops blinking, the javelin waits for a byte from the JIDE port.

    Then simply reconnect the cable and let the PC program send the 'no data' character.

    So your PC program better has a button just to send that character.



    regards peter
    ·
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-04 16:57
    i assume the sendbyte is the COMM API in the second main method for the pc.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-04 17:05
    Yes.

    sendByte(), byteAvailable() and receiveByte() must be replaced when

    using the protocol on a PC program by appropiate PC routines.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-04 22:05
    will i have to do anything special to the data being transmitted like encode it or can i send regular characters like r and c and not having to worry about hexadecimal numbers.-Adam
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-04 22:49
    The PC program must wait to receive 0x11 from the Javelin,
    then if the PC·has data, it must send 0x12 followed by 1·databyte,
    otherwise it must send 0x13 (as defined by the protocol).

    On the Javelin you use
    if (Terminal.byteAvailable()) {
    · char c = Terminal.getChar();
    }

    c can have any value from 0x00 to 0xFF
    Best to have a unique value that is never data to synchronize,
    eg. if 0xFE cannot be a databyte, start messages/commands with 0xFE.
    If all values can be databytes, you could use bytestuffing. Then it would
    make sense to use the Javelin protocol (which is bytestuffed)·to send
    the PC data to the Javelin.

    regards peter
    ·
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-04 22:54
    so the program must first wait for 0x11 then it sends 0x12 to start transmission then it has to send the databyte, and then repeat for each databyte. Do i have to change from char to databyte? If so how would i go about doing that?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-04 23:05
    The method receiveTask() tells it all:

    · static void receiveTask(char ch) {
    ··· switch (state) {
    ····· case 0:· //no special chars received
    ·············· if (ch == 0x0F) { //first char after reset
    ················ state = 10;
    ················ break;
    ·············· }
    ·············· if (ch == 0x05) { //start of message
    ················ state = 20;
    ················ break;
    ·············· }
    ·············· if (ch == 0x11) { //javelin requests data
    ················ if (cmd) {
    ·················· SendByte((char)0x12);
    ·················· if (index == cmdlen) {
    ···················· SendByte((char)0x0D); //append CR,LF to end of command
    ···················· index++;
    ·················· }
    ·················· else if (index == cmdlen + 1) {
    ························· SendByte((char)0x0A);
    ························· cmd = false;
    ························· index = 0;
    ························· cmdlen = 0;
    ······················· }
    ······················· else {
    ························· SendByte(cmdbuf[noparse][[/noparse]index++]); //transmit next byte from cmdbuf
    ······················· }
    ················ }
    ················ else {
    ·················· SendByte((char)0x13); //reply with 'No data to send'
    ················ }
    ·············· }
    ·············· break;
    ····· case 10: //0x0F received
    ·············· state = 0; //ignore char following 0x0F
    ·············· break;
    ····· case 20: //0x05 received
    ·············· if (ch == 0x03) {·· //message header
    ················ state = 30;
    ················ break;
    ·············· }
    ·············· if (ch == 0x05) {·· //end of program
    ················ state = 40;
    ················ break;
    ·············· }
    ·············· state = 0;
    ·············· break;
    ····· case 30: //0x05 0x03 received
    ·············· if (ch == 0x7F) state = 31;· //bytestuffed char
    ·············· else {
    ················ if (ch == 0x7E) {
    ·················· state = 0; //end of message
    ················ }
    ················ else {
    ·················· DisplayChar(ch);
    ················ }
    ·············· }
    ·············· break;
    ····· case 31: //0x7F in messagedata
    ·············· ch = (char)(ch ^ 0x20); //ch = (<b>^0x20) ^ 0x20 = <b>
    ·············· DisplayChar(ch);
    ·············· state = 30;
    ·············· break;
    ····· case 40: //0x05 0x05 received
    ·············· state = 0; //ignore char following 0x05 0x05
    ·············· break;
    ····· default: state = 0;
    ·············· break;
    ··· }
    · }

    Important to note: this method assumes there is a buffer holding bytes that together
    are regarded a single command. After the last byte has been transmitted, 0x0A,0x0D is appended
    (CR,LF) because it is set up to transmit text only (You could have commands r1, c2 etc).
    The javelin would recognize CR,LF as the end of a commandstring. No need for bytestuffing this
    way. But 0x0A and 0x0D cannot be databytes.

    regards peter

    ·
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-04 23:22
    Here is the description of the Javelin protocol.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-05 05:48
    ok would this work instead for the program interface with the javelin stamp? (not in final form just a rough thought experiment with bytes added in)
    program identifies the COM port
    program sets the buffer sizes for I/O
    program loops until it recieves byte 0x11 and then breaks
    program stores each "control signals" (r,c,x in that form not in hex) in the buffer
    program xmits one by one
    program goes back to top loop
    program breaks if a button is pressed in the GUI
    program xmits 0x05
    program closes the port

    Post Edited (Hacker) : 8/5/2005 5:51:05 AM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-05 08:21
    No. The PC may only send 1 byte after it receives 0x11.
    To send another byte, it must wait again for·0x11.

    You really should try out my JideWin_Terminal program
    First download JideTerm_protocol_test.java to the Javelin.
    Leave the programming cable connected.
    Close the Javelin IDE program.
    Run "JideWin Terminal.exe"
    Select com port Javelin is connected to.
    Click Start
    Enter any command in the command box.
    While you do not·click Send, JideWin Terminal transmits 'no data' character to Javelin
    when Javelin requests data. Once you click Send, all the characters from the command
    box are send to the Javelin when the Javelin requests data.
    One the Javelin has assembled a command, the javelin sends the command back to the
    PC with a leading CMD:
    So you can send commands like r1, c1, x, etc
    You can also store those commands in a file and send that file to the javelin.
    Each line in the file is a command and thus the file contents will show in the message
    display.
    The JideWin Terminal program implements the Javelin protocol exactly as discussed.

    regards peter
    <!-- Edit -->
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-05 16:12
    ok so it has to recieve 0x11 before it sends a byte, then it closes the connection by sending 0x05 right?-Adam
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-05 16:26
    also when i try to load it on the stamp it says that there is no such thing as stamp.util.text and it can't find the format method.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-05 19:18
    No, after you send the byte (actually 2 bytes, 0x12 followed by the databyte) you

    simply wait for the next byte from the javelin.

    The Format class can be found here:

    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/util/text/

    Place the class in folder lib/stamp/util/text

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-05 21:35
    ok so a sample of the actual byte exchange would be 0x11 (from stamp), 0x12(from program), r (from program), 0x11 (from stamp), 0x05 (from program)

    Post Edited (Hacker) : 8/5/2005 9:38:18 PM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-05 22:06
    No,

    The PC program never sends 0x05. It responds to a received 0x11 with either 0x13 or

    with 0x12 <byte>.

    Again, the protocol:

    Debug messages sent from the Javelin conform to the following pattern:

    0x05 0x03 <messagedata> 0x7E

    <messagedata> is the sequence of bytes being sent by the CPU.message() native method. It is byte-stuffed. This means that if <messagedata> contains a byte <b> that has the value 0x7F or 0x7E then that byte is replaced with 0x7F <b>^0x20. i.e. 0x7F followed by the orginal byte xored with 0x20.

    Terminal characters are sent to the Javelin using the following algorithm:
    1. When it is ready to receive a byte (the Terminal.getByte() native method is called) the Javelin transmits 0x11 out Sout.
    2. If the terminal has no data to send to the Javelin it replies with 0x13.
    3. If the terminal has a byte <b> to send, then it replies with 0x12 <b>.

    After the Javelin is reset it send 0x0F followed a pause followed by 0x50 (the version of the Javelin firmware).

    Running the following simple program:

    public class HelloWorld { public static void main() { System.out.println("Hello World"); } }

    will generate the following on Sout:

    0F 50 05 03 48 65 6C 6C 6F 20 57 6F 72 6C 64 7E 05 03 0D 0A 7E 05 05 7E

    Note that the sequence 0x05 0x05 0x7E indicates that the Java program has ended.


    The PC program never closes transmission or whatever. It merely responds to bytes received
    from the Javelin.

    regards peter
    ·
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-05 22:49
    so a standard control signal would be 0x12 0x72 from the program after it recieves 0x11

    Post Edited (Hacker) : 8/5/2005 11:02:45 PM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-05 23:05
    yes!

    The byte received (= returned by Terminal.getChar()) will then be 0x72 (= 'r')

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-06 00:34
    Would this work for the main method for the javelin?

    static void main() {
    char ch;
    Format.printf("JideTerm protocol test program\n");
    while (true) {
    //perform terminal task
    if (Terminal.byteAvailable()) {
    ch = Terminal.getChar();
    assembleCommand(ch);
    if (cmd) {
    Format.printf("CMD: %s\n",buf);
    cmd = false;
    index = 0;
    }
    }
    if (buf.equals(0x72) ) {
    servo1.update(64,2304);
    }
    if (buf.equals(0x63) ) {
    servo1.update(173,2304);
    }

    }
    }
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-06 03:40
    assembleCommand() stores received bytes until 0x0D ( = CR) is received.

    Then cmd will be true. If your PC only sends single byte commands (eg. 'r' or 'c')

    then you can simplify things.

    ·· static void main() {
    ··· char ch;
    ··· Format.printf("JideTerm protocol test program\n");
    ··· while (true) {
    ····· //perform terminal task
    ····· if (Terminal.byteAvailable()) {
    ······· ch = Terminal.getChar();
    ······· switch (ch) {
    ········· case 'r': servo1.update(64,2304);
    ··················· break;
    ········· case 'c': servo1.update(173,2304);
    ··················· break;
    ········· default:· //put error handling here
    ······· }
    ····· }
    ····· //perform other tasks
    ··· }
    · }

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-06 22:49
    Could it be possible to see how the program sends the different commands that have been input from the terminal in JideWinTerm? I am having trouble figuring out how to transmit the characters from the array one by one. Thanks!-Adam
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-06 23:50
    You wait for 0x11, then transmit 0x12 'r'.

    Then, again you wait for 0x11, then transmit 0x12 'c'.

    In other words: you wait for 0x11, then transmit 0x12 and one databyte.

    go here

    ·http://groups.yahoo.com/group/JavelinCode/files/JideTerm/

    and download JideTerm_1_2.zip.

    That is the commandline version of JideWin_terminal.

    In the file main.c you find the receiveTask() statemachine again (as in the JideTerm_protocol.java file)

    Actually, receiveTask() already shows it. Look at·when state == 0 (the case 0[noparse]:)[/noparse]

    and when ch == 0x11. There you'll see the bytes stored in the buffer (eg. the command)

    are transmitted one at a time, after 0x11 is received.

    ····· case 0:· //no special chars received
    ·············· if (ch == 0x0F) { //first char after reset
    ················ state = 10;
    ················ break;
    ·············· }
    ·············· if (ch == 0x05) { //start of message
    ················ state = 20;
    ················ break;
    ·············· }

    ······ //Here starts the part that transmits the command bytes
    ·············· if (ch == 0x11) { //javelin requests data
    ················ if (cmd) {
    ·················· SendByte((char)0x12);
    ·················· if (index == cmdlen) {
    ···················· SendByte((char)0x0D); //append CR,LF to end of command
    ···················· index++;
    ·················· }
    ·················· else if (index == cmdlen + 1) {
    ························· SendByte((char)0x0A);
    ························· cmd = false;
    ························· index = 0;
    ························· cmdlen = 0;
    ······················· }
    ······················· else {
    ························· SendByte(cmdbuf[noparse][[/noparse]index++]); //transmit next byte from cmdbuf
    ······················· }
    ················ }
    ················ else {
    ·················· SendByte((char)0x13); //reply with 'No data to send'
    ················ }
    ·············· }
    ·············· break;

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-07 15:26
    I think that that best translates into the Java COMM API like this, I am not sure though the name of the array that holds the bytes is called notes but most of the other variables are the same, Sendbyte() has also been replaced by outputstream.write().

    if (inputStream.available() > 0) {
    cmd = true;
    }
    try {
    while (inputStream.available() > 0) {
    if (readBuffer == 0x11){//javilen requests stuff
    if (cmd){
    outputStream.write((notes)0x12.getBytes());
    if (index == cmdlen){
    outputStream.write((notes)0x0D);
    index++;
    }
    else if (index == cmdlen + 1) {
    outputStream.write((notes)0x0A);
    cmd = false;
    index = 0;
    cmdlen = 0;
    }
    else {
    outputStream.write(notes [noparse][[/noparse]index++]);//transmit next byte from notes
    }
    }
    else {
    outputStream.write((notes)0x13); //reply with 'No data to send'
    }
    }
    break;
    }

    } catch (IOException e) {}

    break;
    }
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-16 04:15
    quick question, if the program is supposed to transmit 0x12 data, then shouldn't this line be outputStream.write(0x12(notes).outputStream); instead of outputStream.write((notes)0x12.outputStream);?
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-27 14:23
    Um, what are the purposes of sending 0x0A and 0x0D?
  • Chris SavageChris Savage Parallax Engineering Posts: 14,406
    edited 2005-08-27 17:13
    Hacker,

    ·· Typically that's a linefeed (LF) and carriage return (CR).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Chris Savage
    Parallax Tech Support
    csavage@parallax.com
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-27 19:40
    If to send contol signals you have to send 0x12 first then followed by the signal, (signals in here is a string variable) would it not be to have (0x12(signals)); instead of below? Also what would purpose be to send the same byte signal again to the stamp when you transmit 0x0D the carriage return? Thanks-Hacker

    while (inputStream.available() > 0) {
    if (readBuffer == 0x11){//javilen requests stuff
    if (cmd){
    outputStream.write((signals)0x12);
    if (index == cmdlen){
    outputStream.write((signals)0x0D);
    index++;
    }
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2005-08-27 21:19
    Hacker,

    I get the feeling you don't quite understand the javelin protocol.

    When your javelin program calls Terminal.getChar() then the javelin transmits

    0x11. The pc program must respond, and there are only 2 responses possible.

    Either the pc program responds with 0x13 (no data to send) or it responds

    with 0x12, followed by a single data byte. This data byte is the value returned

    by the Terminal.getChar() method.

    In my pc code, I attach a CR (0x0D) and LF (0x0A) to each message the pc

    sends to the javelin. This is arbitrary, but allows the javelin program to recognize

    the end of messages (my messages consists of printable characters only).

    You could also use other techniques, like fixed size messages.

    In the most simple form a message would consist of a single byte.

    In case a message consists of multiple bytes, the pc must wait for 0x11, before

    it sends ONLY 1 BYTE of the message, and that for each byte of the message.

    regards peter
  • WaldoDTDWaldoDTD Posts: 142
    edited 2005-08-29 16:33
    So would this follow the protocol? I understand the protocol but I am unsure how to attach the Line Feed and Carriage Return signals.
    try {
    while (inputStream.available() > 0) {
    if (readBuffer == 0x11){//javilen requests stuff
    while (st.hasMoreTokens()){
    outputStream.write(0x12(st.nextToken()));
    if (index == cmdlen){
    outputStream.write(0x0D);
    index++;
    }
    else if (index == cmdlen + 1) {
    outputStream.write(0x0A);
    cmd = false;
    index = 0;
    cmdlen = 0;
    }
Sign In or Register to comment.