Show Posts
Pages: 1 [2] 3 4 ... 6
16  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 13, 2013, 03:24:34 pm
All the moving variables are initialized as true.  What exactly does the MotorRun variable do?  You're setting it to -1, but I don't currently have a MotorRun variable in my code... so I'm not sure what it's referring to.
17  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 13, 2013, 03:14:11 pm
Regarding your comment:  Perhaps what needs to happen is that if any of the moving_n flags is false, motorRun needs to be set to other than 1.
Does this mean I need to check whether the boolean is true/false before telling the motor to run?  I tried something like this, but it doesn't seem to work.  Basically, it waits to get the first command, and when I send it the string: 500,400,300,200,1000,100,1,0, then you'd think it would wait until all the motors have finished moving (so however long it takes to move the motor 500 steps) and then it would print the command "next".  However, it never prints "next".  It just hangs there.  Any thoughts?

Quote
  if (motorRun == 1) {
    while(1)
    {
      if(!moving_1) moving_1 = stepper1.run();
      if(!moving_2) moving_2 = stepper2.run();
      if(!moving_3) moving_3 = stepper3.run();
      if(!moving_4) moving_4 = stepper4.run();

      if(!moving_1 && !moving_2 && !moving_3 && !moving_4){
        
        Serial.println("next");   //send character for the next line from Firefly
        
        moving_1 = true;          //reset all the moving variables
        moving_2 = true;
        moving_3 = true;
        moving_4 = true;
        
        break;
      }
    }
  }
