Offline
Newbie
Karma: 0
Posts: 44
|
 |
« on: December 01, 2012, 10:18:29 am » |
I've made post in different sections before concerning this project. As a Capstone Senior Design project my team is building an ROV......we are all Mechanical Engineers with no robotic experience making the programming difficult. My part of the project is to control this thing. We need to control 4 horizontal thrusters, two vertical thrusters, and a servo. I initially developed code that would take voltage analog inputs from the surface using joysticks and transmit this voltage to an arduino onboard the ROV via 50' of ethernet line. Noise may be a concern here so I am now working on serial communication using RS232. I was able to find several examples of serial communication on this website and I think I may now have functioning code, at least according to my testing with LEDs. The code receives inputs from an Arduino on surface in a form like this: <Case><Speed> and then executes the commands. The commands are not developed yet, I am just turning on LEDs right now and I have commented out some things for testing purposes. My question is this: What if anything could go wrong with this? How reliably will this behave? I think I have provided everything yall need to help me, if not let me know. Thankyou!
const char SOP = '<'; const char EOP = '>';
enum { Case, Speed };
int whichNumber = Case;
int Casev, Speedv;
//-------------------------------------------------------------------
void setup () { Serial.begin (9600); pinMode (3, OUTPUT); pinMode (4, OUTPUT); pinMode (5, OUTPUT); pinMode (6, OUTPUT); pinMode (7, OUTPUT); pinMode (8, OUTPUT); pinMode (9, OUTPUT); pinMode (10, OUTPUT); pinMode (11, OUTPUT); pinMode (12, OUTPUT); pinMode (13, OUTPUT); }
//-------------------------------------------------------------------
void processNumber (int n) { int x = n; switch (whichNumber) { case Case: Casev = x; whichNumber = Speed; //Serial.print (" Case = "); break; case Speed: Speedv = x; whichNumber = Case; //Serial.print (" Speed = "); break; } //Serial.print(x); } //------------------------------------------------------------------- void processInput () { static float receivedNumber = 0; static boolean False = false; byte c = Serial.read (); switch (c) { case EOP: if (False) processNumber (- receivedNumber); else processNumber (receivedNumber);
// fall through to start a new number case SOP: receivedNumber = 0; False = false; break; case '0' ... '9': receivedNumber *= 10; // receivedNumber = recievedNumber*10 receivedNumber += c - '0'; //receivedNumber = recievedNumber + (c - '0') break; case '-': False = true; break; } }
//------------------------------------------------------------------- void loop () { if (Serial.available ()) processInput (); int var1 = Casev; int var2 = Speedv; switch (var1) { //RIGHT case 1: analogWrite(3,var2); digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(12, LOW); // digitalWrite(13,LOW); break; //LEFT case 2: analogWrite(9,var2); digitalWrite(3,LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(12, LOW); // digitalWrite(13,LOW); break; //FWD case 3: analogWrite(10,var2); digitalWrite(3,LOW); digitalWrite(4, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(12, LOW); // digitalWrite(13,LOW); break; //REV case 4: analogWrite(6,var2); digitalWrite(3,LOW); digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(12, LOW); //digitalWrite(13,LOW); break; //CW case 5: digitalWrite(7,HIGH); digitalWrite(3,LOW); digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(12, LOW); // digitalWrite(13,LOW); break; //CCW case 6: digitalWrite(8,HIGH);
//digitalWrite(3,LOW); digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); digitalWrite(12, LOW); //digitalWrite(13,LOW); break; //SURFACE case 7: digitalWrite(4,LOW);
// digitalWrite(3,LOW); digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(10, LOW); digitalWrite(12, LOW); //digitalWrite(13,LOW); break; //DIVE case 8: digitalWrite(5,var2);
//digitalWrite(3,LOW); digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(12, LOW); digitalWrite(13,LOW); break; //PITCH case 9: analogWrite(12,var2); //digitalWrite(3,LOW); digitalWrite(4, LOW); digitalWrite(5, LOW); digitalWrite(6, LOW); digitalWrite(7, LOW); digitalWrite(8, LOW); digitalWrite(9, LOW); digitalWrite(10, LOW); // digitalWrite(13, LOW); break; //SERVO case 10: digitalWrite (13,HIGH); //digitalWrite(3,LOW); //...digitalWrite(4, LOW); // digitalWrite(5, LOW); //digitalWrite(6, LOW); //digitalWrite(7, LOW); //digitalWrite(8, LOW); //digitalWrite(9, LOW); //digitalWrite(10, LOW); //digitalWrite(12, LOW); break; } } //-------------------------------------------------------------------
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #1 on: December 01, 2012, 10:21:28 am » |
This is the code that transmits the serial data from the surface. It take analogy inputs from a joystick. //INPUTS int pot12 = A0; int pot34= A2; int potLR = A1;
//ADJUSTABLE PARAMETERS int frequency=256; float speedlimit= 1; // Value range: 0-1 (0-100%) int DEADBAND= 20;
//OUTPUT VALUES int val12 = 0; int val34= 0; int valLR = 0; int Fs= 0; int Bs= 0; int CWs=0; int CCWs=0; int Rs=0; int Ls=0; int fwd = 127-DEADBAND/2; int rev = 127+DEADBAND/2; int Cfwd = 255; int Crev = -255; int LEFT = 127-DEADBAND/2; int RIGHT = 127+DEADBAND/2; int Cleft= 255; int Cright= -255; int Case=0;
void setup() { Serial.begin(9600); ; pinMode(pot12, INPUT); pinMode(pot34, INPUT); pinMode(potLR, INPUT); }
//------------------------------------------------------------------- void loop() { // SET PWM valLR = analogRead(potLR)/4; //RIGHT if (valLR >= RIGHT ) { //Case 1 bumpright(); } //LEFT else if (valLR <= LEFT) { //Case 2 bumpleft(); } //FWD,REV OR CW,CCW SEE LOOP1234 else { //Case 3,4,5,6 loop1234(); } Serial.print('<'); Serial.print(10); Serial.print('>'); Serial.print('<'); Serial.print(255); Serial.print('>');
delay(100);
} //-------------------------------------------------------------------
void bumpleft() { Ls= (Cleft-(valLR))*speedlimit; //left speed Case=1; Serial.print('<'); Serial.print(Case); Serial.print('>'); Serial.print('<'); Serial.print(Ls); Serial.print('>'); } //------------------------------------------------------------------- void bumpright() { Rs=(Cright+2*(valLR))*speedlimit; //right speed Case=2; Serial.print('<'); Serial.print(Case); Serial.print('>'); Serial.print('<'); Serial.print(Rs); Serial.print('>'); } //-------------------------------------------------------------------
void loop1234(){ val12 = analogRead(pot12)/4; val34 = analogRead(pot34)/4;
Fs=(Cfwd-2*val12)*speedlimit; //forward speed Bs=(Crev+2*val12)*speedlimit; CWs=(Cfwd-2*(val34))*speedlimit; //clockwise speed CCWs=(Crev+2*(val34))*speedlimit;
//forward if (val12 <= fwd) { Case=3; Serial.print('<'); Serial.print(Case); Serial.print('>'); Serial.print('<'); Serial.print(Fs); Serial.print('>'); } //backwards else if (val12 >= rev) { Case=4; Serial.print('<'); Serial.print(Case); Serial.print('>'); Serial.print('<'); Serial.print(Bs); Serial.print('>'); } //loop to rotate CW/CCW else { if (val34 <= fwd) { Case = 5; Serial.print('<'); Serial.print(Case); Serial.print('>'); Serial.print('<'); Serial.print(CWs); Serial.print('>'); } else if (val34 >= rev) { Case=6; Serial.print('<'); Serial.print(Case); Serial.print('>'); Serial.print('<'); Serial.print(CCWs); Serial.print('>'); } else { off(); } } }
//-------------------------------------------------------------------
void off() { Case=7; Serial.print('<'); Serial.print(Case); Serial.print('>'); Serial.print('<'); Serial.print(0); Serial.print('>'); } //------------------------------------------------------------------- void setPwmFrequency(int pin, int divisor) { byte mode; if(pin == 5 || pin == 6 || pin == 9 || pin == 10) { switch(divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 64: mode = 0x03; break; case 256: mode = 0x04; break; case 1024: mode = 0x05; break; default: return; } if(pin == 5 || pin == 6) { TCCR0B = TCCR0B & 0b11111000 | mode; } else { TCCR1B = TCCR1B & 0b11111000 | mode; } } else if(pin == 3 || pin == 11) { switch(divisor) { case 1: mode = 0x01; break; case 8: mode = 0x02; break; case 32: mode = 0x03; break; case 64: mode = 0x04; break; case 128: mode = 0x05; break; case 256: mode = 0x06; break; case 1024: mode = 0x7; break; default: return; } TCCR2B = TCCR2B & 0b11111000 | mode; } } //-------------------------------------------------------------------
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Online
Brattain Member
Karma: 137
Posts: 19032
I don't think you connected the grounds, Dave.
|
 |
« Reply #2 on: December 01, 2012, 10:24:59 am » |
What if anything could go wrong with this? You could forget what pin 9 is connected to. Or pin 7...or just about any of those anonymous pins.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #3 on: December 01, 2012, 10:35:16 am » |
The commands are for testing right now, just turning LEDs on and off. The final code will have named pins. Are there any other concerns with the code?
|
|
|
|
|
Logged
|
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #4 on: December 01, 2012, 10:48:04 am » |
As a Capstone Senior Design project my team is building an ROV......we are all Mechanical Engineers with no robotic experience making the programming difficult. I find it hard to believe that your doing your culminating project with no experience in programming any kind of computer. The final code will have named pins. Why doesn't THIS code? Correcting bad habits later is much harder than learning good habits to start with. You've been told what you should do. The correct response is "I'll fix that right away", not "but that's not my problem".
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #5 on: December 01, 2012, 12:08:38 pm » |
Sorry was not trying to be rude or anything. I'll name the pins then re-post the code.
Capstone Design incorporates many disciplines, unfortunately my team has only Mechanical Engineers. We do have experience using MATLAB for mathematical/engineering problems. The projects are not provided by the school but by sponsors through the school. The sponsors give you the project scope and funding then you run with it. We did not have to use a micro controller, we could have used mechanical relays but the micro-controller is obviously superior. The Arduino makes this easier with lots of books and online help.
The point of the program is to use and engineering approach to develop a solution to a given problem. Some of the solutions may require, as is the case with this project, using knowledge outside of our discipline or seeking someone knowledgeable in said discipline, which is exactly what I am doing here.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #6 on: December 01, 2012, 12:19:33 pm » |
Code with named output variables: const char SOP = '<'; const char EOP = '>';
enum { Case, Speed };
int whichNumber = Case;
int Casev, Speedv; int M1A = 3; int M1B = 4; int M2A = 5; int M2B = 6; int MServ =11;
//-------------------------------------------------------------------
void setup () { Serial.begin (9600); pinMode (M1A, OUTPUT); pinMode (M1B, OUTPUT); pinMode (M2A, OUTPUT); pinMode (M2B, OUTPUT); pinMode (MServ, OUTPUT);
}
//-------------------------------------------------------------------
void processNumber (int n) { int x = n; switch (whichNumber) { case Case: Casev = x; whichNumber = Speed; //Serial.print (" Case = "); break; case Speed: Speedv = x; whichNumber = Case; //Serial.print (" Speed = "); break; } //Serial.print(x); } //------------------------------------------------------------------- void processInput () { static float receivedNumber = 0; static boolean False = false; byte c = Serial.read (); switch (c) { case EOP: if (False) processNumber (- receivedNumber); else processNumber (receivedNumber);
// fall through to start a new number case SOP: receivedNumber = 0; False = false; break; case '0' ... '9': receivedNumber *= 10; // receivedNumber = recievedNumber*10 receivedNumber += c - '0'; //receivedNumber = recievedNumber + (c - '0') break; case '-': False = true; break; } }
//------------------------------------------------------------------- void loop () { if (Serial.available ()) processInput (); int var1 = Casev; int var2 = Speedv; switch (var1) { //RIGHT case 1: analogWrite(M1A,var2); digitalWrite(M1B, LOW); digitalWrite(M2A, LOW); digitalWrite(M2B, LOW); break; //LEFT case 2: analogWrite(M1A,var2); digitalWrite(M1B, HIGH); digitalWrite(M2A, LOW); digitalWrite(M2B, LOW); break; //FWD case 3: analogWrite(M1A,var2); digitalWrite(M1B, LOW); digitalWrite(M2A, HIGH); digitalWrite(M2B, LOW); break; //REV case 4: analogWrite(M1A,var2); digitalWrite(M1B, LOW); digitalWrite(M2A, LOW); digitalWrite(M2B, HIGH); break; //CW case 5: analogWrite(M1A,var2); digitalWrite(M1B, HIGH); digitalWrite(M2A, LOW); digitalWrite(M2B, HIGH); break; //CCW case 6: analogWrite(M1A,var2); digitalWrite(M1B, LOW); digitalWrite(M2A, HIGH); digitalWrite(M2B, HIGH); break; //SURFACE case 7: analogWrite(M1A,LOW); digitalWrite(M1B, LOW); digitalWrite(M2A, LOW); digitalWrite(M2B, LOW); break; //DIVE case 8: analogWrite(M1A,var2); digitalWrite(M1B, HIGH); digitalWrite(M2A, HIGH); digitalWrite(M2B, HIGH); break; //PITCH case 9: analogWrite(M1A,HIGH); digitalWrite(M1B, LOW); digitalWrite(M2A, LOW); digitalWrite(M2B, HIGH); break; //SERVO case 10: digitalWrite (MServ,HIGH); //digitalWrite(3,LOW); //...digitalWrite(4, LOW); // digitalWrite(5, LOW); //digitalWrite(6, LOW); //digitalWrite(7, LOW); //digitalWrite(8, LOW); //digitalWrite(9, LOW); //digitalWrite(10, LOW); //digitalWrite(12, LOW); break; } } //-------------------------------------------------------------------
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
UK
Online
Brattain Member
Karma: 137
Posts: 19032
I don't think you connected the grounds, Dave.
|
 |
« Reply #7 on: December 01, 2012, 12:23:23 pm » |
void processNumber (int n) { int x = n; Why the reassignment? int M1A = 3; int M1B = 4; int M2A = 5; int M2B = 6; Are you planning on changing these pin assignments whilst the program is running? If not, consider making them constants.
|
|
|
|
|
Logged
|
Pete, it's a fool looks for logic in the chambers of the human heart.
|
|
|
|
Seattle, WA USA
Offline
Brattain Member
Karma: 312
Posts: 35483
Seattle, WA USA
|
 |
« Reply #8 on: December 01, 2012, 12:34:04 pm » |
Create some functions, with meaningful names, like turnRight(), turnLeft(), dive(), rise(), etc. Call them in the appropriate place(s) in loop(). Which is easier to grasp: case 1: analogWrite(M1A,var2); digitalWrite(M1B, LOW); digitalWrite(M2A, LOW); digitalWrite(M2B, LOW); break; or: case 1: turnRight(); break; The big advantage of functions is that you can debug them once. Comment out the whole loop() function. Create a new loop() function that does nothing but call turnRught(). Does the sub do what it is supposed to? If so, great. The function is working properly. If not, you can look at the logic of the function to see if there are errors, and you can look at the hardware. Is it connected to the right pins? If is powered correctly? Divide and conquer. Don't try to do everything at once.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #9 on: December 01, 2012, 12:40:45 pm » |
Thanks for the advice, when I have developed the final code I will post it. I'll clean it up and make logical names for what I want it to do. I have finals this week so it won't be until next week. It sounds like I am on the right track though. Thank you!
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #10 on: December 12, 2012, 10:21:58 am » |
I've cleaned the code up using some of the above suggestions. Here it is: //-------------------------------------------------------------------
#include <Servo.h> Servo servo;
//PINS const int M1A = 20; // M1---M4 ARE HORIZONTAL THRUSTERS const int M1B = 21; const int M2A = 22; const int M2B = 23; const int M3A = 24; const int M3B = 25; const int M4A = 26; const int M4B = 27; const int M5A = 28; // M5---M6 ARE VERTICAL THRUSTERS const int M5B = 29; const int M6A = 30; const int M6B = 31; const int M12 = 44; // M1 and M2 PWM const int M34 = 45; // M3 and M4 PWM const int M56 = 46; // M5 and M6 PWM const int servopin = 2;
//INCOMING DATA const char SOP = '<'; const char EOP = '>'; enum { Case, Speed };
//VARIABLES int whichNumber = Case; int Casev, Speedv; int pwmright; //1 int pwmleft; //2 int pwmfwd; //3 int pwmrev; //4 int pwmcw; //5 int pwmccw; //6 int pwmsurface; //7 int pwmdive; //8 int pwmpitch; //9 int valservo; //10
//-------------------------------------------------------------------
void setup () { Serial.begin (9600); pinMode (M1A, OUTPUT); pinMode (M1B, OUTPUT); pinMode (M2A, OUTPUT); pinMode (M2B, OUTPUT); pinMode (M3A, OUTPUT); pinMode (M3B, OUTPUT); pinMode (M4A, OUTPUT); pinMode (M4B, OUTPUT); pinMode (M5A, OUTPUT); pinMode (M5B, OUTPUT); pinMode (M6A, OUTPUT); pinMode (M6B, OUTPUT); pinMode (M12, OUTPUT); pinMode (M34, OUTPUT); pinMode (M56, OUTPUT); servo.attach(servopin);
}
//-------------------------------------------------------------------
void processNumber (int x) {
switch (whichNumber) {
case Case: Casev = x; whichNumber = Speed; break;
case Speed: Speedv = x; whichNumber = Case; break;
} }
//-------------------------------------------------------------------
void processInput () { static float receivedNumber = 0; static boolean False = false; byte c = Serial.read ();
switch (c) {
case EOP: if (False) processNumber (- receivedNumber); else processNumber (receivedNumber);
// fall through to start a new number case SOP: receivedNumber = 0; False = false; break;
case '0' ... '9': receivedNumber *= 10; // receivedNumber = recievedNumber*10 receivedNumber += c - '0'; //receivedNumber = recievedNumber + (c - '0') break;
case '-': False = true; break;
} }
//-------------------------------------------------------------------
void loop () { Serial.print(127); if (Serial.available ()) processInput (); int var1 = Casev; int var2 = Speedv;
switch (var1) {
//RIGHT case 1: pwmright = var2; moveright(); break;
//LEFT case 2: pwmleft = var2; moveleft(); break;
//FWD case 3: pwmfwd = var2; fwd(); break;
//REV case 4: pwmrev = var2; rev(); break;
//CW case 5: pwmcw = var2; cw(); break;
//CCW case 6: pwmccw = var2; ccw(); break;
//SURFACE case 7: pwmsurface = var2; surface(); break;
//DIVE case 8: pwmdive = var2; dive(); break;
//PITCH case 9: pwmpitch = var2; pitch(); break;
//SERVO case 10: valservo = var2; claw(); break;
}
} //-------------------------------------------------------------------1
void moveright() { }
//------------------------------------------------------------------- 2
void moveleft() { }
//------------------------------------------------------------------- 3
void fwd() { }
//------------------------------------------------------------------- 4
void rev() { }
//------------------------------------------------------------------- 5
void cw() { }
//------------------------------------------------------------------- 6
void ccw() { }
//------------------------------------------------------------------- 7
void surface() { }
//------------------------------------------------------------------- 8
void dive() { }
//------------------------------------------------------------------- 9
void pitch() { }
//------------------------------------------------------------------- 10
void claw() {
valservo = map(valservo, 0, 255, 0, 179); // scale it to use it with the servo (value between 0 and 180) servo.write(valservo); // sets the servo position according to the scaled value }
//-------------------------------------------------------------------
Data will be transmitted over 50' of wire using RS-232, how reliable can I expect this to be if the data transmission line is ran next to the power line of the ROV which will carry 20 amps? Also, would this code work using RS 485 communications? Am I missing anything obvious here?
|
|
|
|
|
Logged
|
|
|
|
|
nr Bundaberg, Australia
Offline
Tesla Member
Karma: 71
Posts: 6822
Scattered showers my arse -- Noah, 2348BC.
|
 |
« Reply #11 on: December 12, 2012, 11:30:58 am » |
Also, would this code work using RS 485 communications? RS-232, RS-485, makes no difference to your code if you use 485 in full duplex mode. Do you have 2 extra wires? ______ Rob
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #12 on: December 12, 2012, 11:22:34 pm » |
Should have 3 unused twisted pairs
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Tesla Member
Karma: 50
Posts: 6546
Arduino rocks
|
 |
« Reply #13 on: December 13, 2012, 12:12:00 am » |
You can run the rs232 type communication over cat3 four conductor phone wire (tx, rx, ground, and power/spare).
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 44
|
 |
« Reply #14 on: December 13, 2012, 11:15:02 am » |
If I wanted to go the full duplex RS 485 route, would this require 4 MAXRS485 convertors? Basically keeping one in transmit mode and one in receive mode on both sides of the CAT5 cable at all times and leaving the code as is?
|
|
|
|
|
Logged
|
|
|
|
|
|