Shop OBEX P1 Docs P2 Docs Learn Events
Open Propeller Project #1: iPad to ActivityBot - Page 8 — Parallax Forums

Open Propeller Project #1: iPad to ActivityBot

15681011

Comments

  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-01-31 06:19
    Brian, Tom and Steve thanks for the C examples I have really been wanting to try this with C code and will try them all later today. I'm not completely new to C but its been so long since I really focused on it.

    @Tom, I thought about ASCII strings and it does have it's advantages and so does a fixed byte array. To change to ASCII strings would be quite easy, the TCP stuff has it's own little slot that could be modified to anything. One of the things I have at the back of my mind is simplicity and flexibilty, whoever uses this at the end of the day will not want something so complex they can't understand it thats why I went with 6 bytes in 6 bytes out. I think what I will do is create a duplicate of the existing source so that both methods can be tried, that way it can be decided at a later date which would be best.

    @Thomas, I hope your daughter is doing better. Family should always be our first priority and you have to work so you have money for your hobby goodies.

    Jeff
  • John AbshierJohn Abshier Posts: 1,116
    edited 2014-01-31 07:24
    All of my previous robots were if not easy, simple. They each had one microcontroller (BS2, ATMEL, Propeller). Now things are not as simple. What is the division of labor between the Propeller and the iPad? For example in a iPad drives the robot context, does the iPad send left and right motor speeds or something at a higher level like speed and radius of curvature or speed and angular velocity?

    Another thought. The Propeller needs to be able to know if it has lost comms and put the robot into a safe mode. Perhaps not very important for an Activity Bot, but critical for a QuadRover. One possible implementation would be to set a global variable to a value, say 5, every time a message is received from the iPad. Another cog would decrease the variable by 1 every second and shut the robot down if it ever reached 0.

    Time to do medical paperwork, taxes and get a dog license. Not near as fun as here.

    John Abshier
  • tdlivingstdlivings Posts: 437
    edited 2014-01-31 08:54
    @Thomas I also hope your daughter is doing better. Good Luck!

    @Brian
    When ever you want to watch for one thing like your 'X' char and then do something with the next char
    if you saw the 'X' already you need some sort of state machine. It can be as simple as a true false variable
    that you set if you saw an 'X' . Separate your code into getting the chars as they come in and then do something
    with the next char based on what you saw already or did not see.

    @Jeff
    The six bytes coming back to the iPad, what do you see those bytes being. For testing the WiFi concept I think it was
    just to test the send and receive of anything and the scaled Acell values were something to test with.
    Do you see them as a 6 byte message like my A6 message with the 6 data bytes meaning different things.

    @ John
    A heartbeat message is a good idea. Sometimes as simple as if I have not received a heartbeat message for 0,1 sec or even longer
    depends on how quick you need to recognize the loss of control.

    Tom
  • Brian_BBrian_B Posts: 841
    edited 2014-02-01 06:37
    Jeff,
    I figure if my code don't work ,it should at least look good (Red Green) . I have to be getting close to a working version.


    Brian
    
    #include "simpletools.h"
    #include "fdserial.h"
    fdserial  *xbee;
    fdserial  *term;
    int main(void)
    {
     
    
      xbee = fdserial_open(11,10,0,9600);              // start xbee Full duplex
      simpleterm_close();                              // shutdown SIDE simple serial
      term = (fdserial_open(31,30,0,115200));          // start term Full duplex 
      int x,ptr;
      int temp,element;
      int array[6];                                  // array to store data
      element = 6;                                   // byte of data to recieve
     
      fdserial_rxFlush(xbee);
      pause(2);
    
    
      while(1) {                                          // run forever
        if(fdserial_rxReady(xbee));{                        // is xbee ready
         x = -1;                                          // x marker to false
           x = fdserial_rxChar(xbee);
          
            if (x == 'W');{                               // is in char W
              
              for (ptr = 0;ptr < element; ptr++)          // repeat loop 6 times, advancing array index each time 
                temp = fdserial_rxTime(xbee,20);          // wait 20 ms to recieve byte
                   while(temp != -1){                  
                        array[ptr] = temp;                // if there is a byte ,store in array, otherwise move on 
                      }                                   // end 2nd while
                          
             }                                            // close  W if
    
             {    
               
              for (ptr = 0;ptr < element; ptr++)          // loop 6 times ,advancing array each time
                fdserial_txChar(xbee,array[ptr]);         // echo back data to xbee   
                fdserial_txChar(term,array[ptr]);         // send same data to PST for my enjoyment
             }     
          
        
       }                                                  // close first if
            
      }                                                  // close while(1);
     return 0 ; 
    }                                                    //  close main ;
    
    
  • dgatelydgately Posts: 1,623
    edited 2014-02-01 07:59
    Brian_B wrote: »
    
    #include "simpletools.h"
    #include "fdserial.h"
    fdserial  *xbee;
    fdserial  *term;
    int main(void)
    {
     
    
      xbee = fdserial_open(11,10,0,9600);              // start xbee Full duplex
      simpleterm_close();                              // shutdown SIDE simple serial
      term = (fdserial_open(31,30,0,115200));          // start term Full duplex 
      char x,ptr;
      char temp,element;
      char array[6];                                  // array to store data
      element = 6;                                   // byte of data to recieve
     
      fdserial_rxFlush(xbee);
      pause(2);
    
    
      while(1) {                                          // run forever
        if(fdserial_rxReady(xbee));{                        // is xbee ready
         x = -1;                                          // x marker to false
           x = fdserial_rxChar(xbee);
          
            if (x == 'W');{                               // is in char W
              
              for (ptr = 0;ptr < element; ptr++)          // repeat loop 6 times, advancing array index each time 
                temp = fdserial_rxTime(xbee,20);          // wait 20 ms to recieve byte
                   while(temp != -1){                  
                        array[ptr] = temp;                // if there is a byte ,store in array, otherwise move on 
                      }                                   // end 2nd while
                          
             }                                            // close  W if
    
             {    
               
              for (ptr = 0;ptr < element; ptr++)          // loop 6 times ,advancing array each time
                fdserial_txChar(xbee,array[ptr]);         // echo back data to xbee   
                fdserial_txChar(term,array[ptr]);         // send same data to PST for my enjoyment
             }     
          
        
       }                                                  // close first if
            
      }                                                  // close while(1);
     return 0 ; 
    }                                                    //  close main ;
    
    

    Well, you've kinda asked for a response, so take this as just my opinion...

    This line is incorrect and will not achieve what you thought it would:


    if(fdserial_rxReady(xbee));{ // is xbee ready


    The block of code following the if(___); will not be executed conditionally. The semicolon has created a null statement. Do this:


    if(fdserial_rxReady(xbee)) { // is xbee ready


    OR

    if(fdserial_rxReady(xbee)) // is xbee ready
    {


    Also, you've defined element & temp as chars which will work in your case but is unnecessary and may cause grief if you at some point need them to represent numbers larger than 255. 'ptr' is also defined as a char. If you are truly using ptr as a C pointer, which represents an address in memory, it needs to an integer (or whatever best represents memory addresses on the CPU you are building code for). A char can represent only 256 values (0-255, -127-127, etc...).

    On commenting the code, it's not about making it 'pretty'. The comments should provide information that is not evident to the reader. As an example stating "repeat loop 6 times" is not helpful. Firstly, you've made the loop execute 'element' number of times, which is a variable. If you change that variable, your comment is no longer correct. If there will never be a reason to change the number of loop executions, you don't need to use a variable and the number '20' is self-documenting.

    "}"s represent the end of a block in C. You should't need to comment "// close while(1)" and "close main". It seems like you are trying to comment every line of code, which is not the intent of good code documentation. The reader wants to know what your code is trying to achieve, not the execution details of a particular line of code. Comments like "// array to store data" tell the user nothing about what data the array will hold and naming the array variable 'array' is truly not helpful. You might call the array something like "xbee_data" or "xbeeData" or whatever you've chosen as your variable naming style. In fact, if you make all of the variable names meaningful, you won't need so many comments!


    Here's my redo, that should work and provides just useful comments:
    #include "simpletools.h"
    #include "fdserial.h"
    fdserial  *xbee;
    fdserial  *term;
    
    #define xbee_recieve_pin    11          // I prefer to define these so I can easily change them later
    #define xbee_transmit_pin   10          // I prefer to define these so I can easily change them later
    
    int main(void)
    {
        int i;                                 // iterator
        char x;                             // from xbee 1-byte buffer
        char xbee_data[6];                  // command buffer
    
        xbee  = fdserial_open(xbee_recieve_pin,xbee_transmit_pin,0,9600);
        simpleterm_close();                              // close old terminal connections, cause Jazzed said so!
        term  = (fdserial_open(31,30,0,115200));
        fdserial_rxFlush(xbee);                          // clear the xbee buffer, need to start 'anew'
        pause(100);                                      // pause 1/10 of a second (2ms) was not enough time
    
        while(1)                                         // run forever
        {
            if(fdserial_rxReady(xbee))                   // xbee sending us commands?
            {                                              
                if (fdserial_rxChar(xbee) == 'W')        // got specific command-byte?   
                {
                    for (i = 0; i < 6; i++)              // 6 characters in a command string, check them!
                    {
                        x = fdserial_rxTime(xbee,20);
                        if(x != -1)
                            xbee_data[i] = x;                // if there is a byte, store it, else move on 
                    }
                 }
                for (i = 0;i < 6; i++)                   // hopefully, there's 6 bytes stored...                
                {                                        //     if not, xbee gets garbage returned
                    fdserial_txChar(xbee,xbee_data[i]);      // echo back data to xbee   
                    fdserial_txChar(term,xbee_data[i]);      // send same data to PST for my enjoyment
                }           
            }        
        }
        return 0 ; 
    }
    

    Apologies for my own style inclusion... Use what you want from this.

    I recommend: http://www.cs.rochester.edu/u/brown/172/readings_texts/KR.pdf, though not sure if the University of Rochester should have put the whole text up, legally :cool:

    dgately
  • Brian_BBrian_B Posts: 841
    edited 2014-02-01 08:23
    dgately,
    Thanks a million !!! ,here is the version with a few tweaks to make it work. Now I can start using the data :)

    Brian

    #include "simpletools.h"
    #include "fdserial.h"
    fdserial  *xbee;
    fdserial  *term;
    
    #define xbee_recieve_pin    11                              // I prefer to define these so I can easily change them later
    #define xbee_transmit_pin   10                            // I prefer to define these so I can easily change them later
    int main(void)
    {
        int i;                                                            // iterator
        char x;                                                        // from xbee 1-byte buffer
        char xbee_data[6];                                              // command buffer
    
        xbee  = fdserial_open(xbee_recieve_pin,xbee_transmit_pin,0,9600);
        simpleterm_close();                                      // close old terminal connections, cause Jazzed said so!
        term  = (fdserial_open(31,30,0,115200));
        fdserial_rxFlush(xbee);                                 // clear the xbee buffer, need to start 'anew'
        pause(100);                                                // pause 1/10 of a second (2ms) was not enough time
     
        while(1)                                                      // run forever
        {
            if(fdserial_rxReady(xbee))                        // xbee sending us commands?
            {                                              
                if (fdserial_rxChar(xbee) == 'W')           // got specific command-byte?   
                {
                    for (i = 0; i < 6; i++)                        // 6 characters in a command string, check them!
                    {
                        x = fdserial_rxTime(xbee,20);
                        if(x != -1)
                             xbee_data[i] = x;                          // if there is a byte, store it, else move on 
                    }
                 }
                for (i = 0;i < 6; i++)                          // hopefully, there's 6 bytes stored...                
                {                                                    //     if not, xbee gets garbage returned
                    fdserial_txChar(xbee, xbee_data[i]);      // echo back data to xbee   
                    writeDec(term, xbee_data[i]); 
                    writeChar(term,13);                    // send same data to PST for my enjoyment 
                }           
            }       
        }   
        return 0 ; 
    }
    
    
  • dgatelydgately Posts: 1,623
    edited 2014-02-01 08:38
    Brian,

    The for loop that sends data back to the xbee and out to the terminal may encounter garbage bytes from un-initialized elements within the array. The for loop that builds the array executes just 6 times and there's no guarantee that it will receive 6 'good' bytes. You may want to change that loop to run as many times as needed to get 6 good bytes, with some sort of timeout, in case the connection is broken or disturbed. Then, if the array is not full or corrupted, you'll not want to echo it. At that point you may want to send an error code back to the xbee and to the terminal.
  • Brian_BBrian_B Posts: 841
    edited 2014-02-01 14:31
    Dgately,
    Yes I can already see the need for error checking ,this code operates the leds on the activity Bot and sends ping data back to the ipad. I see the data jumping around when a byte was missed.

    Thank you and everyone for all the help.


    Brian

    edit: added false X at end, help missed data.


    #include "simpletools.h"
    #include "fdserial.h"
    #include "ping.h"
    fdserial  *xbee;
    fdserial  *term;
    
    #define xbee_recieve_pin    11          // I prefer to define these so I can easily change them later
    #define xbee_transmit_pin   10
    #define LED1                26         // activity bot led on 26
    #define LED2                27         // activity bot led on 27
    #define LedCode1            17         // code from ipad to turn on led 1
    #define LedCode2            33         // code from ipad to turn on led 2
    #define LedCode3            49         // code from ipad to turn on led 1 and led 2                
    int main(void)
    {
        int i;                          // iterator
        char x;                             // from xbee 1-byte buffer
        char xBee_Data[6];                  // command buffer
    
        xbee  = fdserial_open(xbee_recieve_pin,xbee_transmit_pin,0,9600);
        simpleterm_close();                              // close old terminal connections
        term  = (fdserial_open(31,30,0,115200));
        fdserial_rxFlush(xbee);                          // clear the xbee buffer, need to start 'anew'
        pause(100);                                      // pause 1/10 of a second (2ms) was not enough time
    
        while(1)                                         // run forever
        {
            if(fdserial_rxReady(xbee))                   // xbee sending us commands?
            {                                              
                if (fdserial_rxChar(xbee) == 'W')        // got specific command-byte?   
                {
                    for (i = 0; i < 6; i++)              // 6 characters in a command string, check them!
                    {
                        x = fdserial_rxTime(xbee,20);
                        if(x != -1)
                            xBee_Data[i] = x;                // if there is a byte, store it, else move on 
                    }
                 }
                    switch(xBee_Data[0]){                  // check data from proper char for controlling leds
                       case LedCode1:
                         high(LED1);
                         low(LED2);
                         break;
                       case LedCode2:
                         high(LED2);
                         low(LED1);
                         break;
                       case LedCode3:
                         high(LED1);
                         high(LED2);
                         break;
                       default:
                         low(LED1);
                         low(LED2);
                  } 
                      
               {
                    xBee_Data[3] = ping_inches(4);        //  read ping and insert in proper char to send back to ipad
               }   
                for (i = 0;i < 6; i++)                   // hopefully, there's 6 bytes stored...                
                {                                        //     if not, xbee gets garbage returned
                    fdserial_txChar(xbee,xBee_Data[i]);      // echo back data to xbee   
                    writeDec(term,xBee_Data[i]); 
                    writeChar(term,13);                    // send same data to PST for my enjoyment
                }  
                    writeChar(term,1);                    // cursor home on PST
                    x  = -1;                                    // one byte buffer set to false   
           }       
    
       }    
        return 0 ; 
    }
    
    
    1024 x 768 - 92K
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-01 19:14
    Brian, any spare time I have had has been spent trying to iron out the error handling routines of techBasic so getting involved with the C side of things had been put on the back burner

    Tonight I copied your code and pasted it into SimpleIDE, it was my first time using SimpleIDE so I was pleasantly surprised when everthing behaved like it should. As for the code you and dgately have provided it's awesome.

    Error handling at the bot end has been mentioned by John ( a heartbeat ) and dgately ( a checksum ) so tomorrow I am going to add a checksum and store it in byte 6.

    It is a very simple checksum so if there are any better ideas we can look at them but for now this is where I am headed. Both the Bot and the iPad will use the same method.

    The array of bytes to be transmitted are summed and the low byte is subtracted from $FF the result is the checksum.

    The low byte of the received bytes when summed, thats the data plus the checksum, should equate to $FF.

    I am attaching an updated source for techBasic which, with preliminary testing, deals with

    A bad IP or Port
    No wifi connection
    Loss of wifi comms
    Loss of Bot comms

    The app stays responsive and recoverable.

    Jeff
  • Brian_BBrian_B Posts: 841
    edited 2014-02-01 19:59
    Jeff,
    Thanks' , that code was definitely a group effort, I'll keep plugging away at the actBot side of this. Here is the same code, but cleaned up a little. I will start testing your new code tomorrow.


    Brian

    Edit : clear array
    #include "simpletools.h"
    #include "fdserial.h"
    #include "ping.h"
    #include "abdrive.h"
    fdserial  *xbee;
    fdserial  *term;
    
    #define xbee_recieve_pin    11         // I prefer to define these so I can easily change them later
    #define xbee_transmit_pin   10
    #define LED1                0          //  select activity bot led 1 pin
    #define LED2                6          // select  activity bot led 2 pin
    #define LedCode1            17         // code from ipad to turn on led 1
    #define LedCode2            33         // code from ipad to turn on led 2
    #define LedCode3            49         // code from ipad to turn on led 1 and led 2
    #define PingPin             4          // ping pin
    #define LedData             0          // byte for led data
    #define AccelXdata          1          // byte for accel x data
    #define AccelYdata          2          // byte for accel y data
    #define PingData            3          // byte for sending ping data 
    #define UserData1           4          // byte for user data
    #define CheckSum            5          // byte for checksum
                                                       
    int main(void)
    {
        int i;                                           // iterator
        char x ;
        char Ay,Ax;                                          // from xbee 1-byte buffer
        char xBee_Data[6] = {0,0,0,0,0,0};                             // command buffer
    
        xbee  = fdserial_open(xbee_recieve_pin,xbee_transmit_pin,0,9600);
        
        simpleterm_close();                              // close old terminal connections
        term  = (fdserial_open(31,30,0,115200));
        fdserial_rxFlush(xbee);                          // clear the xbee buffer, need to start 'anew'
        pause(100);                                      // pause 1/10 of a second (2ms) was not enough time
    
        while(1)                                         // run forever
        {
            if(fdserial_rxReady(xbee))                   // xbee sending us commands?
            {                                              
                if (fdserial_rxChar(xbee) == 'W')        // got specific command-byte?   
                {
                    for (i = 0; i < 6; i++)              // 6 characters in a command string, check them!
                    {
                        x = fdserial_rxTime(xbee,20);
                        if(x != -1)
                            xBee_Data[i] = x;                // if there is a byte, store it, else move on 
                    }
                 }
                    switch(xBee_Data[LedData]){                  // check data from proper char for controlling leds
                       case LedCode1:
                         high(LED1);
                         low(LED2);
                         break;
                       case LedCode2:
                         high(LED2);
                         low(LED1);
                         break;
                       case LedCode3:
                         high(LED1);
                         high(LED2);
                         break;
                       default:
                         low(LED1);
                         low(LED2);
                                                  }
    
                       Ax = (xBee_Data[AccelXdata]);                  // getting drive data ready ,will expand latter  
                       Ay = (xBee_Data[AccelYdata]);                  
                    
                      
                      xBee_Data[PingData] = ping_inches(PingPin);        //  read ping and insert in proper char to send back to ipad
                
    
      
                for (i = 0;i < 6; i++)                                 // hopefully, there's 6 bytes stored...                
                {                                                      //     if not, xbee gets garbage returned
                    fdserial_txChar(xbee,xBee_Data[i]);                // echo back data to xbee   
                    writeDec(term,xBee_Data[i]); 
                    writeChar(term,CR);                               // send same data to PST for my enjoyment
                }  
                    writeChar(term,HOME);                             // cursor home on PST
            
                     x = -1;                                           // 1 byte buffer set to false
         }
     }   
        return 0 ; 
    }
    
    
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-03 19:43
    Hi, the wifi error handling in the techBasic appears to be working quite well.

    I have included a checksum in and a checksum out and set a few debug traps in the techBasic code, the Spin code and the C code.

    iPad to Spin is working exceptionally well, iPad to C has a few issues with the current C code.

    The receive part of the C code is working well with minimal errors, the transmit part has a higher rate of error. The C transmit/receive cycle is noticeably slower than the Spin file.

    I'd like to get Spin and C on par with each other if possible.

    Jeff
  • tdlivingstdlivings Posts: 437
    edited 2014-02-03 20:29
    Jeff
    When you say your getting errors with the C code do you mean checksum errors or unstable operation.
    The checksum I used in the message way is just the two's complement of the sum. Which will be the negative
    of the sum so when you add what is in the message to what you get from summing bytes you receive you should get zero.

    In the C code Brian last posted writing to the terminal in the for loop outputting the bytes could put some time between chars output
    as it takes time to write to the terminal. Just a thought

    I am continuing to work on the message method of having the iPad send command messages to the AB to execute.

    Tom
  • jazzedjazzed Posts: 11,803
    edited 2014-02-03 23:50
    I'd like to get Spin and C on par with each other if possible.


    Can you please post the relevant C and Spin fragments for comparison?
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-04 05:53
    Hi guys, the C code is the code from post #219 and the Spin is contained in the zip in post #203.

    The only thing different is that they don't contain the checksum calculation which I outlined in post #220.

    The checksum is working fine and does not give me any problems. The receive part of the C code will give a couple of checksum errors it is not too serious but not as reliable as the Spin.

    The biggest problem is the way the C program transmits the 6 byte array, I did a simple test to see if the correct value was being placed in it's respective element of the array and it failed frequently especially when the values were changing rapidly. I wasn't getting checksum errors so it appears it was filling the array with the wrong values and then calculating the checksum

    it not only shows at the iPad but also in the SimpleIDE terminal, the values coming into the terminal look good and steady the values going out get very erratic.

    I commented out the terminal stuff to see if that would make a difference and it did not help, I have not tried removing the "switch" or ping instructions yet.

    Hopefully I am missing something obvious that you guys can spot.

    Jeff
  • tdlivingstdlivings Posts: 437
    edited 2014-02-04 08:31
    In the Tech Basic code null event there are two back to back for loops. First you send a "W" and then the
    first for loop puts out 6 bytes and then right away the second for loop is getting 6 bytes. This depends on the other
    side sending back right away. It gives the C side no time to do anything with the bytes. Seems like it could get out
    of sync easily with the array index of where to put the bytes.
    One quick debug test might be to put some code between the two for loops to wait a bit of time say 100ms or more and see
    if you luck out and it stays in sync.
    Better long term
    If you want to use the letter "W" as a message id then the C code should send it back to you as well as the 6 bytes so you can
    watch for a "W" coming back from the C code after sending out the 6 bytes, then read the next 6 bytes into your array.
    Just eat any char they is not a "W" until you get one back

    Tom
  • jazzedjazzed Posts: 11,803
    edited 2014-02-04 09:05
    There is no C code in post #220 ... did you mean #221?

    Part of the issue could be that we use the Propeller Serial Terminal.spin code as the basis of fdserial in the simple libraries.

    Could you try Propeller Serial Terminal.spin in SPIN instead of FullDuplexSerial.spin for comparison?
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-04 10:23
    Hi, sorry Steve I meant post #219 for the C code. Yes when I get home I will try with PST.spin and I will try and give a more detailed explanation of what I am seeing.

    Tom, the second loop in techBasic which receives the data from the wifi blocks for as long as ~5 seconds after which it will close the connection so it must be receiving 6 bytes, if it were receiving more than 6 there would be sync problems which I am not seeing. I am seeing erratic behaviour on the IDE terminal of the transmitted data while the received data looks stable. I know this is a little vague right now but hopefully more to tell later.

    Jeff
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-04 15:54
    The "Parallax Serial Terminal.spin" ran without any check sum errors at either end, I let it run for a little over 20 minutes.

    I had an additional check with error counter at the iPad looking for a fixed value in byte(0) , the value in byte(0) remained fixed and never threw an error.

    I have attached the spin code I used, it's a modification of Brian's file.

    I am moving on to the C file and will post back with what I see.
    con
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000  
      TX_PIN        =  1
      RX_PIN        =  0
      MODE          = %0000                                 ' see FullDuplexSerial.spin for description
      BAUD          = 9600
        
    obj
          com : "Parallax Serial Terminal.spin"
          debug :  "Parallax Serial Terminal.spin" 
       
    var
       Byte chk
       Byte error
       Byte buffer[6]
       Byte ArrayIn[6]
      
    pub Main  | x 
    
       com.startrxtx(RX_PIN,TX_PIN,%0000,BAUD)
       debug.startrxtx( 31,30,%0000,BAUD)
      
       com.rxflush
        
         repeat
            
             x:=com.charin
                                      
             case  x
                "W" : get_data 
                   
     
    Pri get_data  | i                                              
       rxarray(0,@buffer,6)
    
            buffer[5] := $FF-(buffer[0]+ buffer[1]+ buffer[2]+  buffer[3]+ buffer[4])   ' Buffer[5] contains the checksum
    
       i:=0 
       repeat 6
           com.char(buffer[i])
          
              i ++
                    
    PUB RxArray (ms,stringptr,element_num) : Value | ptr , temp
    
      ptr:=0                            
      chk:=0
                                                  
       repeat   while  ptr < element_num 
          temp :=  com.charin   
              if temp == -1
             
                 quit      
           ArrayIn[ptr] :=  temp   
           ptr++
    
    
      ptr:=0
      
       repeat 6
           chk += buffer[ptr]
             
              ptr ++
              
      if chk<>255  
          DataOut
                                        
    byteMove(stringptr,@Arrayin,element_num)
    
                                
    PUB DataOut | x
    
               error+=1
               debug.dec(chk)
               debug.char(32)
               debug.dec(error)
               debug.char(32)
    

    Jeff
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-02-04 16:43
    Nothing to add here, except to say I can test any code this evening. I've been offline from this project for a couple of days, but tonight I have time. I can see that posters above have been rounding up the code so that'll help. It's always a bit challenging to find the latest code examples in these threads.
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-04 17:14
    Ken I recommend the Spin file and new images from post #203 but use the techBasic source from post #220. The source in #220 has some error checks built in, if you have the time check how the data flows back and forth from the Prop, does it look like everything is echoed back ok, is the responsiveness fairly fast.

    Also perhaps you can check out how the following errors are handled

    A bad IP or Port
    No wifi connection
    Loss of wifi comms
    Loss of Bot comms

    What we are looking at right now is an apparent difference between the C and Spin files, you could try the C source v the Spin and see if you can detect any difference.

    Jeff
  • jazzedjazzed Posts: 11,803
    edited 2014-02-04 17:57
    What we are looking at right now is an apparent difference between the C and Spin files, you could try the C source v the Spin and see if you can detect any difference.
    I don't have a clue why there would be any difference at the moment. As I understand it, the transmit is having trouble, but I'm not sure one can really tell from the way the C code is written.

    It bothers me that the C code is not checking for a valid packet before trying to send a response. There should at least be a checksum byte for sanity check like in the spin.

    Another item is that a sequence protocol could be used to ensure that all packets arrived safely. I'm too wiped out to suggest a good sequence protocol right now though.

    It should not be necessary to have this at the beginning of the while loop: if(fdserial_rxReady(xbee)) ... The follow on fdserial_rxChar(xbee) should work. You could also replace that with readChar(xbee).

    One thing that is being missed is that writeChar(xbee, char) can be used instead of fdserial_txChar(xbee, char). I doubt that will make any difference though.

    The reason to use readChar(xbee) and writeChar(xbee) would be if we wanted to try a different port driver ... some day.
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-04 19:23
    It should not be necessary to have this at the beginning of the while loop: if(fdserial_rxReady(xbee))

    I did wonder that and actually have it commented out
    There should at least be a checksum byte for sanity check like in the spin

    I have that and thats how I could measure the incoming to the C program. It did error but not beyond a level you could live with.

    SimpleIDE terminal displayed a fairly good incoming stream, there is something happening with the array the C code transmits that does not happen with the Spin example. I think I will create a second array and have one for receive and one for transmit and see if I get the same.
    Another item is that a sequence protocol could be used to ensure that all packets arrived safely

    I was trying to keep things as simple as possible but perhaps that is what will be needed.

    Jeff
  • tdlivingstdlivings Posts: 437
    edited 2014-02-04 19:51
    Here is a test program that uses my messaging concept from an earlier post.
    The concepts Jazzed is talking about are what the message concept is about.

    Pardon the code has gotten a bit into a test concepts only version.
    For testing concept and speed of sending and receiving and showin Jeff state maching
    in TB to receive a message protocall. The one I thought of today, probably many other ways

    By changing tpause in the TB code changes the pace but keep in mind Accell values are paced
    at 0.1 sec and TB Manual says not to do that to fast or iPad system will hang

    I am only using the case of an A6 message. The one with 6 data bytes.
    The C code has the other message parsing code but it will not be called by the
    Tech Basic code attached as the TB code only sends an A6 message and waits to receive an A6 message

    I put the iPad Accel values in the first three data bytes of the message and fixed values in the other three bytes.
    The TB code receive uses a simple state machine to get each byte.

    The top of the iPad screen will show the Accel values in floating point and then scalled the way Jeff does it and then
    what came back after a round trip out to the Activity Board wifi and back to iPad.

    Just above the Quit button are a good messages received count and a bad checksum messages count, which is an * until you
    get one. I have not in testing at 0.1 second pace up to 3000 messages.

    Since I do not use any images if you email yourself the TB text by coping the text and pasting it into an email you receive on your iPad
    You can then on the iPad again copy the text in the received email and paste it into a new program in Tech Basic and run it.

    For the C side unzip the attached zip file and open the project side file and build. If you open the terminal message data will zip by.
    I run it also without the terminal to just watch the message count.

    Tom
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-05 10:03
    @Tom, I have your C and techBasic source. Should the terminal be updating? I see the x,y,z values on the iPad what are the other 3 values? I agree with your thoughts on timing and trying to do things too fast, this has been in my mind from early on.

    I have something going with Brian's and dgately's C source now. I don't know if I was doing something wrong earlier or it was the if(fdserial_rxReady(xbee)) which I commented out, anyway the C source is running on par with the Spin now. Here it is with the checksum calc. The checksum is calculated but not yet used to do anything positive with the errors.
    #include "simpletools.h"
    #include "fdserial.h"
    #include "ping.h"
    fdserial  *xbee;
    fdserial  *term;
    
    #define xbee_recieve_pin    0          // I prefer to define these so I can easily change them later
    #define xbee_transmit_pin   1
    #define LED1                26         // activity bot led on 26
    #define LED2                27         // activity bot led on 27
    #define LedCode1            17         // code from ipad to turn on led 1
    #define LedCode2            33         // code from ipad to turn on led 2
    #define LedCode3            49         // code from ipad to turn on led 1 and led 2                
    int main(void)
    {
        int i;                              // iterator
        char err;                           // error counter
        char chksum;                        // checksum place holder
        char x;                             // from xbee 1-byte buffer
        char xBee_Data[6];                  // command buffer
    
        xbee  = fdserial_open(xbee_recieve_pin,xbee_transmit_pin,0,9600);
        simpleterm_close();                              // close old terminal connections
        term  = (fdserial_open(31,30,0,9600));
        fdserial_rxFlush(xbee);                          // clear the xbee buffer, need to start 'anew'
        pause(100);                                      // pause 1/10 of a second (2ms) was not enough time 
    
        err=0;
    
        while(1)                                         // run forever
       // {
           //if(fdserial_rxReady(xbee))                   // xbee sending us commands?
            {                                              
                if (fdserial_rxChar(xbee) == 'W')        // got specific command-byte?   
                {
                    chksum=0;
                   
                    for (i = 0; i < 6; i++)              // 6 characters in a command string, check them!
                    {
                        x = fdserial_rxTime(xbee,2);
                        if(x != -1)
                            xBee_Data[i] = x;                // if there is a byte, store it, else move on 
                            chksum += xBee_Data[i];          // sum the checksum as data is received 
                          writeDec(term,xBee_Data[i]); 
                          writeChar(term,32);   
                    }
                           writeDec(term,chksum);           // display the checksum value in the terminal
                           writeChar(term,32);
                            if (chksum != 255)              // if the checksum <> 255 then there is an error
                                err+=1;
                           writeDec(term,err);              // tally the errors and display them in the terminal
                           writeChar(term,13);
                        
             }
                    switch(xBee_Data[0]){                  // check data from proper char for controlling leds
                       case LedCode1:
                         high(LED1);
                         low(LED2);
                         break;
                       case LedCode2:
                         high(LED2);
                         low(LED1);
                         break;
                       case LedCode3:
                         high(LED1);
                         high(LED2);
                         break;
                       default:
                         low(LED1);
                         low(LED2);
                  } 
                      
               {
                    xBee_Data[3] = ping_inches(4);        //  read ping and insert in proper char to send back to ipad
               }   
    
            
    
    
    
                chksum=0;
                for (i = 0;i < 5; i++)                             
                {                                        
                         
                   chksum += xBee_Data[i];              
                                    
                }  
               xBee_Data[5]=255-chksum;                   // calculate the outgoing checksum in byte 6 (element 5)
    
    
    
    
                for (i = 0;i < 6; i++)                   // hopefully, there's 6 bytes stored...                
                {                                        //     if not, xbee gets garbage returned
                    fdserial_txChar(xbee,xBee_Data[i]);      // echo back data to xbee   
                    writeDec(term,xBee_Data[i]); 
                    writeChar(term,32);                    // send same data to PST for my enjoyment
                }  
                    writeChar(term,1);                    // cursor home on PST
                    x  = -1;                                    // one byte buffer set to false   
          // }       
    
       }    
        return 0 ; 
    }
    

    From my point of view there is not much more I can do with the iPad side until the inputs and outputs have been defined. I will post the latest source containing the checksum that matches the checksum in the above C code a little later.

    Jeff
  • tdlivingstdlivings Posts: 437
    edited 2014-02-05 10:47
    Jeff
    The other values to the right of the floating point Acell vaues are the byte result
    of using your scaling ( Ac() * 128) +127 for x,y,z. The first one is calculated on the iPad
    and sent out in the A6 message the last column of byte values on the right is what the
    C code sent back . They look the same to me indicating no issue in making the round trip
    out and back

    For the terminal it will show contents of message received data if the print statements are in and
    not commented out in the processing of A6 message. I only send A6 messages in this example so
    that is the only case the processing loop will execute.
    I comment out the print statements for letting it run awhile, no reason to fill the terminal window.
    case 0xA6:
           print("Message A6\n");
           ix++;       // Bump index past len byte of message
           for(int b=0;b<6;b++) {
            Sixbytes[b] = MsgBuffer[ix++];
           }
           SendMsgA6(0xA6,Sixbytes);
    
    
           for(int br=0;br<6;br++){
             print("$x ",Sixbytes[br]);
           }
           print("\n");     
           break;
     
    

    As a note I had it running at 50ms and it still worked but my Bluetooth keyboard disconnected thinking the iPad
    was off I guess. When I touched the Quit button on TB screen it still worked but I had to reconnect the keyboard
    as it was now off.
    Also the wifi led's on the Activity Board will pause, both go off for a second or so and I will see the message count
    jump several messages ahead instead of just one count but the good news is I do not get any errors .
    I am guessing someone's comm buffer fills up and it causes a hold.
    In case your thinking it I am not using any serial control RTS or CTS. Something just seems to pause and recover.
    My code does not seem to care, with that said today it will care LOL

    Tom
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-02-05 15:57
    tdlivings wrote: »
    Here is a test program that uses my messaging concept from an earlier post.
    The concepts Jazzed is talking about are what the message concept is about.

    Tom

    Hey Tom!

    I'm running your TB and C code [post 234] and I have a display like this on the iPad:

    photo.jpg


    And in the SIDE debug display I see this:

    Screen Shot 2014-02-05 at 3.58.59 PM.jpg


    Should I be seeing values after the *s showing the number of round trips?

    And for the terminal?

    From the iPad side, I'm not clear on how to activate the LEDs on P26-27.

    Update: I have the Ping))) value displaying in the SIDE terminal.

    Thanks!

    Ken Gracey
    1024 x 768 - 92K
  • tdlivingstdlivings Posts: 437
    edited 2014-02-05 16:07
    Ken
    EDIT2
    I JUST SAW IT, YOUR MIXING CODE SETS.
    You need to run my simpleide project with my TB code.
    In the picture your running different code in simpleide
    Also ip address as i mention below.


    It appears to not be connected.
    Check that the ip address in the TB code is the same as what you set up the XBEE for.
    I have a slight different one than Jeff, I was experimenting. The red and blue Led's on the
    Activity Board should be flashing if connected.
    Just need to edit the comm.openTCIP line in the TB code.

    I did not incorporate Jeff's TB code for testing message communication errors.

    Edit:
    The code you see for P26 and P27 Led's is part of a different TB app that I left in for a quick test of
    message sending speed. That is why I said I was only sending an A6 message in the TB code.
    It does show however how to do a simple case on an incoming message and use it the same as typing
    a char on a terminal to select an operation.

    I think the first post I did here on the message concept has the iPad switches that turn on the Led's by sending a A1 message
    Have to go check POST 207 is the code set that switches LED's on and off using messages. iPad gets nothing back it just sends
    messages as commands to AB. Terminal shows what came in. In that test the 6 byte A6 message is fixed data, I like looking at
    something I know what the message is suppose to contain.
    You can create a new project with that set of code and run it. Also need to change ip to yours
    Tom


    Tom
  • UnsoundcodeUnsoundcode Posts: 1,531
    edited 2014-02-05 18:45
    This is the techBasic with the checksum included and partners the C source in post #235

    If you don't yet have the images for this project they are in the zip attached to post #203

    Jeff
  • Ken GraceyKen Gracey Posts: 7,386
    edited 2014-02-05 22:04
    tdlivings wrote: »
    Ken
    EDIT2
    I JUST SAW IT, YOUR MIXING CODE SETS.
    You need to run my simpleide project with my TB code.
    In the picture your running different code in simpleide
    Also ip address as i mention below.

    Tom

    I ran the C and TB code from your post #234. The blue/red LEDs on the Propeller Activity Board were blinking so I assume the connection was established. Indeed, I had configured the XBee to have the same IP and port as the TB code used.

    But at this stage I see Jeff's code above supersedes what we're using, so I'll switch to that and report back.

    It's quite the process to get this whole connection working:

    - email the code to the iPad, copy and paste it into TechBASIC
    - connect the iPad to iTunes, drag any graphic files into it's directory
    - configure the XBee ad-hoc and set iP addresses the same in the TB software
    - load and run the code in the ActivityBot.

    And then, if it's all done right, we've got success!

    I have to admit, though, I'm pleasantly surprised that it's been so productive thanks to you guys. I assumed it would be nearly impossible to do anything like this with the iPad, but we've got a bi-directional serial framework, communication, and code for both ends.

    Ken Gracey
  • Brian_BBrian_B Posts: 841
    edited 2014-02-06 05:16
    I know this is not a big issue ,but I think we should all get on same page for pin assignment. I've change my setup to reflect Jeff's pin 1 and 0 xbee setup. I figure this setup is hard enough to get working without more confusion.


    Brian
Sign In or Register to comment.