Hello and I am New Here...18v7

Hello to You,

I have a motor driver, well two of them, from Pololu and I wanted to use them in a post that I am making for a robotics show-and-tell basically.

I have a beagleY-AI from beagleboard.org and I wanted to use it alongside my 18v7 drivers.

I was reading a bit earlier that these specific DC drivers are maybe going into a deprecation state. Is this a fact? Is it true that the 18v7 drivers are getting a boot with newer, more talented drivers available?

Anyway, I see here: Pololu - 6.7.3. Cross-platform C Example

Are there ways to handle two drivers on the same SBC with the above example? I mean, “No,” is the answer with the cross-platform C example in question but without too much thought, I figured I could try it.

I am not so much of an avid source code maker but I enjoy trying.

Anyway, any ideas or notions will be 100% considered. At first, all I did was attach them to the development desktop to test. I will be using Linux as my end result for an OS.

Seth

P.S. Anyway and so, more about me. I am learning slowly how quickly things change over time within the kernel of Linux more and more recently it seems, I am noticing it change quicker than at any point in time. Okay!

Hello.

As mentioned on the Simple Motor Controller 18v7 product page, we strongly recommend our newer and better G2 Simple Motor Controllers, which can generally be used as drop-in replacements for these original SMCs. We are continuing to offer the original Simple Motor Controllers for now as legacy products for those with systems designed specifically for this controller.

Modifying that example C code to support two devices shouldn’t be too difficult. You can see where the device gets defined and the port gets opened at the beginning of the main() loop:

  // Open the Simple Motor Controller's virtual COM port.
  const char * device = "/dev/ttyACM0";  // Linux
  //const char * device = "\\\\.\\COM6";  // Windows
  //const char * device = "/dev/cu.usbmodemfa121"; // Mac OS X
  int fd = open(device, O_RDWR | O_NOCTTY);

You can essentially duplicate that code to define a second device and open the port for that device (which you can use as arguments to the other functions to control which controller the code is talking to). However, since you have multiple SMCs and /dev/ttyACM0 could refer to either one, I recommend using the symbolic links in /dev/serial/by-id/ to refer to their serial ports. Also, you should make sure to close the new port at the end of your program.

If you try modifying the code and have problems getting it to work, you can post what you have so far, and I would be happy to take a look.

Brandon

1 Like

Hello and Thank You,

I was thinking the 18v7 was deprecated for new use cases. I will look into the new drivers and boards.

I will try the source and report back with the changes I make. Thank you for alerting me on the closing of the serial ports.

Seth

P.S. I might have some serial ports opened in /dev/ by way of multiple USB ports. I need to double check. Anyway, thank you.

// Uses POSIX functions to send and receive data from the virtual serial
// port of a Pololu Simple Motor Controller.
// NOTE: The Simple Motor Controller's Input Mode must be set to Serial/USB.
// NOTE: You must change the 'const char * device' line below.

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

#include <stdlib.h>

#ifdef _WIN32
#define O_NOCTTY 0
#else
#include <termios.h>
#endif

#define SERIAL_ERROR -9999

// Reads a variable from the SMC and returns it as number between 0 and 65535.
// Returns SERIAL_ERROR if there was an error.
// The 'variableId' argument must be one of IDs listed in the
// "Controller Variables" section of the user's guide.
// For variables that are actually signed, additional processing is required
// (see smcGetTargetSpeed for an example).
int smcGetVariable(int fd, unsigned char variableId)
{
  unsigned char command[] = {0xA1, variableId};
  if(write(fd, &command, sizeof(command)) == -1)
  {
    perror("error writing");
    return SERIAL_ERROR;
  }

  unsigned char response[2];
  if(read(fd,response,2) != 2)
  {
    perror("error reading");
    return SERIAL_ERROR;
  }

  return response[0] + 256 * response[1];
}

// Returns the target speed (-3200 to 3200).
// Returns SERIAL_ERROR if there is an error.
int smcGetTargetSpeed(int fd)
{
  int val = smcGetVariable(fd, 20);
  return val == SERIAL_ERROR ? SERIAL_ERROR : (signed short)val;
}

// Returns a number where each bit represents a different error, and the
// bit is 1 if the error is currently active.
// See the user's guide for definitions of the different error bits.
// Returns SERIAL_ERROR if there is an error.
int smcGetErrorStatus(int fd)
{
  return smcGetVariable(fd, 0);
}