18  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 13, 2013, 02:37:52 pm
Thanks for all the quick replies!  It seems like the AccelStepper library actually returns true if it's still moving and false when it's done (https://github.com/adafruit/AccelStepper/blob/master/AccelStepper.cpp)... so I think I have to check weather or not the motor has returned false.  But, I'm making a little progress.  I now have this as the function:

Quote
  if (motorRun == 1) {
    timer = millis();
    while(1)
    {
      done_1 = stepper1.run();
      done_2 = stepper2.run();
      done_3 = stepper3.run();
      done_4 = stepper4.run();

      if(!done_1 || !done_2 || !done_3 || !done_4){
        if(!done_1) msg_char = "1";
        else if(!done_2) msg_char = "2";
        else if(!done_3) msg_char = "3";
        else if(!done_4) msg_char = "4";
        Serial.println(msg_char);  //send character for the next line from Firefly
        break;
      }
    }
  }

This works for the most part... if I enter in the string: 5000,4000,3000,2000,1000,100,1,0, then it waits a brief period of time (simulating moving motor 4 to 1000 steps) and then prints the number 4... then 3... then 2... then 1.  However, I noticed something funny.  For some reason, after I enter in the string command above, and before it's reached position 4 (so some small amount of time) the serial monitor starts printing the number 1 (almost as if it's broken out of the while loop and assigned the msg_char... however, all the done variables are initialized to true and the msg_char is initialized as an empty string.  So, I'm not sure why it's printing the number 1, before it prints 4, 3, 2, and then 1. 

Also, the timer check was in there so it slows everything down.  Let's say I send a command, then all the motors reach their final position.  If this condition is true, then it will start sending the msg_char basically as fast as it can, because their is nothing in the loop function slowing it down.  If I send the data too quickly, then my application will crash.  So, I had tried to put a simple timer check to make sure at least 10ms had elapsed before sending the string back to my application.  But, when I try adding that into the code, nothing seems to work (like before).  When it isn't in there, then I get the response above.  Thoughts?
19  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 13, 2013, 02:16:30 pm
Ah.  Ok.  My mistake.  Still, if I change the conditional to

Quote
      if(done_1 || done_2 || done_3 || done_4)
         break;

Then, I still have the same issue... as soon as I send that string: 500,400,300,200,1000,100,1,0... then the program basically freezes... it never sends the msg_char back to the serial port indicating which motor has finished.  Do you think it has something to do with the millis() conditional check:

Quote
    if(millis() - timer > 10){
      Serial.println(msg_char);  //send character for the next line from Firefly
    }

I put this in so that if they're all at their final destination point, that it has to wait at least 10ms before sending the next command... The buffer in my application can get flooded if too much data is sent too quickly, so this is just a simple check to make sure at least a small portion of time has elapsed before sending the call back command.
20  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 13, 2013, 02:05:27 pm
Thanks Paul.  That was my mistake... I had been fiddling around with different parts of the code and had originally tested whether or not all 4 motors had gotten to their position.  However, I tried your code snippet and it still doesn't seem to work.  Here's my new code (I think you have to check for !done_1, etc... because it returns true when the motor is moving and false when it's reached its final position):

Quote
  
  if (motorRun == 1) {
    timer = millis();
    while(1)
    {
      done_1 = stepper1.run();
      done_2 = stepper2.run();
      done_3 = stepper3.run();
      done_4 = stepper4.run();

      if(!done_1 || !done_2 || !done_3 || !done_4)
         break;
    }
    
    if(done_1) msg_char = "1";
    else if(done_2) msg_char = "2";
    else if(done_3) msg_char = "3";
    else if(done_4) msg_char = "4";
    if(millis() - timer > 10){
      Serial.println(msg_char);  //send character for the next line from Firefly
    }
  }


However, if I launch the serial monitor... what I see at first is a bunch of 'n' characters printing every 200ms (this is from the establishContact function).  Once it receives it's first incoming serial data, it should then launch into the loop() function and determine the first motor positions and jump into the while loop.  So, if I send the following string:

Quote
500,400,300,200,1000,100,1,0

where the first four numbers are the target positions for each motor (starting with motor 1), the next number is Motor Speed, then Motor Acceleration, then Motor Run, and Motor Reset values... So this is the string my application would be sending... I'm using the Serial Monitor send function to simulate this just for debugging... So, I would think that once I send this string via the Serial Monitor, it would wait some brief time (to move the motors) and then when the first of the motors was done (motor 4), then it would print a character back to the serial port ("4") indicating it's ready for the next line.  However, as soon as I send the data via the serial monitor... nothing happens after that point.  It basically freezes (and nothing gets printed back).  So, something is getting stuck somewhere, but I'm not really sure where.  Any ideas?  Thanks again for your help.
21  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 13, 2013, 01:34:28 pm
Quote
 
#include <AccelStepper.h>
#define BAUDRATE 115200     //Set the Baud Rate to an appropriate speed
#define BUFFSIZE  256       // buffer one command at a time, 12 bytes is longer than the max length
#define DIR_PIN_A 2         //Set Direction Pin for Stepper A to Digital Pin 2
#define STEP_PIN_A 3        //Set Step Pin for Stepper A to Digital Pin 3
#define DIR_PIN_B 4         //Set Direction Pin for Stepper B to Digital Pin 4
#define STEP_PIN_B 5        //Set Step Pin for Stepper B to Digital Pin 5
#define DIR_PIN_C 6         //Set Direction Pin for Stepper C to Digital Pin 6
#define STEP_PIN_C 7        //Set Step Pin for Stepper C to Digital Pin 7
#define DIR_PIN_D 8         //Set Direction Pin for Stepper D to Digital Pin 8
#define STEP_PIN_D 9        //Set Step Pin for Stepper D to Digital Pin 9

long motorPos[4] = {0,0,0,0};
int motorSpeed = 2000;     //Set default speed value
int motorAcc = 1000;       //Set default acceleration value
int motorRun = 1;          //Set default run value
int motorReset = 0;        //Set default reset value

boolean needUpdate_1 = true;
boolean needUpdate_2 = true;
boolean needUpdate_3 = true;
boolean needUpdate_4 = true;

unsigned long timer = 0;
String msg_char = "";

char *parseptr;
char buffidx;

char buffer[BUFFSIZE];    // this is the double buffer
uint16_t bufferidx = 0;   // a type of unsigned integer of length 16 bits
uint16_t p1, s1;   

// Define some steppers and the pins they will use: Ex: Accelstepper stepper1(1, 3, 4) <- STEP PIN 3, DIR PIN 4.
AccelStepper stepper1(1, STEP_PIN_A, DIR_PIN_A);
AccelStepper stepper2(1, STEP_PIN_B, DIR_PIN_B);
AccelStepper stepper3(1, STEP_PIN_C, DIR_PIN_C);
AccelStepper stepper4(1, STEP_PIN_D, DIR_PIN_D);

void setup()
{  
  stepper1.setCurrentPosition(0);  //Move steppers to default position
  stepper2.setCurrentPosition(0);
  stepper3.setCurrentPosition(0);
  stepper4.setCurrentPosition(0);  
  setStepperSpeeds();

  Serial.begin(BAUDRATE);         // Start serial communication
  establishContact();             // send a byte to establish contact until receiver responds
}

void loop()
{
  UpdateStepperValues();  //Get all the incoming values from Firefly

  if (motorReset == 1) {
    stepper1.setCurrentPosition(motorPos[0]);
    stepper2.setCurrentPosition(motorPos[1]);
    stepper3.setCurrentPosition(motorPos[2]);
    stepper4.setCurrentPosition(motorPos[3]);
  }
  
  if (motorRun == 1) {
    timer = millis();
    do{
      needUpdate_1 = stepper1.run();
      needUpdate_2 = stepper2.run();
      needUpdate_3 = stepper3.run();
      needUpdate_4 = stepper4.run();  
    } while (!needUpdate_1);
    
    if(needUpdate_1) msg_char = "1";
    else if(needUpdate_2) msg_char = "2";
    else if(needUpdate_3) msg_char = "3";
    else if(needUpdate_4) msg_char = "4";
    if(millis() - timer > 20){
      Serial.println(msg_char);  //send character for the next line from Firefly
    }
  }
}

void UpdateStepperValues(){

  char c;    // holds one character from the serial port
  if (Serial.available() > 0) {
    c = Serial.read();      // read one character
    buffer[bufferidx] = c;  // add to buffer

    if (c == '\n') { 
      buffer[bufferidx+1] = 0; // terminate it
      parseptr = buffer;       // offload the buffer into temp variable

      //********************************************************

      motorPos[0] = parsedecimal(parseptr);    // parse the first number
      parseptr = strchr(parseptr, ',')+1;      // move past the ","

      motorPos[1] = parsedecimal(parseptr);    // parse the next number
      parseptr = strchr(parseptr, ',')+1;      // move past the ","

      motorPos[2] = parsedecimal(parseptr);    // parse the next number
      parseptr = strchr(parseptr, ',')+1;       // move past the ","

      motorPos[3] = parsedecimal(parseptr);    // parse the next number
      parseptr = strchr(parseptr, ',')+1;      // move past the ","

      motorSpeed = parsedecimal(parseptr);     // parse the next number
      parseptr = strchr(parseptr, ',')+1;      // move past the ","

      motorAcc = parsedecimal(parseptr);       // parse the next number
      parseptr = strchr(parseptr, ',')+1;      // move past the ","

      motorRun = parsedecimal(parseptr);       // parse the next number
      parseptr = strchr(parseptr, ',')+1;      // move past the ","

      motorReset = parsedecimal(parseptr);     // parse the next number

      setStepperSpeeds();
      stepper1.moveTo(motorPos[0]);            //set new absolute target position
      stepper2.moveTo(motorPos[1]);            //set new absolute target position
      stepper3.moveTo(motorPos[2]);            //set new absolute target position
      stepper4.moveTo(motorPos[3]);            //set new absolute target position

      bufferidx = 0;       // reset the buffer for the next read
      return;              //return so that we don't trigger the index increment below
    }
    // didn't get newline, need to read more from the buffer
    bufferidx++;    // increment the index for the next character
    if (bufferidx == BUFFSIZE-1) {  //if we get to the end of the buffer reset for safety
      bufferidx = 0;
    }
  }
}

double parsedecimal(char *str)
{
  return atof(str);
}

void establishContact() {
  while (Serial.available() <= 0) {
    Serial.println("n");   // send an initial string
    delay(200);
  }
}

void setStepperSpeeds() {

  stepper1.setMaxSpeed(motorSpeed);
  stepper1.setAcceleration(motorAcc);

  stepper2.setMaxSpeed(motorSpeed);
  stepper2.setAcceleration(motorAcc);

  stepper3.setMaxSpeed(motorSpeed);
  stepper3.setAcceleration(motorAcc);

  stepper4.setMaxSpeed(motorSpeed);
  stepper4.setAcceleration(motorAcc);
}

22  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 13, 2013, 01:34:05 pm
Ok.  I've tried a few options, but can't seem to get anywhere.  I've tried adding a while loop which will terminate when one of the four motors has finished getting to its desired position.  I do this by storing the return boolean value from the stepper.run() function where it will return true if the motor is still trying to move to it's final position.  Once it breaks out of the loop, I then determine which of the four motors has finished (again, by using the return value) and then sending a character (1, 2, 3, or 4) back to my application telling my application it's ready for the next bit of information.  However, none of this seems to really work.  The code is somewhat long (see post below... it was too long to add in this post), but I've tried to add comments so that it's clear.  Please let me know if you have any suggestions.  Thanks.
23  Using Arduino / Programming Questions / Re: Serial Communication and Blocking vs NonBlocking Functions on: February 12, 2013, 03:13:36 pm
Interesting.  Thanks for the reply and suggestions.  I agree that the blocking functions seemed troublesome (which is precisely why I was looking for help).  Thanks again for the suggestions.  I'll try to give it a go and see if I can come up with a solution.  As far as call backs go, is there a better way than just sending a string back to my application when the while loop breaks out of its loop?
24  Using Arduino / Programming Questions / Serial Communication and Blocking vs NonBlocking Functions on: February 12, 2013, 02:46:33 pm
Hi everyone,
I'm writing to get some help on a program I'm writing to control stepper motors.  I've already got a version of the program working where my program (developed in C#) will send a string of data (over serial) over to the arduino board with information about how to control up to four steppers (using the AccelStepper library: https://github.com/adafruit/AccelStepper).  This process works pretty well, however my arduino code currently calls non-blocking move functions... so every time the serial data is available, it reads it in and then immediately tries to move the motors to those positions.  However, it may not have reached the destination it had previously been trying to get to, before this next command had been issues.  This non-blocking sequence is helpful in some instances, like when you move a slider and you want the stepper to try to keep up with the most current position.  However, it's a bit troublesome if trying to control precisely the movement path of a motor (say for a CNC machine) where it needs to move to every position before moving onto the next instruction.

So, I think I need to rethink the workflow a bit.  First, I'm pretty sure I'll need to use blocking commands (the Accel Stepper library has both)... however, more importantly I need the Arduino to send a call back to my application letting it know that it just completed the last move and it's ready to receive the next one.  The issue I see is that my applications update cycle is relatively slow (and it's scene dependent... meaning the more stuff I have going on in the scene, the slower the refresh rate will be)... Typically the fastest I've been able to get it to run is 60Hz, but usually closer to 30Hz.  So, if I'm trying to get smooth motor control, this may be a problem, because my application will send a command and then wait for the call back... The arduino will execute the command and then send the call back and wait for the next command from GH.  However, there is probably going to be a delay of several milliseconds between those two actions... and this could cause somewhat jerky motion. 

I'm wondering if anyone has any suggestions about how to resolve this.  Are there any ways to issue a callback to another application and have it basically be instantaneous?  The other issue I see is how can I control up to 4 motors in parallel if using blocking commands?  If it's a blocking function, wouldn't it have to move one motor, then the next, then the next, etc.  Is there a way to be able to control motors in parallel and still know when the stepper has completed moving to its destination?  If it would help, I can post the arduino code that I have so far... but currently it's just implementing the non-blocking functions and doesn't implement the call back function at all.  Thanks for the help.
25  Using Arduino / Motors, Mechanics, and Power / Pnuematic Pump Suggestion on: January 31, 2013, 09:51:58 am
Hi Everyone,
I've been thinking of taking on a small side research project for a while... and I was wondering if I could get some suggestions for a small pnuematic pump (probably something that could supply about 10psi).  I've been interested in the idea of 'soft' robotics for a while, and found George Whiteside's research at Harvard very compelling (http://gmwgroup.harvard.edu/techniques/index.php?topic=Soft%20Robotics).  I've got some information on the silicone casting process... but I'm a little new to pnuematics and don't really know where to start.  I know the Whiteside research group also uses liquid pumping, but I think for the moment I'd like to stick to air pressure to inflate the silicone.  Ideally, I'd like the pump to be able to be controlled via an arduino (to turn on/off) and potentially have a valve (solenoid) that could be opened/close via a microcontroller as well.  Does anyone on here have any suggestions or places to start looking?
Thanks again,
Andy
26  Using Arduino / Programming Questions / Re: Determining which board type is being used? on: July 17, 2012, 08:24:19 am
Thanks so much!
27  Using Arduino / Programming Questions / Re: Determining which board type is being used? on: July 17, 2012, 08:06:29 am
Hi Paul,
I'm sorry for getting back to this late.  I found the pins_arduino.h header file, but I'm having a little trouble figuring out how to actually determine if the #define has been set for the Mega or not.  Would it be possible to setup a really basic example (just a bare minimum sketch) with the proper code in the setup() function that determines which board type is being used.  Actually, I also have a follow-up.  I'm also trying to add support for the Leonardo, and I see it also has it's own pins_arduino.h file.  Is there an easy way to determine between standard, Mega, and Leonardo boards?  Thanks for the help.
-Andy
28  Using Arduino / Installation & Troubleshooting / Leo and Serial Monitor/Print Troubles on: July 11, 2012, 08:36:52 am
Hi everyone,
I'm testing the new Leonardo board.  I've read through the [http://arduino.cc/en/Guide/ArduinoLeonardo]getting started[/url] page and I think I understand the differences between this board and the older boards.  My question deals with serial communication.  I've developed a sketch which sends information back and forth to another application using serial commands.  Basically the arduino board sets up all the pins, prints the most current sensor data (all analog pins, and 3 digital pins), and then waits for data coming over from the application at which point it parses it up and sends the data out to the remaining digital pins.  Now, all of this works great with the Uno (and I also have a version for the Mega).  I'm trying to modify the code so that it now works with the Leonardo... but I'm getting some strange results.

First, the Leonardo never seems to 'hold' onto a given virtual port.  I know it temporarily creates them on the fly, but it seems it only does so when I hold down the reset button.  After a few seconds it loses the port again.  So, every time I want to upload a sketch, I have to hold down the reset button, wait for it say "Uploading" and then release the reset button.  Then, it seems to upload just fine.  However, I can't then launch the serial monitor right after that, because as soon as it's done uploading, it loses the connection again.  If I hold reset again, I can launch the serial monitor, but nothing seems to be getting printed to the serial monitor (where as I should see a formatted string of data flying by if this had been done using the Uno).  I've even tried basic example sketches like the AnalogReadSerial example, and this also never seems to work. Do I have a faulty board (I purchased it from sparkfun)?  Or am I doing something wrong in my code?  

Also, I've gone through and installed the driver per the website instructions... but I'm still getting a strange icon showing up next to my board in the device manager.  Is this what it's supposed to look like?  I've pointed the driver to the drivers folder in the 1.01 Arduino folder.

29  Using Arduino / Programming Questions / Determining which board type is being used? on: July 10, 2012, 08:54:07 am
Hi Arduino community,
I have a question that I'm hoping someone can help me out with.  You see I have two different sketches, each of which work fine... but are geared specifically for different types of boards.  The first is for the Uno or all other clones (basically any board that has the same number of pins, ie. Lillypad, Duemilanove, etc.)  The second is a sketch for the Mega (since this has a completely different pin setup.  What I would like to do is to combine these two sketches into a single sketch and have some sort of function that checks which board type is being used during the upload process... an only load portions of the combined sketch that are appropriate for that type of board.  Does that make sense?  I could imagine some sort of #ifdef function that could be used if the board that was being used was an Uno, or Mega, and only upload those portions of the sketch.  So, my question is... is there a way to determine which board is being used upon upload?  I know the IDE reports the last selected board at the bottom of the window... so, is this being stored somewhere that I could access?  Or am I going about this the wrong way.  Any help would be greatly appreciated.
Cheers,
Andy
30  Using Arduino / Installation & Troubleshooting / Re: Mega 2560 Serial Monitor on: July 03, 2011, 09:19:52 am
Hmm... Ok.  I bought the board from Sparkfun, so perhaps I will contact them.  It does still seem to be sending values (eventually) but it's really strange that even completely basic sketches still take almost 7-10 seconds before starting to print the values.  Thanks again.
Pages: 1 [2] 3 4 ... 6