Highspeed X Y gantry parts bucket getter (bushless motor)

How are you doing? I have started my second Arduino project and it seems as though I always want to start a project that I can’t find any information on. I have found similar projects and but can’t find exactly what I need. So I would like to get some feedback on my approach on how to code this before I spend a long amount of time trying to code this seeing as how I always get stuck there.

I have built a linear rail system in my garage and the ultimate goal is parts bin picker. I know everyone is going to want to give advice on why I should use a stepper motor but I have chosen to use an RC car brushless motor. Do to raw power that these things have. I have chosen a motor with three hall-effect sensors in it although I am only using one hall sensor to count my rotations. The motor is coupled through a two gear reductions and 33t pinion to an 87 tooth gear the 87t gear is mounted solid to a 16t bicycle gear and they turn 1 for 1 and then the 16t drives a 44 t bicycle sprocket and that is mounted solid to another 16t bicycle sprocket that turns a bicycle chain that is about 16 feet long. In the future this chain will be about 80 feet long. I have two of these one goes vertically and one goes horizontally. The motor can spin excess of 20,000 rpms. By my math which is not great, it should do about 20mph and be able to haul a pretty nice load. It will go to its target by counting the effect sensor rotations. If I’m not mistaken it will turn about 10 times for every inch that it moves. I have used the servo library to control the motor successfully as well as pulled the hall effect sensor and printed it 1’s and 0’s on the serial monitor along with making the pin 13 led blink with it although when I get up in the rpms the led actually looks solid. So this is what I’m thinking.

This is what I got an Arduino Uno, Ethernet shield

First I will start by giving it a number via serial port somehow (LCD later with a number pad) this will correspond to the x axis and y axis although just getting one to move right now is the goal.

Arduino will give speed controller a PWM signal to start to accelerate. Right now I have it mapped so that 1500 is neutral and the lower you go to 1000 the faster it goes in reverse and when you go the other way 2000 is full throttle forward.
Do you think that I have to use an interrupt pin to count the 1’s or highs from the hall effect sensor so that the counting process is number one priority seeing as I don’t want the thing to go 20 miles an hour into the wall (I have also read the sensor with analog read but, it gives me three different numbers usually 0,0,45,545,45,0,0). So, I think I need to use digital read on an interrupt pin to count the rotations and then once it gets to my desired number it gives the speed controller a 1500 or neutral (but in this case 1500 is actually brakes) so it should decelerate very fast. I know it’s going to over shoot and I think that after I do some testing and find out long it takes it to stop I can slow it once it gets to a specific number say 20 hall-effect sensor occurrences before target location. Its probably going to overshoot by a pretty consistent number. So I will be able to figure that out and when I know what that is I will be able to add in some sort of decelerate function as it approaches the target. I will start out slow so as to not ram the thing into the side of wall.

Can anyone help me figure out how to make it count my hall-effect sensor occurrences?
What would be a simple solution to give it a target number?

Should I use one of the chat server functions or is there an easier way?

No, please don't do this in a chat window. I'm very interested in this, myself.

So you have solved most problems already? You can control the beast, now we want to add intelligence :slight_smile:

Usualy I always say "Do NOT use interrupts". Like any rule there are exceptions. Here would be good use. Unless you tell me otherwise I'll assume you can work out the details on how to attach the interrupt to your routine when the pin changes state or just goes high. The interrupt rotine should simply be

void HallISR() {
if (GoingFWD) HallCounter++; else HallCounter-- ;
}

HallCounter can be an int or a long, usual stuff about declaring it voletile etc. The GoingFWD is set to true if you currently have commanded the motor forward. (That means this code can not work if you reverse directions before the motor has stopped)

In your main motor move section you have HallDestination which contains the desired end value. You subtract this from the HallCounter and it gives you sort of the distance to go, and you add that to your 1500 neutral stuff. This then means that the speed/power will be proprtional to the distance to go. Tweak it with a little offset, probably scale it and this thing should simply move the carriage to the destination you enter in the HallDestination.

