Hi.
I have a question - might be trivial. I am on my way to control a motor in both directions, using a MegaMoto shield. The thing is - changing direction is done by changing the PWM-outputpin, but when i do that, the old outputpin is still HIGH thereby making the motor act like a brake. So i need a way to flip between the pins and at the same time setting the last used as LOW. I have of cause tried adding a line of code at the end, changing both pins to low, but that seems like it is adding a lot of delay to the system and also making the motor change direction a few times before rotating in the desired direction. the same goes for adding a pull-down.
MrBear:
I have of cause tried adding a line of code at the end, changing both pins to low, but that seems like it is adding a lot of delay to the system and also making the motor change direction a few times before rotating in the desired direction.
You must be doing it wrong - what you're describing could be done in a fraction of a millisecond, far faster than the motor could react. I suggest you post your code, perhaps we can suggest how to improve it.
Post my code........ hmm.. okay, you asked for it.
I am very new to this (Arduino and code in general) so please leave me with some useful criticism that can help me get better.
What happens when loading this to the Arduino, is that the motor will spin in one direction (the initial one), but if i try to change direction the motor acts like a brake (the motor leads are shortened) and stay this way.
Here it is:
#include <PID_v1.h>
//Define Variables we'll be connecting to
double SetpointPin = A5; //Setpoint from transducer
double InputPin = 0; //Feedback signal
double OutputPinCCW = 3; // OutputCCW (PWM)
double OutputPinCW = 11;
double Setpoint = 0;
double Input = 0;
double Output = 0;
int ENA = 8;
int CW = 7; //clockwise
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
void setup()
{
Serial.begin(9600); //Opens serial at 9600 bps
//initialize the variables we're linked to
pinMode(InputPin, INPUT); //are these necessary?
pinMode(SetpointPin, INPUT);
pinMode(OutputPinCCW, OUTPUT);
pinMode(ENA, OUTPUT);
//turn the PID on
myPID.SetMode(AUTOMATIC);
}
void loop()
{
digitalWrite(ENA, HIGH); // Leave on HIGH
if (digitalRead(CW) == HIGH) {
Input = analogRead(InputPin)*2; //returns voltage*0.5 if full H-bridge config
Input = map(Input,0, 611, 0, 1023); //input ranging from 0-3V, converting to 0-1023
Setpoint = analogRead(SetpointPin);
myPID.Compute();
analogWrite(11, Output);
}
if (digitalRead(CW) == LOW){
Input = analogRead(InputPin)*2;
Input = map(Input,0, 611, 0, 1023);
Setpoint = analogRead(SetpointPin);
myPID.Compute();
analogWrite(3, Output); //Output (PWM) on pin 11
}
Serial.write("OUTPUT:");
Serial.println(Output);
Serial.write("Setpointet er:");
Serial.println(Setpoint);
Serial.write("Inputtet er");
Serial.println(Input);
delay(2);
}
Thank you for your time, cant wait until i will be the one helping others out.
Input = analogRead(InputPin)*2; //returns voltage*0.5 if full H-bridge config
Input = map(Input,0, 611, 0, 1023); //input ranging from 0-3V, converting to 0-1023
Setpoint = analogRead(SetpointPin);
The analogRead and map functions deal with integers. Why are you using doubles?
Input and Setpoint are in the range 0 to 1023. Output will be in what range? I'd expect it to be in the same range, but you are using it as a PWM value, which needs to be in the range 0 to 255.
I have some useful remarks: please delete the sketch.
I'm serious, you should make a fresh start.
You want to read input pins, use a motor shield, write a sketch, use a PID library (never easy).... all at once.
Not even a advanced programmer would try this.
Forget the PID for now.
Try to get the motor running. How is the shield connected ?
The motor should be connected to X1-1 and X1-2.
You need an enable but also two PWM outputs PWMA and PWMB.
Write a sketch that makes the motor run, nothing else.
To declare an output pin, use this: const int pinname = 10;
Not a 'double'.
Write to the serial monitor what you are doing, like this: Serial.println("Forward for 5 seconds");
Use delays between the actions, and let the motor run forward, backward, slow, fast.
I have some useful remarks: please delete the sketch. DONE
I'm serious, you should make a fresh start.
You want to read input pins, use a motor shield, write a sketch, use a PID library (never easy).... all at once.
Not even a advanced programmer would try this.
Forget the PID for now.
Try to get the motor running. How is the shield connected ? mounted on top of the Arduino (is that not the idea/function of a shield?)
The motor should be connected to X1-1 and X1-2. What is that?
You need an enable but also two PWM outputs PWMA and PWMB.
Write a sketch that makes the motor run, nothing else.
To declare an output pin, use this: const int pinname = 10;
Not a 'double'.
Write to the serial monitor what you are doing, like this: Serial.println("Forward for 5 seconds");
Use delays between the actions, and let the motor run forward, backward, slow, fast.
But what's the PID for anyway?- are you actually reading a sensor to give you a setpoint that the PID homes to? (I haven't looked at that sketch closely, not even sure what that setpoint is... position? I see PID examples around which make a DC motor into a servo... is this one of them? Where did the code come from and what's it for?)
But I'm with Krodal on this, that there's too much to get going first time round the block, especially since you are new to both Arduino and coding....
MrBear:
The motor should be connected to X1-1 and X1-2. What is that?
I'm sorry, I was looking at the schematic, I should have been looking at the user manual.
Can you perhaps make a photo of the jumpers and attach it, so we can check the Arduino pins you use.
The normal way for a H-bridge mode seems this:
PWMA to D11
PWMB to D3
ENABLE to D8
SENSOR : jumper between A3 and A2 and A0, see figure 3 and 4 in user manual.
I would write the code like this:
const int pinPWMA 11;
const int pinPWMB 3;
const int pinENABLE 8;
const int pinSENSOR 0; // analog input
Set the mode of the pins, set one pin high, the other low, and see the motor run.
Change the high and low for the pins, and the motor should run in the opposite direction.
The control signal (signal into the Arduino) is a +-5V where - = CW and + = CCW rotation. This signal is generated by a torque transducer. As an input signal is given to the Arduino, the motor must produce a torque and continue to do so, even after the motor has stopped because the load is greater than the torque produced from the motor.
You can think of it as a motor connected to a spring. When an input signal of eg. +2V the motor has to turn CCW with a torque 2/5 of maximum, hereby extending the spring - at some point the force from the spring will be the same as the torque/force from the motor and then then the system has reached an equilibrium. if you apply a higher input the motor will start turning CCW again and if you lower the signal the motor will unroll the spring until a new equilibrium has been reached. If no signal is provided the motor must become "loose" and the spring will be the only force (neglecting friction) in the system.
Some will probably ask me why i dont just use a position servo so i will reveal right away that i need to control the torque, NOT the position.
My guess is that i can use a closed loop servo approach, but instead of the feedback signal being a encoder it will be a current measurement. I want to use the current sensors in the motor shield hereby generating an error signal for the feedback loop. The error signal will result in a change in the PWM cycle in order to reduce the error so the produced torque will actually reach the desired value. Is that right?
The system has to end up being a steer by wire system with haptic feedback. Because it will be a steering-mechanism it is important that there is no overshoot, thats why i think that the PID (or maybe PI only) is important to incorporate!
I am using the pins just as in the manual, and as you are describing.
For now i have added a pot as the torque transducer (it easier to test with) and the motor connected is not the one i will be using (see previous post).
I suggest to continue with a very small sketch, just to make the motor run in both directions and with PWM.
A function that controls the motor would be needed. Perhaps with an integer parameter from -1000 to +1000. The sign is the direction and '0' would be a 'stop'.
But first you have to get to know the MegaMotor shield. Just try a few things.
I don't know about using the current feedback. A PID and a current feedback will create a torque. So far I understand it, but I don't know how it will be if you actually use it for real.
Thanks for the reply.
Well, for PMDC motors the torque is proportional to current - the motor-shield i have, has an analog current sensor that provides a voltage to the Arduino. You can monitor this with the Arduino to give torque feedback as torque is equal to T=Kt*I, where T is torque, Kt is the motor torque constant, and I is the current. I need a linearly increasing output torque with respect to my input (torque transducer).
const int pinPWMA = 11;
const int pinPWMB = 3;
const int pinENABLE = 8;
const int pinTRANSDUCER = 5; // analog input (for now a POT)
int Setpoint = 5;
int CW = 7;
void setup()
{
pinMode(pinPWMA, OUTPUT);
pinMode(pinPWMB, OUTPUT);
pinMode(pinENABLE, OUTPUT);
pinMode(pinTRANSDUCER, INPUT);
pinMode(Setpoint, INPUT);
pinMode(CW, INPUT);
Serial.begin(9600);
digitalWrite(pinENABLE, HIGH);
delay(500);
digitalWrite(pinENABLE, LOW);// Reset overcurrent or overtemp fault. May need to let the MegaMoto cool.
delay(500);
digitalWrite(pinENABLE, HIGH);
}
void loop()
{
if (digitalRead(CW) == HIGH) {
digitalWrite(pinPWMB, LOW);
digitalWrite(pinPWMA, HIGH);
/*Setpoint = analogRead(pinTRANSDUCER);
analogWrite(pinPWMA, Setpoint / 4);
*/
}
else {
digitalWrite(pinPWMA, LOW);
digitalWrite(pinPWMB, HIGH);
/*Setpoint = analogRead(pinTRANSDUCER);
analogWrite(pinPWMB, Setpoint / 4);
*/
}
Serial.write("Transducer input:");
Serial.println(Setpoint);
delay(10);
}
I am still having problems with the motor switching direction a few times when i connect CW to 3.3V (change direction) before "settling " in the correct direction. as you can see in the sketch i have tried with adjusting the speed and full speed.
Also, when i get close to the pin with my finger, it does the same (switch direction) - do i need to add a pulldown or something to prevent that?
You are doing fine.
But I would like to make smaller steps.
Don't use any input for now.
Can you try this:
Make the motor run; wait some time; run motor in other direction. You have that almost. Perhaps you can make a function for it.
Make a sketch to test the inputs and write strings to the serial monitor like this : Serial.println("Input is now high");
Only after that make a sketch that combines both.
I don't understand how you use the 3 inputs, but if an input is not connected, it can be anything and (barely) touching it has a big influence. The impedance of the inputs is very high.
MrBear:
Some will probably ask me why i dont just use a position servo so i will reveal right away that i need to control the torque, NOT the position.
You could use torque feedback to control the position of a standard servo just as easily as you could use it to control the torque of a DC motor - probably more easily in fact, since the servo already incorporates a feedback system which ensures that it meets your demanded position accurately, whereas you can only guess at the approximate relationship between current and torque from a DC motor since the relationship varies all over the places as the motor moves.
If you can get a servo capable of providing the torque you need, I recommend that you use that instead of the motor.
After installing a button everything is working well.
Now i have control of the speed and the direction of the motor.
So i guess the next step is PID? or am i goint too fast again?
@PeterH
You are probably right, but this is proof of concept on a patent. So i MUST build a system that works by reading a torque transducer and using that signal to apply torque (not position controlled) to the wheels on the road in order to make them turn.
MrBear:
So i guess the next step is PID? or am i goint too fast again?
No, you are right on track.
But what about a single function that controls the speed and direction of the motor ? Like I wrote before with a parameter from -1000 to +1000. That way the PID can be set to those limits and the function will take care of the direction.