// Sends the Exit Safe Start command, which is required to drive the motor.
// Returns 0 if successful, SERIAL_ERROR if there was an error sending.
int smcExitSafeStart(int fd)
{
  const unsigned char command = 0x83;
  if (write(fd, &command, 1) == -1)
  {
    perror("error writing");
    return SERIAL_ERROR;
  }
  return 0;
}

// Sets the SMC's target speed (-3200 to 3200).
// Returns 0 if successful, SERIAL_ERROR if there was an error sending.
int smcSetTargetSpeed(int fd, int speed)
{
  unsigned char command[3];

  if (speed < 0)
  {
    command[0] = 0x86; // Motor Reverse
    speed = -speed;
  }
  else
  {
    command[0] = 0x85; // Motor Forward
  }
  command[1] = speed & 0x1F;
  command[2] = speed >> 5 & 0x7F;

  if (write(fd, command, sizeof(command)) == -1)
  {
    perror("error writing");
    return SERIAL_ERROR;
  }
  return 0;
}

void intHandler(int) {
    fprintf(stderr, "\nintHandler called\n");
    exit(0);
}

int get(int argc, char** argv) {

    __sighandler_t rc;

    rc = signal(SIGINT, intHandler);  // catches ctrl c
    if (rc == SIG_ERR) {
        perror("SIGINT error");
    }

    rc = signal(SIGTERM, intHandler);  // catches kill commands
    if (rc == SIG_ERR) {
        perror("SIGTERM error");
    }
}

int main()
{
  // Open the Simple Motor Controller's virtual COM port.
  const char * device = "/dev/ttyACM0";  // Linux
  //const char * device = "\\\\.\\COM6";  // Windows
  //const char * device = "/dev/cu.usbmodemfa121"; // Mac OS X
  int fd = open(device, O_RDWR | O_NOCTTY);
  if (fd == -1)
  {
    perror(device);
    return 1;
  }

#ifdef _WIN32
  _setmode(fd, _O_BINARY);
#else
  struct termios options;
  tcgetattr(fd, &options);
  options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IXON | IXOFF);
  options.c_oflag &= ~(ONLCR | OCRNL);
  options.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  tcsetattr(fd, TCSANOW, &options);
#endif

  smcExitSafeStart(fd);

  printf("Error status: 0x%04x\n", smcGetErrorStatus(fd));

  int speed = smcGetTargetSpeed(fd);
  printf("Current Target Speed is %d.\n", speed);

  int newSpeed = (speed <= 0) ? 3200 : -3200;
  printf("Setting Target Speed to %d.\n", newSpeed);
  smcSetTargetSpeed(fd, newSpeed);

  close(fd == 0);
  int val = smcGetVariable(fd, 0);
  perror("Cannot close now...\n");
  return 0;

}

Right now, the source just runs the motor continuously. It seems I cannot close the USB Device via Linux at /dev/ttyAMA0 so far.

I have tried multiple ways. It seems that there are commands being sent while trying to close the device. Please send some guidance.

Seth

Should I use the temporary motor limits like in in the docs?

Seth

Update

I am getting gibberish on the screen on your website located at this address: Pololu Simple Motor Controller User’s Guide

I am trying to figure out all the Controller Variables.

So, this line should account for closing the fd and stopping the motor after initializing it:

smcSetTargetSpeed(fd, newSpeed = 0);
close(fd);

That stalls the motor to end the file…

So, the G2 is the updated versioning, right?

I see it was released in 2018. I am reviewing the documentation on it now.

Seth

P.S. I will keep reading, i.e. as I am looking for some serial communication types for drivers and motor usage.

Update

No issue now. I see the pricing and availability. I see the G2 versions now. Just a little more digging. Did Pololu personnel update the STM chip on the G2 versioning? Anyway, thank you again for your time. I am researching and I also see the BEC available for these drivers and the RC signals available. Nice.

When it states 6.5v minimal voltage, is this translating to not 5v USB and needs an additional supply for USB?

6.5V is the minimum operating voltage is for VIN, and you do not need two separate power sources. The board incorporates both a 5V regulator and 3.3V regulator. The onboard 5V regulator is powered by VIN and used for the 5V bus whenever VIN is connected; otherwise, the 5V bus is powered from the USB.

I am not entirely following the state of your problem, but it sounds like it might be working how you want now and you found answers to your questions. Please let me know if that is not the case or you have any questions still unanswered.

Brandon

1 Like

No issue. I got everything working with the source given on the website, I got the extra needed stopping done at the end of the source code, and I got the RC section(s) working too.

Thank you again for dealing with me and providing support.

Seth

1 Like