Hey everybody,
I plan to build a positioning axis with my Arduino. Therefore I bought the Arduino Uno, a CNC Shield V3, 4 Stepper drivers A4988, and 4 x 4401 stepper motors.
I want the positioning axis to follow different speed/acceleration profiles and not only to position to the point with a constant speed.
Question1:
I saw a lot of people using the GBRL Lib for CNC & printers, but all I have is one positioning axis so GCode might not fit.
I found the AccelStepper.h which seems to work with the CNC Shield V3 aswel.
Can I use the Lib to control the stepper and implement speed/accel changes during the positioning?
Question2:
I want to control these positioning jobs (with different speed profiles) from my android phone.
I already did control an arduino via HC-05 in the past but now I'm not sure if I can use the spare inputs (the flat ones on the side) of the UNO to connect the bluetooth module, because the CNC shield does cover pretty all of the standard in/outputs?
I saw people connecting the HC-05 with the CNC shield directly, but I do not want to send GCode signals as mentioned above.
Summary:
Is there a way to control a positioning axis to follow my preset speed profiles using my phone, the HC-05 the Arduino uno and the CNC Shield?
Thanks in advance!
Max
Is there a way to control a positioning axis to follow my preset speed profiles using my phone, the HC-05 the Arduino uno and the CNC Shield?
Sure there is. You will need to define your protocol. Say a comma delimited string that has the information that you wish to send. Like <m1,a1000,s300,p40> could mean motor 1, acceleration to 1000, speed to 300, position to 40. '<' and '>' are start and end markers. See the serial input basics tutorial for how to read and parse the data string.
And the string copy, compare, search, ect functions to further parse the data.
Oh, and do not forget to set the coil current on the stepper drivers. That is an important step. See the Pololu A4988 page.
Thanks for your ideas!
Do you know if I can connect the Bluetooth chip to the Arduino in parallel?
I thought the CNC Shield does already use the RX TX serial communication port, so is it possible to speak to the Arduino via a second channel like the Bluetooth chip?
If you are not using a firmware like grbl to send gcode to the Uno (with CNC shield) the serial port is free. I would leave the hardware serial port (USB) for program upload and monitoring program flow and variable values. You would connect the HC05 to a software serial port using free pins on the CNC shield. Let's assume that you are not using the Reset/Abort and Feed Hold pins. Those connect to A0 (abort) and A1 (hold) on the Uno. Then you could set up software serial like so:
SoftwareSerial ss(A0, A1); // RX, TX




Here is example code for receiving parameter-value pairs via HC05 and a software serial port on the Uno/CNC shield combo. The Bluetooth sender would transmit a message of the following protocol with start marker, comma delimited parameter-value pair list and an end marker: For example: <M1, S200, A1000> The data string is parsed to an array of parameter-value pairs that can be further parsed to set speed, acceleration, position, etc. variables as needed. This borrows code from Robin2's excellent serial input basics tutorial. This is just an idea, it will need to be customized to fit your project once we know more about what you want.
#include <SoftwareSerial.h>
SoftwareSerial ss(A0, A1);
const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];
char *strings[10];
char *ptr = NULL;
boolean newData = false;
void setup()
{
Serial.begin(115200);
ss.begin(38400);
Serial.println("software serial for HC05 and CNC shield");
Serial.println("CNC ready \n\n");
}
void loop()
{
recvWithStartEndMarkers();
if (newData == true)
{
parseData();
newData = false;
}
}
void recvWithStartEndMarkers()
{
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (ss.available() > 0 && newData == false)
{
rc = ss.read();
//Serial.print(rc);
if (recvInProgress == true)
{
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker)
{
recvInProgress = true;
}
}
}
//============
void parseData() // split the data into its parts
{
byte index = 0;
ptr = strtok(receivedChars, ",");
while (ptr != NULL)
{
strings[index] = ptr;
index++;
ptr = strtok(NULL, ",");
}
//Serial.println(index);
Serial.println("parameter-value pairs received");
for (int n = 0; n < index; n++)
{
Serial.println(strings[n]);
}
Serial.println();
}
Again thanks a lot for these amazing tricks.
To make it a little bit easier to understand here the full description:
I plan to build my own shooting ranch for my cellar for air guns.
To have a more advanced training, I'd like to train with moving targets (boar mode) --> positioning Axis
The target is moving from right to left following a speed profile.
To get more control compared to the regular big shooting ranches (literally just 3 buttons on a cabled remote) I want it to be controlled by app to make adjustments and select the mode.
I planned to build a state machine to handle the 2 device communication.
Your Bluetooth code piece already looks very nice but I'm not sure if I can handle the state machine in the Loop() or even ask there for new bluetooth messages.
In the beginning I also want to have a reference mode where the sleigh references itself on the rail touching hardware limit switches and then gets back to home.
In behind there are additional paper cards to shoot. These can be turned 90° and then flipped back to train the reaction. (BDMP/IPSC mode)
void loop()
{
//per bluetooth ask which mode the user wants to use
switch (myMode){
case 0: //Boar mode
//Send reply to cell phone the first time that Boar mode is selected
//per bluetooth ask in which state we are (only if necessary - possibly lock)
switch (myState){
case 0: //reference mode
//for the first time answers that now reference mode is set
// in reference mode, the machine moves slowly to the limit switch. Then back to the other limit switch. The steps in between form the maximum distance, which is later divided into 10 sections (- some spare space). After referencing move to home position.
//Answer via bluetooth that referencing is completed --> Save steps
break;
case 1: //receive drive profile (profiles + homing + show result mode)
//answers that in receive state and values are waited for.
//receive values for next job
//answer that values have arrived
break;
case 2; //execute mode
//perform movement
//report when movement is done
break;
default:
break;
}
break;
case 1: //BDMP mode
//Send reply to cell phone the first time that BDMP mode has arrived
//per bluetooth ask in which state we are (only if necessary - possibly lock)
switch (myState){
case 0: //reference mode
//answer that we are in reference mode.
//Aply to bluetooth signal x steps right or left until reference is sent.
break;
case 1: //receive waiting time and number of passes
//Per bluetooth process received
//Reception Acknowledge
break;
case 2: //execute mode
//Evtl beep from the Arduino
//Move, wait X Sec (possibly beep) and the whole thing Y times
break;
default:
break;
}
break;
case 2: //IPSC mode
//Send reply to cell phone the first time that IPSC mode has arrived
//per bluetooth ask in which state we are (only if necessary - possibly lock)
switch (myState){
case 0: //reference mode
//answer that we are in reference mode.
//Aply to bluetooth signal each x steps right or left until reference is sent.
//The same for motor 2 and 3.
break;
case 1: //receive waiting time and number of passes for motors 2,3,4 (possibly different beeps)
//Per bluetooth process received
//Reception Acknowledge
break;
case 2: //execute mode
//E.g. beep from the Arduino for start
//Move, wait X Sec (possibly beep up or down) and do the whole thing Y times for one pass
//transmit the end of the turn
break;
default:
break;
}
break;
case 3: //reset everything
break;
default:
break;
}
Not sure what I can do to help. So you have specific needs that I can address?
Your Bluetooth code piece already looks very nice but I'm not sure if I can handle the state machine in the Loop() or even ask there for new bluetooth messages.
Call the recvWithStartEndMarkers() function every time through loop(). It will set the newData flag if there is a new Bluetooth packet available. Otherwise it will do nothing.