Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Serial communication issue

  1. Serial communication issue

    Hi all,

    I am currently working on a three joint robotic arm with MX64T,MX28T and AX12A used for joint 1, 2 and 3 respectively. I am using the Arbotix-M Robocontroller to control them.

    I am using a case structure for triggering different movements for the robotic arm. When I send the required data, it mostly works the first time. But if I try to repeat the same movement again, it doesn't act the same. For example, sometimes the MX64 on joint 1 reacts late and does not go to the initial position as it is meant to. Once that happens, I face different problems repeatedly.
    Also, at times the system completely acts weird and servos go into a position that was not even programmed to.It can then only be resolved by restarting the system (powering off and on again).

    I couldn't isolate the problem. So I tried using my motion algorithms into a new sketch without using case structures. I just tested a single motion algorithm in a loop using the Arbotix controller, and it seemed to work as required without any failures.

    So, I do not think it is a hardware problem and also cannot really the isolate the problem in my software. I have added the link to my code in this forum.

    https://www.dropbox.com/s/wmf26mgdgi3lfss/Integration_Test_NoCS_Problem.ino?dl=0

    Any help will be greatly appreciated. Thanks.

  2. #2
    Join Date
    Sep 2010
    Location
    ಠ_ಠ
    Posts
    2,313
    Images
    27
    Rep Power
    278

    Re: Serial communication issue

    Code:
    #define SetSpeedL(id, spdl) (ax12SetRegister2(id, AX_GOAL_SPEED_L, spdl))
    #define SetSpeedH(id, spdh) (ax12SetRegister2(id, AX_GOAL_SPEED_H, spdh))
    #define SetTorqueH(id, torh) (ax12SetRegister2(id, AX_MAX_TORQUE_H, torh))
    #define SetTorqueL(id, torl) (ax12SetRegister2(id, AX_MAX_TORQUE_L, torl))
    #define GetTemp(id) (ax12GetRegister(id, AX_PRESENT_TEMPERATURE, 2))
    #define SetTemp(id,lim)  (ax12SetRegister2(id, AX_LIMIT_TEMPERATURE, lim))
    #define SetShutdown(id,std)  (ax12SetRegister2(id, AX_ALARM_SHUTDOWN, std))
    #define SetD(id,der)  (ax12SetRegister2(id, AX_CW_COMPLIANCE_MARGIN, der))
    #define SetI(id,intg)  (ax12SetRegister2(id, AX_CCW_COMPLIANCE_MARGIN, intg))
    #define SetP(id,prp)  (ax12SetRegister2(id, AX_CW_COMPLIANCE_SLOPE, prp))
    should be
    Code:
    #define SetSpeed(id, spd) (ax12SetRegister2(id, AX_GOAL_SPEED_L, spd))
    #define SetTorque(id, tor) (ax12SetRegister2(id, AX_MAX_TORQUE_L, tor))
    #define GetTemp(id) (ax12GetRegister(id, AX_PRESENT_TEMPERATURE, 2))
    #define SetTemp(id,lim)  (ax12SetRegister(id, AX_LIMIT_TEMPERATURE, lim))
    #define SetShutdown(id,std)  (ax12SetRegister(id, AX_ALARM_SHUTDOWN, std))
    #define SetD(id,der)  (ax12SetRegister(id, AX_CW_COMPLIANCE_MARGIN, der))
    #define SetI(id,intg)  (ax12SetRegister(id, AX_CCW_COMPLIANCE_MARGIN, intg))
    #define SetP(id,prp)  (ax12SetRegister(id, AX_CW_COMPLIANCE_SLOPE, prp))
    and called as
    Code:
    // the setup routine runs once when you press reset:
    void setup() {                
      // initialize the digital pin as an output.
      pinMode(led, OUTPUT);     
    
      Serial.begin(9600);
    
      Relax(1);
      Relax(2);
      Relax(3); 
      delay(100);
    
      // Set Torque limit to max
      SetTorque(1,  0x3FF); 
      SetTorque(2,  0x3FF); 
      SetTorque(3,  0x3FF);
      delay(100);
    
      // Set Temperature Limit to Max
      SetTemp(1,0x50);
      SetTemp(2,0x50);
      SetTemp(3,0x46);
      delay(100);
    
      // Set Shutdown mode to default 
      SetShutdown(1,  0x24);
      SetShutdown(2,  0x24);
      SetShutdown(3,  0x24);
      delay(100);
    
      // Set initial speed in rpm
      SetSpeed(1,0x030);
      SetSpeed(2,0x030);
      SetSpeed(3,0x030);
      delay(100); 
    
      //SetP(1,0x50);
      //SetP(2,0x50);
      //SetI(1,0x02);
      //SetI(2,0x02);
    
      // Connect only when serial COM is available 
      while (Serial.available()==0)
      {
        ; // wait for serial port to connect.
      }
    
    }
    ax12SetRegister2() writes a full two-byte word starting at the lower address. You call it once with the 16-bit value and never call it with the high-byte address which will write the second byte into the next register (usually a low-byte address of some other parameter).
    ax12SetRegister() writes a single byte to only the desired address. It is used for single byte parameters like voltage, temperature, status return level, alarm shutdown, torque enable, CW compliance slope, CW compliance margin, etc.

  3. Re: Serial communication issue

    Thanks for the information tician.

    I have made all the changes that you mentioned, but I am still facing similar problems.

    In order to further investigate this problem, I tried using a single case structure test. I did two different tests.

    1. If 'A' is sent, the user LED on the Arbotix will light up for 'x' amount of time
    Code - https://www.dropbox.com/s/t82ohph6c4...t_LED.ino?dl=0

    2. If 'A' is sent, the robotic arm will perform a pre-set motion
    Code - https://www.dropbox.com/s/v4bj2k49qd...mTest.ino?dl=0

    I only did the test to simply the code structure and try to isolate the problem. Test 1 worked fine with LED. I repeated it several times and it worked as expected every single time. But with Test 2, the robotic arm movement wasn't as expected. It worked only the first time or a few times but trying to repeat the test caused the same problem. I can't really isolate if data is not being sent to the servos properly or is it getting confused. Then again, when I test the similar code on just a loop with the case structure, it doesn't cause any problem.

    Any help will be greatly appreciated. Thanks.

  4. #4
    Join Date
    Sep 2010
    Location
    ಠ_ಠ
    Posts
    2,313
    Images
    27
    Rep Power
    278

    Re: Serial communication issue

    Sounds like the power supply may be inadequate, but brown-outs tend to cause servos to reset to ID==1 when sending packets at relatively high rates.

    Also, you are sending 'double'-type variables to the SetPosition() functions, but they require 16-bit integer properly scaled to range of the servo. J1, J2, J3 should not be 'double'.

    Also also, the arbotix is 8-bit with no floating point, so expect slowness...
    Last edited by tician; 05-28-2015 at 08:00 AM.
    Please pardon the pedantry... and the profanity... and the convoluted speech pattern...
    "You have failed me, Brain!"
    [git][mech][hack]
    gives free advice only on public threads

  5. Re: Serial communication issue

    Quote Originally Posted by tician View Post
    Sounds like the power supply may be inadequate, but brown-outs tend to cause servos to reset to ID==1 when sending packets at relatively high rates.

    Also, you are sending 'double'-type variables to the SetPosition() functions, but they require 16-bit integer properly scaled to range of the servo. J1, J2, J3 should not be 'double'.

    Also also, the arbotix is 8-bit with no floating point, so expect slowness...
    I have changed the variables J1,J2 and J3 to integers.

    If the power supply was inadequate, would it not have affected the servos during testing in a loop?

    But the thing is that the algorithm does work properly in a normal sketch without the case structure and waiting for serial data. So my worry is if I have taken any wrong approach in sending data to the servos through the case structure? I am just wondering what the best step for me is to program the servos to perform all the required motions and to make the system robust with minimal failures.

    Any help will be greatly appreciated. Thanks.
    Last edited by navidahmeduom; 05-28-2015 at 10:09 AM.

  6. #6

    Re: Serial communication issue

    "switch" statements work as intended. However, you may not be using them correctly -- that's hard for us to figure out; you'll have to debug that.

    In general, to receive serial packets/commands, you'll want to be able to tell either when a packet starts, or when a packet ends. Using newline (ASCII value 10, '\n') for ending commands is often useful.

    Then, the receiving code will simply put data into a buffer, until it sees the terminator (or the buffer fills up) and then it will "run" the command. This lets the rest of the code stay entirely asynchronous.

    Code:
    char buf[100] = { 0 };
    int bufptr = 0;
    
    
    void loop()
    {
      while (Serial.available())
      {
        buf[bufptr] = Serial.read();
        ++bufptr;
        if (buf[bufptr-1] == '\n')
        {
          // got a valid command, turn it into a string and run it
          buf[bufptr-1] = 0;
          do_command(buf);
          bufptr = 0;
        }
        else if (bufptr == (int)sizeof(buf))
        {
          // overflow of input buffer
          bufptr = 0;
        }
      }
      ... do other loop stuff
    }
    
    
    void do_command(char const *str)
    {
      if (str[0] == 'A')
      { // an 'A' command
        int val = atoi(&str[1]); // read an integer
        ... do stuff
      }
      else if (str[0] == 'B')
      { // a 'B' command
        int a, b, c;
        int n = sscanf(str, "B%d,%d,%d", &a, &b, &c);
        if (n == 3)
        {
          // got three arguments: B1,2,3
          ... do B stuff ...
        }
        else
        {
          ... mal-formatted B command ...
        }
      }
      else
      {
        ... unknown command ... ignore it
      }
    }
    Last edited by jwatte; 05-28-2015 at 11:39 AM.

  7. Re: Serial communication issue

    Quote Originally Posted by jwatte View Post
    "switch" statements work as intended. However, you may not be using them correctly -- that's hard for us to figure out; you'll have to debug that.

    In general, to receive serial packets/commands, you'll want to be able to tell either when a packet starts, or when a packet ends. Using newline (ASCII value 10, '\n') for ending commands is often useful.

    Then, the receiving code will simply put data into a buffer, until it sees the terminator (or the buffer fills up) and then it will "run" the command. This lets the rest of the code stay entirely asynchronous.

    Code:
    char buf[100] = { 0 };
    int bufptr = 0;
    
    
    void loop()
    {
      while (Serial.available())
      {
        buf[bufptr] = Serial.read();
        ++bufptr;
        if (buf[bufptr-1] == '\n')
        {
          // got a valid command, turn it into a string and run it
          buf[bufptr-1] = 0;
          do_command(buf);
          bufptr = 0;
        }
        else if (bufptr == (int)sizeof(buf))
        {
          // overflow of input buffer
          bufptr = 0;
        }
      }
      ... do other loop stuff
    }
    
    
    void do_command(char const *str)
    {
      if (str[0] == 'A')
      { // an 'A' command
        int val = atoi(&str[1]); // read an integer
        ... do stuff
      }
      else if (str[0] == 'B')
      { // a 'B' command
        int a, b, c;
        int n = sscanf(str, "B%d,%d,%d", &a, &b, &c);
        if (n == 3)
        {
          // got three arguments: B1,2,3
          ... do B stuff ...
        }
        else
        {
          ... mal-formatted B command ...
        }
      }
      else
      {
        ... unknown command ... ignore it
      }
    }
    Thank you for the information jwatte.

    I understand what you are trying to say. But the main thing that is confusing to me is that the program works at least the first time when data is sent to it. It starts acting weird after a few times.

    For example, the response to serial data '150TC' will be appropiate the first time but if the same serial data is sent a second or a third time, the motion may not be executed as required. As an example, sometimes joint 1 may skip the initial step and only responds during the completion of the second step.

    That is why I was a bit confused. Is it a problem of the buffer not being emptied after execution of the first serial command? Or is the buffer of the servos that may be creating a problem? Or something else? It has been hard to isolate the problem, as the program works in running the LED on the Arbotix controller representing different sequence for different motion. So, my only thought was my communication method or speed to the servos may be causing some sort of problem.

    I do not know if I have been able to clarify the problem properly, but hopefully you will be able to provide further guidance.

    Any help will be greatly appreciated. Thanks.

  8. #8
    Join Date
    Sep 2010
    Location
    ಠ_ಠ
    Posts
    2,313
    Images
    27
    Rep Power
    278

    Re: Serial communication issue

    Where is the ax12 or BioloidController library being initialized?
    Do you really want to run through the switch() when you have received no new command into the buffer or not verified receipt of terminating '/r', or do you want to make it wait for a few hundred milliseconds and start the loop() over?
    Are you sure you are initializing all your variables prior to use?

    The best piece of advice I can give is to use as few global variables as possible and keep names useful. If you are not doing operations on very large arrays, then pass variables by value in the function call instead of continually modifying global variables.
    Please pardon the pedantry... and the profanity... and the convoluted speech pattern...
    "You have failed me, Brain!"
    [git][mech][hack]
    gives free advice only on public threads

  9. Re: Serial communication issue

    Quote Originally Posted by tician View Post
    Where is the ax12 or BioloidController library being initialized?
    Do you really want to run through the switch() when you have received no new command into the buffer or not verified receipt of terminating '/r', or do you want to make it wait for a few hundred milliseconds and start the loop() over?
    Are you sure you are initializing all your variables prior to use?

    The best piece of advice I can give is to use as few global variables as possible and keep names useful. If you are not doing operations on very large arrays, then pass variables by value in the function call instead of continually modifying global variables.
    All the libraries are being initialised at the start.

    The program should only run through the switch statements when it receives any serial data. But the loop keeps on waiting for serial data to trigger all the motion algorithms in the case structure.
    Most of my variables are initialised before the setup and loop as global variables. Do you think it will be better if I just initialise some of them as local variables within the case structures itself?
    I will try declaring my variables within the functions itself and give that a go and see if it was the problem.

  10. #10
    Join Date
    Sep 2010
    Location
    ಠ_ಠ
    Posts
    2,313
    Images
    27
    Rep Power
    278

    Re: Serial communication issue

    None of the code you posted calls ax12Init() or creates a BioloidController object that would call ax12Init().

    The code you posted will go to the switch() regardless of whether any data is received or available, let alone confirmed as valid and/or properly terminated. Not even a simple check on length of the string returned by readBytesUntil(). Nothing. This means there is no guarantee that the first character in the buffer will actually be the 'command' byte or an initial null instead of any non-command byte from a previous attempt that timed out or got corrupted.
    Please pardon the pedantry... and the profanity... and the convoluted speech pattern...
    "You have failed me, Brain!"
    [git][mech][hack]
    gives free advice only on public threads

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Arduino due Serial communication trouble
    By manu in forum Arbotix, Microcontrollers, Arduino
    Replies: 1
    Last Post: 08-27-2014, 11:34 AM
  2. Serial communication between Arduino and Arbotix
    By dburongarcia in forum Arbotix, Microcontrollers, Arduino
    Replies: 17
    Last Post: 03-09-2014, 12:44 PM
  3. Question(s) AX-12 controled by Serial communication
    By tailer in forum Arbotix, Microcontrollers, Arduino
    Replies: 3
    Last Post: 11-17-2012, 11:19 AM
  4. Question(s) RAW Serial Communication
    By ilo_oli in forum Software and Programming
    Replies: 5
    Last Post: 11-01-2011, 05:38 PM
  5. C++ Serial Communication
    By Resilient in forum Software and Programming
    Replies: 14
    Last Post: 02-03-2009, 03:23 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •