Generic Step Motor WebInterface - control a step motor using a Pololu A4983 driver from a webinterface (EXPERIMENTAL PROTOTYPE - just to be used as a proof-of-concept for a IoT talk, will not be updating this code so often)

Dependencies:   EthernetNetIf RPCInterface mbed HTTPServer

main.cpp

Committer:
botdream
Date:
2012-04-16
Revision:
0:8b3857d4ce02

File content as of revision 0:8b3857d4ce02:

/* //---------------------------------------------------------------------------------------------
// disable/enable auto-run
http://192.168.1.100/rpc/enable/write%200
http://192.168.1.100/rpc/enable/write%201

// normal/inverse direction
http://192.168.1.100/rpc/direction/write%200

// timer delay - motor speed
http://192.168.1.100/rpc/delay/write%200.00001 (default)
http://192.168.1.100/rpc/delay/write%200.0000025 (max)

http://192.168.1.100/rpc/delay/write%200.00048 (super slow)

// RPC number of steps
http://192.168.1.100/rpc/nsteps/run%2016 (16 microsteps => 1 step)
http://192.168.1.100/rpc/nsteps/run%203200 (200 Steps -> 360�)

// RPC StepCmd
http://192.168.1.100/rpc/stepcmd/run%201000%20100%201

// RPC StepMode
http://192.168.1.100/rpc/stepmode/run%200
http://192.168.1.100/rpc/stepmode/run%201

//Sleep mode
http://192.168.1.100/rpc/sleepmode/run%200
http://192.168.1.100/rpc/sleepmode/run%201

//---------------------------------------------------------------------------------------------
// resources
//---------------------------------------------------------------------------------------------
http://mbed.org/handbook/C-Data-Types
http://mbed.org/cookbook/RPC-Interface-Library
http://mbed.org/cookbook/HTTP-Server
http://mbed.org/cookbook/Ethernet
http://mbed.org/handbook/Ticker
//--------------------------------------------------------------------------------------------- */
#include "mbed.h"
#include "EthernetNetIf.h"
#include "HTTPServer.h"
#include "RPCVariable.h"
#include "RPCFunction.h"
#include "A4983.h"
// TListObjects units
#include "TList.h"
#include "TObjects.h"

//#include <memory>
//#include <vector>
//---------------------------------------------------------------------------------------------
// Defines - remove comments to enable special mode
//---------------------------------------------------------------------------------------------
#define internaldebug // send debug messages to USB Serial port (9600,1,N)
//#define dhcpenable    // auto-setup IP Address from DHCP router
//---------------------------------------------------------------------------------------------
// Ethernet Object Setup
//---------------------------------------------------------------------------------------------
#ifdef dhcpenable
  EthernetNetIf eth;  
#else
/*
  EthernetNetIf eth(
    IpAddr(192,168,0,100), //IP Address
    IpAddr(255,255,255,0), //Network Mask
    IpAddr(192,168,0,1),   //Gateway - Laptop sharing Internet via 3G
    IpAddr(208,67,220,220) //OpenDNS
  );
*/  
  EthernetNetIf eth(
    IpAddr(192,168,1,100), //IP Address
    IpAddr(255,255,255,0), //Network Mask
    IpAddr(192,168,1,254), //Gateway
    IpAddr(192,168,1,254)  //DNS
  );
#endif
//---------------------------------------------------------------------------------------------
// HTTP Server
//---------------------------------------------------------------------------------------------
HTTPServer svr;
LocalFileSystem fs("webfs");
//---------------------------------------------------------------------------------------------
// Misc
//---------------------------------------------------------------------------------------------

//---------------------------------------------------------------------------------------------
// Timer Interrupt - NetPool
//---------------------------------------------------------------------------------------------
Ticker netpool;
//---------------------------------------------------------------------------------------------
// auxiliar pointer - necessary for the rpc_nsteps(char *input, char *output) function
//---------------------------------------------------------------------------------------------
A4983 *p_stepmotor;
//---------------------------------------------------------------------------------------------
// temporary TList object
TList *pListPointer = NULL;
//---------------------------------------------------------------------------------------------

bool request_handle = false;

//#############################################################################################

//---------------------------------------------------------------------------------------------
// Pool Ethernet - will be triggered by netpool ticker
//---------------------------------------------------------------------------------------------
void netpoolupdate()
{
    Net::poll();
}
//---------------------------------------------------------------------------------------------
// RPC function
//---------------------------------------------------------------------------------------------
void rpc_nsteps(char *input, char *output)
{
  while(request_handle);
  
  request_handle = true;

  int arg1 = 0; // number of steps
  sscanf(input, "%i", &arg1);

  #ifdef internaldebug
    printf("Calling RCP Function Step.\r\n");
    printf("INPUT: %s.\r\n", input);
    printf("OUTPUT: %s.\r\n", output);
    printf("ARG1: %i.\r\n", arg1);
  #endif 
  
  p_stepmotor->loopstop();             
  for(int i=0; i<arg1; i++)
  {
    wait(p_stepmotor->k_delay);
    p_stepmotor->singlestep();
  }

  sprintf(output, "<html><body>RCP NSteps Completed!</body></html>");  
  request_handle = false;
}
//---------------------------------------------------------------------------------------------
void rpc_stepmode(char *input, char *output)
{
  while(request_handle);
  
  request_handle = true;
  
  int arg1 = 0; // microstep=1; fullstep=0;
  sscanf(input, "%i", &arg1);

  #ifdef internaldebug
    printf("Calling RCP Function Step Mode.\r\n");
    printf("INPUT: %s.\r\n", input);
    printf("OUTPUT: %s.\r\n", output);
    printf("ARG1: %i.\r\n", arg1);
  #endif 
  
  if(arg1 == 0)  
  {
    p_stepmotor->adjust_microstepping_mode(1); // full step

    #ifdef internaldebug
      printf("--> FullStep\r\n");
    #endif
  }
  else
  {
    p_stepmotor->adjust_microstepping_mode(16); // microstep 1/16

    #ifdef internaldebug
      printf("--> MicroStep 1/16\r\n");
    #endif    
  }

  sprintf(output, "<html><body>RCP Step Mode Completed!</body></html>");  
  request_handle = false;
}
//---------------------------------------------------------------------------------------------
void rpc_sleepmode(char *input, char *output)
{
  while(request_handle);
  
  request_handle = true;
  
  int arg1 = 0; // microstep=1; fullstep=0;
  sscanf(input, "%i", &arg1);

  #ifdef internaldebug
    printf("Calling RCP Function Sleep CMD.\r\n");
    printf("INPUT: %s.\r\n", input);
    printf("OUTPUT: %s.\r\n", output);
    printf("ARG1: %i.\r\n", arg1);    
  #endif 
  
  if(arg1 == 1)
    p_stepmotor->sleep(true);
  else
    p_stepmotor->sleep(false);

  sprintf(output, "<html><body>RCP Sleep CMD Completed!</body></html>");  
  request_handle = false;
}
//---------------------------------------------------------------------------------------------
// RPC TList Commands (Task/Job List)
//---------------------------------------------------------------------------------------------
void rpc_stepcmd(char *input, char *output)
{
  while(request_handle);
  
  request_handle = true;
  
  int insteps = 0; // number of steps
  int ideltatime = 0; // time in ms between Step Motor SPI frames  
  int idirection = 0; // direction {0->CCW; 1->CW}
  
  sscanf(input, "%i %i %i", &insteps, &ideltatime, &idirection);    
    
  #ifdef internaldebug
    printf("Calling RCP Function StepCmd.\r\n");
    printf("INPUT: %s.\r\n", input);
    printf("OUTPUT: %s.\r\n", output);
    printf("ARG1: %d\r\n", insteps);
    printf("ARG2: %d\r\n", ideltatime);
    printf("ARG3: %d\r\n", idirection);
  #endif 
  
  // adding cmd (TObjectStep) to TList
  pListPointer = SetListNextObject();
  TObjectStep *pobjectstep = new TObjectStep(insteps, ideltatime, idirection);
  pListPointer->cmdtype = 0x01;
  pListPointer->cmdobject = (TObjectStep*)pobjectstep;

  sprintf(output, "<html><body>RCP Step Cmd Completed!</body></html>");
  request_handle = false;
}
//---------------------------------------------------------------------------------------------


//---------------------------------------------------------------------------------------------
// MAIN routine
//---------------------------------------------------------------------------------------------
int main() 
{   
  //std::auto_ptr<int>abc;
  //std::vector<int>def;
  //--------------------------------------------------------
  // Setting RPC
  //--------------------------------------------------------  
  /*
  Base::add_rpc_class<AnalogIn>();
  Base::add_rpc_class<AnalogOut>();
  Base::add_rpc_class<DigitalIn>();
  Base::add_rpc_class<DigitalOut>();
  Base::add_rpc_class<DigitalInOut>();
  Base::add_rpc_class<PwmOut>();
  Base::add_rpc_class<Timer>();
  Base::add_rpc_class<BusOut>();
  Base::add_rpc_class<BusIn>();
  Base::add_rpc_class<BusInOut>();
  Base::add_rpc_class<Serial>();  */ 
   
  //--------------------------------------------------------
  // Setting Ethernet
  //--------------------------------------------------------    
  #ifdef internaldebug
    printf("Setting up...\r\n");
  #endif
  EthernetErr ethErr = eth.setup(); 
  if(ethErr)
  {
    #ifdef internaldebug
      printf("Error %d in setup.\r\n", ethErr);
    #endif
    return -1;
  }
  #ifdef internaldebug
    printf("Setup OK\r\n");
  #endif  

  //--------------------------------------------------------
  // instance of the Step Motor Driver interface
  //--------------------------------------------------------
  A4983 stepmotor;
  p_stepmotor = &stepmotor; // auxiliar pointer for rpc_nsteps(char *input, char *output);
  
  //--------------------------------------------------------
  // adding RPC variables 
  //--------------------------------------------------------
  RPCVariable<uint8_t> RPCenable(&stepmotor.f_motor_enable, "enable");
  RPCVariable<uint8_t> RPCdir(&stepmotor.f_motor_direction, "direction");
  RPCVariable<float> RPCdelay(&stepmotor.k_delay, "delay");

  //--------------------------------------------------------
  // adding RPC functions
  //--------------------------------------------------------
  RPCFunction RPCnsteps(&rpc_nsteps, "nsteps");  
  RPCFunction RPCsleepmode(&rpc_sleepmode, "sleepmode"); 
  RPCFunction RPCstepmode(&rpc_stepmode, "stepmode"); 
  
  RPCFunction RPCstepcmd(&rpc_stepcmd, "stepcmd");    
 
  //--------------------------------------------------------
  // adding Handlers 
  //--------------------------------------------------------
  FSHandler::mount("/webfs", "/files"); //Mount /webfs path on /files web path
  FSHandler::mount("/webfs", "/"); //Mount /webfs path on web root path

  //svr.addHandler<SimpleHandler>("/hello");
  svr.addHandler<RPCHandler>("/rpc");
  svr.addHandler<FSHandler>("/files");
  svr.addHandler<FSHandler>("/"); //Default handler
  //Example : Access to mbed.htm : http://a.b.c.d/mbed.htm or http://a.b.c.d/files/mbed.htm  

  //--------------------------------------------------------
  // bind http server to port 80 (Listen)
  //--------------------------------------------------------       
  svr.bind(80);  
  #ifdef internaldebug
    printf("Listening on port 80 ...\r\n");
  #endif
    
  //--------------------------------------------------------
  // attach timer interrupt to update Net::Pool();
  //--------------------------------------------------------
  netpool.attach(&netpoolupdate, 0.1);

  //--------------------------------------------------------
  // main loop
  //--------------------------------------------------------        
  //stepmotor.f_motor_enable = 1; // used for debug, force motor to star when micro is reset         
  //stepmotor.k_delay = 0.01;
  while(1) 
  {          
    stepmotor.looprun();    
    //stepmotor.singlestep();
  }  
}
//---------------------------------------------------------------------------------------------