I am trying to write code that will gradually increase speed to each of my ROV motors when called upon via serial.print. To avoid any jerking motion I am trying to use the following syntax " for(int i = 0 ; i <= 255; i++) " . How do I get the command to stop at 255 and not go back to 0. Any help would be greatly appreciated.
" for(int i = 0 ; i <= 255; i++) "
Will generate all values of i from 0 to 255 inclusive.
However, at the end of the loop, the value of "i " will be 256 (0x100).
If you try writing this to a byte-wide variable, the result will be zero.
Can you post your code, please?
char val; //Data received from the serial port
int i = 0;
void setup()
{
Serial.begin(9600);
Serial.print(170, BYTE); //Serial Baudrate Set for Sabertooth 2x5 serial mode
delay(2000);
}
void loop(){
if (Serial.available()){ //If data is available to read,
val = Serial.read(); //read it and store it as val
}
for( i = 0 ; i <= 127; i++){ //gradual speed increase
if (val == 'H'){ //If H is recieved (Forward Thrust Key)
Serial.print (128); //Motor Controller Address
Serial.print (0); //Command 0 = Drive Motor 1 Forward
Serial.print (i); // Speed 0 = Stop, 127 = Full Power
Serial.print ((128+0+i) & B01111111, BYTE); //required checksum
} else {
Serial.print(128);
Serial.print (0);
Serial.print (0); //Speed = 0/ Stop
Serial.print ((128+0+0) & B01111111, BYTE);
}
}
}
Just started writing the code. Here is what I have
Don't you want your "for" loop to be part of the "if (Serial.available)"?
Don't forget, when the "for" loop completes, you'll re-enter "loop ()" with the same value of "val". You may not have any characters for a command, but you'll still execute the "for" loop.
Ok, so I should have it set like this.
void loop(){
if (Serial.available()){ //If data is available to read,
val = Serial.read(); //read it and store it as val
for( i = 0 ; i <= 127; i++){ //gradual speed increase
}
Please forgive my ignorance with code. Never wrote code in my life until I found out about Arduino a couple of weeks ago. I immediately ordered one, read the book Processing last week, and I am now obsessed with this wonderful micro controller. I really do appreciate any help that you or anyone else could give me, thanks.
Please forgive my ignorance with code.
Absolutely no need to apologise - we've all been there.
I can't comment on specifics of your speed controller, but from the manual, what you're doing looks to be sensible.
A couple more things - you may need to put a "delay" at the end of your "for" loop. At the moment the only delay you've got between one speed step and the next is the time it takes to transmit the commands.
At 960 characters per second, and 4 characters per command, you're going to go through the entire 0...127 speed range in about half a second.
Also, the two second delay in "startup ()" should come before the auto-baud select character "170" (p.15 of the pdf manual)
Also, you may find it helpful to create a function to send the speed command to the motors. This would simplify things if you wanted to add functionality to the main loop and it makes your code easier to read. Not sure if this is exactly what you want but hopefully gives you an idea of how to proceed:
void sendSpeed( int speed)
{
Serial.print (128); //Motor Controller Address
Serial.print (0); //Command 0 = Drive Motor 1 Forward
Serial.print (speed); // Speed 0 = Stop, 127 = Full Power
Serial.print ((128 + speed) & B01111111, BYTE); //required checksum
}
void loop(){
if (Serial.available()) //If data is available to read,
{
val = Serial.read(); //read it and store it as val
if (val == 'H') //If H is recieved (Forward Thrust Key)
{
for( i = 0 ; i <= 127; i++) //gradual speed increase
{
sendSpeed(i);
// add a delay here as per AWOL's suggestion
}
}
else
{
sendSpeed(0);
}
}
}
You may want to enhance the sendSpeed function so in addition to the speed parameter, it takes a parameter identifying the motor. You could also add a parameter for motor direction.
OK, how does this look?
char val; //Data received from the serial port
int i = 0;
void setup()
{
Serial.begin(9600);
delay(2000);
Serial.print(170, BYTE); //Serial Baudrate Set for Sabertooth 2x5 serial mode
}
void loop(){
if (Serial.available()){ //If data is available to read,
val = Serial.read(); //read it and store it as val
for( i = 0 ; i <= 127; i++){ //gradual speed increase
delay(1000);
}
if (val == 'H'){ //If H is recieved (Forward Thrust Key)
Serial.print (128, BYTE); //Motor Controller Address
Serial.print (0, BYTE); //Command 0 = Drive Motor 1 Forward
Serial.print (i, BYTE); // Speed 0 = Stop, 127 = Full Power
Serial.print ((128+0+i) & B01111111, BYTE); //required checksum
} else {
Serial.print(128, BYTE);
Serial.print (0, BYTE);
Serial.print (0, BYTE); //Speed = 0/ Stop
Serial.print ((128+0+0) & B01111111, BYTE);
}
}
}
You need to send the motor commands between the for loop and the delay. If you don't want to use the sendSpeed method, replace the two places this is called in the example I posted above with the four Serial.print commands
The logic is:
For speed values between 0 and 127, send this speed to the motor, then wait 1 second before doing the next speed value
Thanks for the tip mem. I was just trying to read up on how functions work. There wasn't that much on them in any of the beginner books I read.
You may find this page helpful: http://www.arduino.cc/en/Reference/FunctionDeclaration
I think the sendSpeed method is the way to go. There will be a total of 5 motors and it could get messy.
I would go about it this way:
Create a library called something like Motor.
The implement, for instance, these functions:
- void update();
- void setSpeed( uint speed );
- void setTargetSpeed( uint speed );
- uint getSpeed();
Then you could do something like:
if (Serial.available() ){
char recieved = Serial.read();
byte speedModifier = 0;
switch (recieved){
case 'H': speedModifier=1; break;
case 'L': speedModifier=-1; break;
}
motor.setSpeed( motor.getSpeed() + speedModifier );
}
motor.update();
It wil result in a linear acceleration.
An alternative solution, if the speed is supposed to be either FULL_FORWARD or STOP you could do it more like this:
if (Serial.available() ){
char recieved = Serial.read();
switch (recieved){
case 'H': motor.setTargetSpeed(FULL_FORWARD); break;
case 'L': motor.setTargetSpeed(STOP); break;
}
}
motor.update();
AlphaBeta, kgdesign says he has never written any code before starting this project a few weeks ago. Although writing a library is a good approach for experienced coders like you, I would think it will be easier for him if he starts off with just some simple functions in his sketch.
mem I think you may be right, but thanks AlphaBeta.
Ok, so how does this look.
char val; //Data received from the serial port
int i = 0;
void setup()
{
Serial.begin(9600);
delay(2000);
Serial.print(170, BYTE); //Serial Baudrate Set for Sabertooth 2x5 serial mode
}
void sendSpeed(int motor, int direction, int speed)
{
Serial.print (motor, BYTE); //Motor Controller Address
Serial.print (direction, BYTE); //Command 0 = Drive Motor 1 Forward
Serial.print (speed, BYTE); // Speed 0 = Stop, 127 = Full Power
Serial.print ((motor + direction + speed) & B01111111, BYTE); //required checksum
}
void loop(){
if (Serial.available()){ //If data is available to read,
val = Serial.read(); //read it and store it as val
if (val == 'H') //If H is recieved (Forward Thrust Key)
{
for( i = 0 ; i <= 127; i++) //gradual speed increase
{
sendSpeed(128, 0, i);
delay(1000);
}
}else{
sendSpeed(128,0,0);
}
}
}
AlphaBeta, kgdesign says he has never written any code before starting this project a few weeks ago. Although writing a library is a good approach for experienced coders like you, I would think it will be easier for him if he starts off with just some simple functions in his sketch.
Never wrote code in my life until I found out about Arduino a couple of weeks ago. I immediately ordered one, read the book Processing last week, and I am now obsessed with this wonderful micro controller. I really do appreciate any help that you or anyone else could give me, thanks.
@mem:
I figured that since he is interested in this Arduino thingy, and that he understood the principles and advantage of using functions right away, I presumed he might as well be interested in the aspects of Libraries and OOP.
And, ofcource, I would definitly help him through the promblems he might come across.
@kgdesign:
Sorry if my suggestion was discouraging.
My only intention was to offer my idea on the matter, and maby guide you to path for furher information and programming tricks.
When this is said; mem is right.
This problem could be sovled using a set of functions and variables in you sketch.
If you want to get it working quick, or just do not care about object oriented programming (what c++ is all about) you should solve it without objects.
If you, however; like a challenge, like 'clean code' and have the interest and apetite for learning, I would suggest getting hands dirty sooner rather than later.
Looks ok, but you may want to define some constants to identify the motor and direction, perhaps somthing like this:
// modify these constants as necessary for the correct values
const int FORWARD = 0;
const int REVERSE = 1;
const int MOTOR_A = 128;
char val; //Data received from the serial port
int i = 0;
void setup()
{
Serial.begin(9600);
delay(2000);
Serial.print(170, BYTE); //Serial Baudrate Set for Sabertooth 2x5 serial mode
}
void sendSpeed(int motor, int direction, int speed)
{
Serial.print (motor, BYTE); //Motor Controller Address
Serial.print (direction, BYTE); //Command 0 = Drive Motor 1 Forward
Serial.print (speed, BYTE); // Speed 0 = Stop, 127 = Full Power
Serial.print ((motor + direction + speed) & B01111111, BYTE); //required checksum
}
void loop(){
if (Serial.available()){ //If data is available to read,
val = Serial.read(); //read it and store it as val
if (val == 'H') //If H is recieved (Forward Thrust Key)
{
for( i = 0 ; i <= 127; i++) //gradual speed increase
{
sendSpeed(MOTOR_A, FORWARD, i);
delay(1000);
}
}
else{
sendSpeed(MOTOR_A, FORWARD,0);
}
}
}
the keyword const in the defines at the top help the compiler to optimize the code.
Wired it all up and nothing works. Does anyone have any idea?
mem, first I pasted your code in and nothing worked. Then I changed the baud rate from 9600 to 2400 and the motor slowly turned on when triggered. It took a long time to get up to top speed and it would not turn off. Any ideas?
Got it to work at 9600, but motor increases from 0 to 127 and then repeats non stop. How do I get it to increase from 0 to 127 and then remain at 127 until trigger is disengaged.