Difference between revisions of "Changing SimpleMotion baud rate"

From Granite Devices Knowledge Wiki
Jump to: navigation, search
[checked revision][checked revision]
Line 4: Line 4:
  
 
<syntaxhighlight lang="C">
 
<syntaxhighlight lang="C">
int pbs=1000000;//new bus baud rate
+
/*
int slaveSMWatchdogTimeountMs=700;//adjustable in 10ms steps up to 8000 ms
+
Notes:
  
//open SM bus with default baud rate
+
This is a complete demo application to change SM bus baud rate with error handling.
smSetBaudrate(460800);
+
smhandle=smOpenBus("COM1");
+
  
//reduce timeout because as following commands are sent to address 0 (broadcast to all devices), they will not return anything, so they will just timeout
+
This demo requires SimpleMotion V2 library from GitHub that is dated 27th July 2018 (27.7.2018) or later.
smSetTimeout(50);
+
*/
  
//setup SM bus watchdog feature. when communication is timeouted, motor will be stopped and baudrate is reset to default
+
#include <stdio.h>
smSetParameter(smhandle,0,SMP_FAULT_BEHAVIOR,((slaveSMWatchdogTimeountMs/10)<<8)|1);
+
#include "simplemotion.h"
  
//change baudrate of all devices on the bus (by giving address 0). it is important to change all devices at once so no communication errors happen due to wrong speed devices on the bus.
+
//GLOBALS
smSetParameter(smhandle,0,SMP_BUS_SPEED,pbs);
+
smbus smhandle=-1; //SM bus handle (no requirement to be global, we're using it as global just to simplify this example)
 +
const char *SMBusDeviceName="FTDI0";
  
//reset errors that have come from above commands (SM library current version expects response from the commands even when they are broadcasted to address 0, thus it is expected not to give respose)
+
//simple function to test whether communication works to a range of slave devices.
resetCumulativeStatus(smhandle);
+
//returns smtrue if connection test passed and smfalse if any of devices didn't respond properly
 +
smbool TestConnection( int fromAddress, int toAddress )
 +
{
 +
    for(int i=fromAddress; i<=toAddress; i++)
 +
    {
 +
        smint32 serialNr;
 +
        if(smRead1Parameter(smhandle, i, SMP_SERIAL_NR, &serialNr ) != SM_OK)
 +
        {
 +
            return smfalse;//read failed
 +
        }
 +
    }
 +
    return smtrue;//all passed
 +
}
  
//set longer timeout, to make SM bus watchdog activate on error, set this value higher than slaveSMWatchdogTimeountMs
+
//open bus with custom baud rate. this can be called again to re-open bus if connection is lost at some point
smSetTimeout(1000);
+
//(i.e. if some communicating function timeouts and does not return SM_OK).
 +
//this function will return smtrue on success, smfalse on any error.
 +
smbool OpenBusWithCustomBaudrate()
 +
{
 +
    //new bus baud rate
 +
    const int pbs=1000000; //note: for FTDI USB chip based interfaces (i.e. SMV2USB and IONICUBE with USB connector, the max supported PBS is 3000000)
  
//reopen SM bus device with new speed
+
    //adjustable in 10ms steps up to 8000 ms
smCloseBus(smhandle);
+
    const int slaveSMWatchdogTimeountMs=700;
smSetBaudrate(pbs);
+
smhandle=smOpenBus("COM1");
+
  
//continue using bus at new speed normally.
+
    //this defines how low SM library will wait for slave device's response before
//keep in mind that new commands must be sent to bus at least with the rate defined by slaveSMWatchdogTimeountMs.
+
    //returing from a communicating function call (such as smSetParameter or smGetParameter).
//if any command fails to timeout, or by any other reason timeout occurs, then devices have reset to default speed  
+
    //Make sure to set this value higher than slaveSMWatchdogTimeountMs to have SM watchdog working properly.
//and reinitialization of the speed is needed.
+
    const int slaveResponseTimeoutMs=1000;
 +
 
 +
    //close bus first if it's been opened previously (if re-calling OpenBusWithCustomBaudrate)
 +
    if(smhandle>=0)
 +
        smCloseBus(smhandle);
 +
 
 +
    //open SM bus with default baud rate
 +
    smSetBaudrate(460800);
 +
    smhandle=smOpenBus(SMBusDeviceName);
 +
 
 +
    //test if bus open failed
 +
    if(smhandle<0)
 +
        return smfalse;//failed
 +
 
 +
    //setup SM bus watchdog feature for all slave devices.
 +
    //when communication is timeouted, motor will be stopped AND their baud rate will be reset to default so we can
 +
    //easliy re-connect to them.
 +
    smSetParameter(smhandle,0,SMP_FAULT_BEHAVIOR,((slaveSMWatchdogTimeountMs/10)<<8)|1);
 +
 
 +
    //set SM library-end timeout for any communicating command. this is longer than slaveSMWatchdogTimeountMs
 +
    //to ensure that slave baudrate will always reset if communication error happens (no valid response received
 +
    //that SM library can read)
 +
    smSetTimeout(slaveResponseTimeoutMs);
 +
 
 +
    //change baudrate of all devices on the bus (by giving address 0). it is important to change all devices at once so no communication errors happen due to some wrong baud rate devices on the bus.
 +
    smSetParameter(smhandle,0,SMP_BUS_SPEED,pbs);
 +
 
 +
    //reopen SM bus device with new baud rate
 +
    smCloseBus(smhandle);
 +
    smSetBaudrate(pbs);
 +
    smhandle=smOpenBus(SMBusDeviceName);
 +
 
 +
    //test if bus open failed
 +
    if(smhandle<0)
 +
        return smfalse;//failed
 +
 
 +
    //optional, but recommended: test that new baud rate works on each device on the bus
 +
    //i.e. it can be done by reading some variable from each of the bus devices, such as SMP_SERIAL_NR
 +
    return TestConnection( first slave device address, last slave device address );
 +
 
 +
    //after this function returns, continue using bus at new speed normally.
 +
    //keep in mind that new commands must be sent to bus at least with the rate defined by slaveSMWatchdogTimeountMs.
 +
    //if any command fails to timeout, or by any other reason timeout occurs, then devices have reset to default speed
 +
    //and reinitialization of the speed is needed.}
 +
}
 +
 
 +