Oh yes, - dont forget - when doing any HallCounter calculation (that is the subtraction mentioned) you disable the interrupts and re-enable them afterwards. It should still catch the current state change (interrupts are queued). If this makes you loose position too much (because you missed a tick) then the code needs to a little more convoluted where you use a byte counter in the interrupt routine and use that to adjust the HallCounter long variable (as a byte is atomic it does not need the interrupt disable stuff) and reduce the byte by the value you added (in case another tick occured while you added)

"chat serve function"?!

I"m sorry i didn't mean to say chat window I meant use the Arduino Chat server library to send information back and forth to the Arduino to give it a command to go to its location. I have also thought maybe later that they could be used with gimbal brushless motors that are very slow rotation but are more precise and smoother than Stepper motors to control CNCs or 3D printers. I know steppers motors are the steps you command is what you get but there has got be a way to feed the pulse width signal along with the counts and make it stop at very precise counts. I think it might be a little harder with CNC seeing as how certain counts have to happen a specific times for arcs and angles to match up. The gimbal motors can rotate but they usually don't and the controllers are just used to control a specific angle of the motor and they do a very good job of keeping cameras exactly where they need to be.

I shouldn't assume that you know about ramping the speed up and back down as it approaches its destination?

No, you should not assume that. I know of it and will address it but lets get it going and trying to stop first. The motor will accelerate itself VIA speed controller.

This is what I got so far and I am not programmer by any means so I have to look at a bunch of sketches and try to mix and match to get what I want. I haven’t tested this yet because there are a lot of compiler issues I’m still trying to work out. Trying to learn where each part is supposed to go. I know I have some issues down at the bottom and some of my int and I think it said something about construction too before void. LOL

#include <Servo.h>           //using this library to control the Speed controller

Servo myspeedcontroller;
const int hallPin = 2;           // the number of the pushbutton pin
const int ledPin =  13;          // the number of the LED pin
int val;                         // desired number of rotations
int hallstate = 0;               // variable for reading the pushbutton status I think I need to use a mechanical debouncer
volitile int motorfwd = valfwd   // tells speedcontroller to rotate motor forward
volitile int motorrev = valrev   // tells speedcontroller to rotate motor rev