//your SimpleMotion application
 +
int main()
 +
{
 +
    /*in your SM application, the code might  follow this kind pattern: */
 +
    smSetDebugOutput(SMDebugMid,stderr);
 +
 
 +
    if( OpenBusWithCustomBaudrate() == smfalse )
 +
    {
 +
        //handle error
 +
        printf("Can't open bus\n");
 +
        return 0;
 +
    }
 +
 
 +
    while(1)
 +
    {
 +
        //do some communication, anything
 +
 
 +
        smint32 deviceType;
 +
        int slaveAddress=enter some address here;
 +
        smRead1Parameter(smhandle, slaveAddress, SMP_DEVICE_TYPE, &deviceType );
 +
 
 +
        if(getCumulativeStatus(smhandle)!=SM_OK)
 +
        {
 +
            //some of above SM commands have failed.
 +
 
 +
            //handle error:
 +
            printf("SM error occurred, status %d\n", getCumulativeStatus(smhandle));
 +
            resetCumulativeStatus(smhandle);
 +
            //...
 +
 
 +
            //if this is happened due to the command timeout, then we know that bus baud rate has been reset to default in all
 +
            //slave devices thanks to SM watchdog.
 +
            //in this case, then call OpenBusWithCustomBaudrate BEFORE continuing communication
 +
            return 1;
 +
        }
 +
        else //read ok
 +
        {
 +
            //print result & quit demo app, in real app do something else maybe
 +
            printf("Read succeed, device type at address %d = %d\n", slaveAddress, deviceType);
 +
            smCloseBus(smhandle);
 +
            return 2;
 +
        }
 +
    }
 +
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  

Revision as of 12:12, 25 July 2018

RS485 based SimpleMotion V2 bus supports changing baud rate on the fly from the default 460800 PBS. The procedure in simplest form is done by writing new baudrate value into parameter SMP_BUS_SPEED, and after that closing and re-opening the bus with the same speed.

However, in addition it is recommended to setup watchdog feature that will reset bus baudrate to default in case of connection is lost and timeouted. Example:

/*
 Notes:
 
 This is a complete demo application to change SM bus baud rate with error handling.
 
 This demo requires SimpleMotion V2 library from GitHub that is dated 27th July 2018 (27.7.2018) or later.
*/
 
#include <stdio.h>
#include "simplemotion.h"
 
//GLOBALS
smbus smhandle=-1; //SM bus handle (no requirement to be global, we're using it as global just to simplify this example)
const char *SMBusDeviceName="FTDI0";
 
//simple function to test whether communication works to a range of slave devices.
//returns smtrue if connection test passed and smfalse if any of devices didn't respond properly
smbool TestConnection( int fromAddress, int toAddress )
{
    for(int i=fromAddress; i<=toAddress; i++)
    {
        smint32 serialNr;
        if(smRead1Parameter(smhandle, i, SMP_SERIAL_NR, &serialNr ) != SM_OK)
        {
            return smfalse;//read failed
        }
    }
    return smtrue;//all passed
}
 
//open bus with custom baud rate. this can be called again to re-open bus if connection is lost at some point
//(i.e. if some communicating function timeouts and does not return SM_OK).
//this function will return smtrue on success, smfalse on any error.
smbool OpenBusWithCustomBaudrate()
{
    //new bus baud rate
    const int pbs=1000000; //note: for FTDI USB chip based interfaces (i.e. SMV2USB and IONICUBE with USB connector, the max supported PBS is 3000000)
 
    //adjustable in 10ms steps up to 8000 ms
    const int slaveSMWatchdogTimeountMs=700;
 
    //this defines how low SM library will wait for slave device's response before
    //returing from a communicating function call (such as smSetParameter or smGetParameter).
    //Make sure to set this value higher than slaveSMWatchdogTimeountMs to have SM watchdog working properly.
    const int slaveResponseTimeoutMs=1000;
 
    //close bus first if it's been opened previously (if re-calling OpenBusWithCustomBaudrate)
    if(smhandle>=0)
        smCloseBus(smhandle);
 
    //open SM bus with default baud rate
    smSetBaudrate(460800);
    smhandle=smOpenBus(SMBusDeviceName);
 
    //test if bus open failed
    if(smhandle<0)
        return smfalse;//failed
 
    //setup SM bus watchdog feature for all slave devices.
    //when communication is timeouted, motor will be stopped AND their baud rate will be reset to default so we can
    //easliy re-connect to them.
    smSetParameter(smhandle,0,SMP_FAULT_BEHAVIOR,((slaveSMWatchdogTimeountMs/10)<<8)|1);
 
    //set SM library-end timeout for any communicating command. this is longer than slaveSMWatchdogTimeountMs
    //to ensure that slave baudrate will always reset if communication error happens (no valid response received
    //that SM library can read)
    smSetTimeout(slaveResponseTimeoutMs);
 
    //change baudrate of all devices on the bus (by giving address 0). it is important to change all devices at once so no communication errors happen due to some wrong baud rate devices on the bus.
    smSetParameter(smhandle,0,SMP_BUS_SPEED,pbs);
 
    //reopen SM bus device with new baud rate
    smCloseBus(smhandle);
    smSetBaudrate(pbs);
    smhandle=smOpenBus(SMBusDeviceName);
 
    //test if bus open failed
    if(smhandle<0)
        return smfalse;//failed
 
    //optional, but recommended: test that new baud rate works on each device on the bus
    //i.e. it can be done by reading some variable from each of the bus devices, such as SMP_SERIAL_NR
    return TestConnection( first slave device address, last slave device address );
 
    //after this function returns, continue using bus at new speed normally.
    //keep in mind that new commands must be sent to bus at least with the rate defined by slaveSMWatchdogTimeountMs.
    //if any command fails to timeout, or by any other reason timeout occurs, then devices have reset to default speed
    //and reinitialization of the speed is needed.}
}
 
//your SimpleMotion application
int main()
{
    /*in your SM application, the code might  follow this kind pattern: */
    smSetDebugOutput(SMDebugMid,stderr);
 
    if( OpenBusWithCustomBaudrate() == smfalse )
    {
        //handle error
        printf("Can't open bus\n");
        return 0;
    }
 
    while(1)
    {
        //do some communication, anything
 
        smint32 deviceType;
        int slaveAddress=enter some address here;
        smRead1Parameter(smhandle, slaveAddress, SMP_DEVICE_TYPE, &deviceType );
 
        if(getCumulativeStatus(smhandle)!=SM_OK)
        {
            //some of above SM commands have failed.
 
            //handle error:
            printf("SM error occurred, status %d\n", getCumulativeStatus(smhandle));
            resetCumulativeStatus(smhandle);
            //...
 
            //if this is happened due to the command timeout, then we know that bus baud rate has been reset to default in all
            //slave devices thanks to SM watchdog.
            //in this case, then call OpenBusWithCustomBaudrate BEFORE continuing communication
            return 1;
        }
        else //read ok
        {
            //print result & quit demo app, in real app do something else maybe
            printf("Read succeed, device type at address %d = %d\n", slaveAddress, deviceType);
            smCloseBus(smhandle);
            return 2;
        }
    }
}

Baud rate parameter behavior:

  • Newly set baud rate will stay active only when device stays on (logic voltage on and drive not restarted). Baud rate will always reset to default 460800 BPS if device is powered off/on.
  • If you setup the SimpleMotion watchdog has been set, then baud rate will also reset to default also if connection is lost for certain period of time. This is useful ensuring that you can re-connect again to the device with default baud rate and then re-do the baud date change procedure.