void HallISR() {
  if (valfwd) HallCounter ++; 
  if (valrev) HallCounter-- ;
}
void setup() {
  myspeedcontroller.attach(9);   //attaches speedcontroller on pin 9 to the servo object
  pinMode(ledPin, OUTPUT);       // initialize the LED pin as an output:  
  pinMode(hallPin, INPUT);       // initialize the pushbutton pin as an input:

void loop(){
  
  hallState = digitalRead(buttonPin);  // read the state of the pushbutton value:

                                       // check if the hallsensor is sending a signal.
                                       // if it is, the hallsensor is HIGH:
  
  
  
  val = (?);                          // reads the value that I send not sure how to yet,desired rotation count
  valfwd                              // speed controller fwd value
  valrev                              // speed controller rev value
  myspeedcontroller.write(valfwd);    // sends speed controller forward command 
  delay(15);                          // waits for the servo to get there if 
  (hallstate == HIGH) {     
                                      // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
                                // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
}

Sounds like a great project. If you want to deal with over-/under-shoots and bearing in mind that you may be moving variable masses around if I've understood you right, I suggest using a closed-loop control system to control the position. That could just be a simple proportional control system based on how far away it is from the target position, but a PID algorithm would give better control and ensure the thing doesn't oscillate or hunt.

I assume you have already figured out how to keep track of the current position by using a parking sensor and counting pulses from the hall sensor. (If you haven't committed to that sensor yet you might also consider adding a quadrature rotary encoder to the final drive mechanism instead - they're easy to use and give you a positive indication of direction as as well as distance moved.)

I've looked into the encoder but right now really would like to stick with the sensor thats in the motor. It actually hass three in there ABC and three I could tell what way rotation just by what signal I have fed it the RC speed controller does that for me. I just have to figure out how if I give it this PWM 1000-1499 it subtracts to the count and if I give it 1501 PWM it adds to the count. My code is horrible, its so hard to try and past stuff together. When people suggest stuff it is like a foreign language to me and then trying to construct a grammatically correct sentence in the language. I have no clue if its an adjective a verb,noun or pronoun more or less where they go in a sentence.

Thanks for the help with the suggestion on the hall counter I noticed that says void HallISR() { why does it now say setup or loop. Why does it just say HallSR() {

Msquare:
So you have solved most problems already? You can control the beast, now we want to add intelligence :slight_smile:

Usualy I always say "Do NOT use interrupts". Like any rule there are exceptions. Here would be good use. Unless you tell me otherwise I'll assume you can work out the details on how to attach the interrupt to your routine when the pin changes state or just goes high. The interrupt rotine should simply be

void HallISR() {

if (GoingFWD) HallCounter++; else HallCounter-- ;
}


HallCounter can be an int or a long, usual stuff about declaring it voletile etc. The GoingFWD is set to `true` if you currently have commanded the motor forward. (That means this code can not work if you reverse directions before the motor has stopped)

In your main motor move section you have HallDestination which contains the desired end value. You subtract this from the HallCounter and it gives you sort of the distance to go, and you add that to your 1500 neutral stuff. This then means that the speed/power will be proprtional to the distance to go. Tweak it with a little offset, probably scale it and this thing should simply move the carriage to the destination you enter in the HallDestination.

Oh yes, - dont forget - when doing any HallCounter calculation (that is the subtraction mentioned) you disable the interrupts and re-enable them afterwards. It should still catch the current state change (interrupts are queued). If this makes you loose position too much (because you missed a tick) then the code needs to a little more convoluted where you use a byte counter in the interrupt routine and use that to adjust the HallCounter long variable (as a byte is atomic it does not need the interrupt disable stuff) and reduce the byte by the value you added (in case another tick occured while you added)

"chat serve function"?!

PeterH:
Sounds like a great project. If you want to deal with over-/under-shoots and bearing in mind that you may be moving variable masses around if I've understood you right, I suggest using a closed-loop control system to control the position. That could just be a simple proportional control system based on how far away it is from the target position, but a PID algorithm would give better control and ensure the thing doesn't oscillate or hunt.

I assume you have already figured out how to keep track of the current position by using a parking sensor and counting pulses from the hall sensor. (If you haven't committed to that sensor yet you might also consider adding a quadrature rotary encoder to the final drive mechanism instead - they're easy to use and give you a positive indication of direction as as well as distance moved.)

What is a parking sensor. I'm trying to make it count right now. and print back to the serial monitor. My most current successful test was getting the sensor to print back a 1 or 0 depending on high and low and turned pin 13 led on. I got a few suggestions and just found a pinintcounter in the references and trying to adapt it to my code although I havn't got it to count yet on the monitor. I actually haven't even got it to compile yet.

By a parking sensor I mean a switch that is tripped when the mechanism reaches the end of its travel, so that you can get a positive indication of where it is in absolute terms. All the hall effect sensors and rotary encoders and so on do it tell you when the mechanism has moved and how much it has moved, but unless you know where it started, you don't know where it has got to. To get around that you can add a parking sensor (aka limit switch) and have an initialisation sequence that moves the motor until that parking sensor is tripped to give you a 'zero' position.

a DC motor with rotary encoder is superior to a stepper for positional accuracy. since the encoder is not part of the drive circuit, it cannot miss steps. also, every rotation has a calibration point. since the project is using a DC motor to start with it would be easy enough to add the encoder. this is what they use for the large high precision gantry tables for lasers and high power milling. the power and accuracy is much better than using steppers.

the part/end/home sensor should allow for the table to pass without damage. the typical use is to run it at high speed until it passes the sensor, stop, reverse slowly, pass again, stop, slowly advance until the sensor is made. compare where it is to where the postioner thinks it should be, report if there is any error. once reported, the user can ignore and re-set, or evaluate if the error would have caused a problem.

A couple of things to consider (before you get too far into this):

  1. Chain stretch. Wear = stretch and it’s cumulative. The longer the chain, the more stretch you get. The usual back of the napkin specification for wear on a standard bike chain is that about 0.5% elongation is point where you replace the chain before it breaks. That works out to roughly 3.5 inches of stretch for your sixty feet of chain, which while you can compensate for it, it will result in an ever changing error in position. Long term, think about another position feedback scheme, a laser distance measurement comes to mind which solves one problem and provides additional speed feedback if it updates fast enough to use in that context.

  2. Zipping the carriage left and right is easily understood. But, once you introduce up and down and add some weight, the physics are quite different. Now, you are no longer using positive torque, lowering the load requires negative torque, a.k.a. braking. While you’ve probably done that with a miniature servo on an Arduino, it’s a different game when you scale things up in size. The energy involved can (typically) no longer be burned off in the motor, at least not in a controlled fashion, which means a loss in speed control. So, normally, a braking resistor is added to the drive to allow the energy to flow out of the dc bus of the drive through a chopper transistor which ultimately allows for speed controlled braking. Hopefully, the drive you have will have provisions for the resistor and the other components that usually get included with resistor braking.

  3. Your drives absolutely need acceleration and deceleration ramps to have any hope at all of having the ability of positioning to a known point. Using linear speed ramps results in a simple calculation to determine when to slow down to reach the desired point. If you draw a graph with time in x and speed in y, you’ll see the result is a right triangle when the speed accels or decels. Since distance traveled is the area of the triangle, use the correct units and it becomes an easy 1/2 * base* height to determine the distance traveled. For example, if 1500 rpm = 10 feet per second and your decel ramp is 5 seconds to go from 1500 rpm to zero, the graph will be a triangle that is 10 units Y (fps) high and 5 X units long (time). So, when the stop command is issued and it takes 5 seconds to stop, you’ve traveled 0.5105 = 25 feet in those 5 seconds. Simple, right?

A parking sensor is also known as a Home sensor.

location of the sensor that controls location of the unit is not as had as one might think.

every shelf, every bin, can have targets the carriage only has to align to the targets. much like you do when parking at the store. you have no clue as to the actual distance traveled or alignment to your front door, just that the vehicle is aligned to the targets for that parking spot.

dave-in-nj:
location of the sensor that controls location of the unit is not as had as one might think. Every shelf, every bin, can have targets the carriage only has to align to the targets. much like you do when parking at the store. you have no clue as to the actual distance traveled or alignment to your front door, just that the vehicle is aligned to the targets for that parking

I don't know about you, but I have learned that it is better to know where you've parked the car...

That approach requires that the targets be encoded so that you know where you have stopped. When it's all said and done, it is easier to keep track of where you've been to know where you are. You will ultimately get to your destination faster :wink:

All of you have some very good feed back. This is the speed controller and motor that I have. Tekin - RX8 1/8 Electronic Speed Control
It has its own ramp and throttle control that I do not have to worry about. It will not miss steps it actually uses the three hall effect sensors built into the motor to accelerate smoothly. I can take very large amount of amperage abuse seeing as its make to take a 10 or so pound car to 60 miles an hour and back down to zero over and over again in a 10 or so minute race. Right now I'll be moving a 10 lb sled 20 miles an hour and that is by gearing at full speed so I now I'm not going to overheat it or put to much load on it. My 1/8th scale car can lock all four tires up if I want it to and stop within a few feet. Here is a youtube video of some of the gas 1/8th scales motor running on an RC track these are gas and the the electrics are quite a bit faster. So If I feed it a full throttle the speed controller will accelerate as fast as it can without skipping a beat. It even adjust motor timing. In the speed controller software I can add and take away this. Please don't take as I know more by any means I am very new and I know RC cars very well and programming I don't. I think that you are right I want to acc and decel as you say but right now I don't know where the gas and brake pedal is. So can we try that first and try then try to pull up to the stop sign without locking up the brakes LOL. I have read some sketches with accel and decel but right now I'm trying to just get the arduino to get it to initialize the speed controller. Actually I just figured that out. I had to feed it the nuetral position for about 5 seconds in the void setup so that it now it was being controlled. but I still can't get it to read the hall sensor and control the servo using the same sketch.

styler93gsx:
still can't get it to read the hall sensor and control the servo using the same sketch.

Divide and conquer. Can you read the hall sensor? Can you control the servo? Don't worry about combining them into a single sketch until you know how to do both separately.

How fast is it turning? You may be missing events because of the delay(15).

Yes I can do both independently just not at the same time.Here is what I have currently. If I hit the reset pin on this sketch and turn on the speed controller at the same time my speed controller will initialize. That is why before the loop I gave my speed controller the 89. I used the servo library to control the speed controller and 89 is it neutral position 180 is its full throttle forward and 0 is full throttle reverse.

#include <Servo.h>

Servo speedcontroller; // create servo object to control a servo
const int hallPin = 2; // the pin that the pushbutton is attached to ???
const int ledPin = 13; // the led to come on if a hall signal is recieved
int hallcounter = 0; // counter for the number of hall occurences
int hallState = 0; // current state of the button
int lasthallState = 0; // not sure why I need this the other sketch had it
int pos = 0; // variable to store the servo position ???
int pin = 13; // not sure if I need this twice ???
volatile int state = LOW; // not sure why I need this ???

void setup()
{
Serial.begin(9600); // starts serial
speedcontroller.attach(9); // attaches the speed controller on pin 9
speedcontroller.write(89); // tell servo to go to position in variable ‘pos’
delay(4000); // this allows the speed controller to do its inialization
pinMode(hallPin, INPUT); // this is my hall pin input
pinMode(ledPin, OUTPUT); // this turns on every time it gets a hall input so I know its getting the signal
}
void loop()
{
speedcontroller.write(90); // tell speedcontroller to go fwd
delay(2000);
speedcontroller.write(89); // tell speedcontroller to go stop
delay(2000);
speedcontroller.write(79); // tell speedcontroller to go rev
delay(2000);
speedcontroller.write(89); // tell speedcontroller to go stop
delay(2000);
}

This sketch allows me to allows me to read my hall effect sensor and print the count of my rotations. It is the basic example from the IDE. Its the state change detection. Although I have to manually turn the motor by hand. If I use my RC remote control to control the motor it picks up in low rpms but it doesn’t read fast enough to print on the serial. Or it may be because its printing to the serial port it slows the program down looses count. I think I need to use the mechanical external interrupt pin I just now quite sure how to do this and still let it keep count accuratley.

int buttonPushCounter = 0; // counter for the number of button presses
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button

void setup() {
// initialize the button pin as a input:
pinMode(buttonPin, INPUT);
// initialize the LED as an output:
pinMode(ledPin, OUTPUT);
// initialize serial communication:
Serial.begin(9600);
}

void loop() {
// read the pushbutton input pin:
buttonState = digitalRead(buttonPin);

// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
// if the state has changed, increment the counter
if (buttonState == HIGH) {
// if the current state is HIGH then the button
// wend from off to on:
buttonPushCounter++;
Serial.println(“on”);
Serial.print("number of button pushes: ");
Serial.println(buttonPushCounter);
}
else {
// if the current state is LOW then the button
// wend from on to off:
Serial.println(“off”);
}
}
if (buttonPushCounter % 4 == 0) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}

}