Let me preface this by saying that I am immensely proud of this work. The work up to here is very special and I can only hope that my work going forward is as good as this.
So I’m calling this the “Final Static Prototype” because it’s pretty damn complete for being prototype and it does not move. I intend on making a moving, non-flying prototype sometime in the future. Let’s start out with the video:
Now an explanation for each of the components starting with the controller.
It’s pretty much the same deal I’ve been using this entire time. The program works as follows.
1. The computer sends a delay value and a cycle number
2. The arduino receives that data
3. The arduino sends the debug switch value, the x and y values of the joystick and the pot value.
4. The program renders that information on the program.
Here’s the controller’s source:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
//include/define #include <string.h> // we'll need this for subString #define MAX_STRING_LEN 20 // like 3 lines above, change as needed. //Mux control pins int s0 = 8; int s1 = 9; int s2 = 10; int s3 = 11; int SIG_pin = 0; //Shift Register Pins int SER_Pin = 5; //pin 14 on the 75HC595 int RCLK_Pin = 6; //pin 12 on the 75HC595 int SRCLK_Pin = 7; //pin 11 on the 75HC595 #define number_of_74hc595s 1 //How many of the shift registers - change this #define numOfRegisterPins number_of_74hc595s * 8 //do not touch boolean registers[numOfRegisterPins]; //serial stuff const char EOPmarker = '.'; //This is the end of packet marker char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming. //other pin setup int joystick_x; int joystick_y; int pot_1; int debug_switch = 4; //vars int sample_delay; int cycle_number; void setup(){ //mux setup pinMode(s0, OUTPUT); pinMode(s1, OUTPUT); pinMode(s2, OUTPUT); pinMode(s3, OUTPUT); digitalWrite(s0, LOW); digitalWrite(s1, LOW); digitalWrite(s2, LOW); digitalWrite(s3, LOW); //shift register setup pinMode(SER_Pin, OUTPUT); pinMode(RCLK_Pin, OUTPUT); pinMode(SRCLK_Pin, OUTPUT); pinMode(0, INPUT); clearRegisters(); writeRegisters(); //other pin setup pinMode(debug_switch, INPUT); Serial.begin(115200); } void loop(){ //start of main loop ------------------------------------------- //delay(25); pin_remap(); if (Serial.available() > 0) { static int bufpos = 0; char inchar = Serial.read(); if (inchar != EOPmarker) { serialbuf[bufpos] = inchar; bufpos++; } else { serialbuf[bufpos] = 0; //restart the buff bufpos = 0; //restart the position of the buff sample_delay = atoi(subStr(serialbuf, "," , 1)); cycle_number = atoi(subStr(serialbuf, "," , 2)); serial_handshake(); //delay(100); } } delay(sample_delay); } //end of main loop -------------------------------------------------------- //start of logic functions ------------------------------------------------ void serial_output_deploy(){ Serial.print("0"); Serial.print(","); Serial.print(joystick_x); Serial.print(","); Serial.print(joystick_y); Serial.print(","); Serial.print(pot_1); Serial.print(","); Serial.print(sample_delay); Serial.print(","); Serial.print(cycle_number); Serial.println(""); } void serial_output_debug(){ Serial.print("1"); Serial.print(", "); Serial.print("Joystick X Axis: "); Serial.print(joystick_x); Serial.print(" , "); Serial.print("Joystick Y Axis: "); Serial.print(joystick_y); Serial.print(" , "); Serial.print("Speed Potentiometer: "); Serial.print(pot_1); Serial.print(" , "); Serial.print("Amount of delay between cycles: "); Serial.print(sample_delay); Serial.print(" , "); Serial.print("Cycle Number:"); Serial.print(cycle_number); Serial.println(""); } void pin_remap(){ joystick_x = map(readMux(15), 0, 1023, 180, 0); joystick_y = map(readMux(14), 0, 1023, 0, 180); pot_1 = map(readMux(13), 0, 1023, 0, 179); } void serial_handshake(){ if (digitalRead(debug_switch) == HIGH){ serial_output_debug(); setRegisterPin(1, HIGH); setRegisterPin(2, LOW); writeRegisters(); } if (digitalRead(debug_switch) == LOW){ serial_output_deploy(); setRegisterPin(2, HIGH); setRegisterPin(1, LOW); writeRegisters(); } } //end of logic functions -------------------------------------------------- void clearRegisters(){ for(int i = numOfRegisterPins - 1; i >= 0; i--){ registers[i] = LOW; } } void writeRegisters(){ digitalWrite(RCLK_Pin, LOW); for(int i = numOfRegisterPins - 1; i >= 0; i--){ digitalWrite(SRCLK_Pin, LOW); int val = registers[i]; digitalWrite(SER_Pin, val); digitalWrite(SRCLK_Pin, HIGH); } digitalWrite(RCLK_Pin, HIGH); } //set an individual pin HIGH or LOW void setRegisterPin(int index, int value){ registers[index] = value; } int readMux(int channel){ int controlPin[] = {s0, s1, s2, s3}; int muxChannel[16][4]={ {0,0,0,0}, //channel 0 {1,0,0,0}, //channel 1 {0,1,0,0}, //channel 2 {1,1,0,0}, //channel 3 {0,0,1,0}, //channel 4 {1,0,1,0}, //channel 5 {0,1,1,0}, //channel 6 {1,1,1,0}, //channel 7 {0,0,0,1}, //channel 8 {1,0,0,1}, //channel 9 {0,1,0,1}, //channel 10 {1,1,0,1}, //channel 11 {0,0,1,1}, //channel 12 {1,0,1,1}, //channel 13 {0,1,1,1}, //channel 14 {1,1,1,1} //channel 15 }; //loop through the 4 sig for(int i = 0; i < 4; i ++){ digitalWrite(controlPin[i], muxChannel[channel][i]); } //read the value at the SIG pin int val = analogRead(SIG_pin); //return the value return val; } char* subStr (char* input_string, char *separator, int segment_number) { char *act, *sub, *ptr; static char copy[MAX_STRING_LEN]; int i; strcpy(copy, input_string); for (i = 1, act = copy; i <= segment_number; i++, act = NULL) { sub = strtok_r(act, separator, &ptr); if (sub == NULL) break; } return sub; } |
Now for the output simulator (eventually the plane)
This works like the controller with the “handshake” protocol as described above, but it writes to the servos and then sends sensor values. Here’s that source:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
//include/define #include <string.h> // we'll need this for subString #define MAX_STRING_LEN 20 // like 3 lines above, change as needed. #include <LiquidCrystal.h> //we'll need this for the lcd LiquidCrystal lcd(22, 24, 26, 28, 32, 34); //pins for the lcd, I set it up using the ladyada tutorial. #include <Servo.h> //inputs int debug_switch = 7; //outputs Servo left_servo; Servo right_servo; Servo esc; int esc_pwm = 6; int debug_led = 11; int deploy_led = 12; //numbers int left_servo_pos; int right_servo_pos; int current; //serial stuff const char EOPmarker = '.'; //This is the end of packet marker char serialbuf[32]; //This gives the incoming serial some room. Change it if you want a longer incoming. //shift register setup int SER_Pin = 8; //pin 14 on the 75HC595 int RCLK_Pin = 9; //pin 12 on the 75HC595 int SRCLK_Pin = 10; //pin 11 on the 75HC595 #define number_of_74hc595s 1 //How many of the shift registers - change this #define numOfRegisterPins number_of_74hc595s * 8 //do not touch boolean registers[numOfRegisterPins]; void setup(){ //lcd.begin(16, 2); left_servo.attach(3); right_servo.attach(5); esc.attach(6); current = 0; pinMode(debug_switch, INPUT); pinMode(1, INPUT); pinMode(debug_led, OUTPUT); pinMode(deploy_led, OUTPUT); pinMode(SER_Pin, OUTPUT); pinMode(RCLK_Pin, OUTPUT); pinMode(SRCLK_Pin, OUTPUT); pinMode(esc_pwm, OUTPUT); // for(int i = 0; i < 180; i += 1){ // esc.write(i); // Serial.println(i); // delay(15); // } clearRegisters(); writeRegisters(); Serial.begin(115200); //changing this to other speeds has not been tested using this meathod } void loop() { if (Serial.available() > 0) { //lcd.clear(); static int bufpos = 0; char inchar = Serial.read(); if (inchar != EOPmarker) { serialbuf[bufpos] = inchar; bufpos++; } else { serialbuf[bufpos] = 0; //restart the buff bufpos = 0; //restart the position of the buff if(digitalRead(debug_switch) == HIGH){ debug(); } if(digitalRead(debug_switch) != HIGH){ deploy(); } out_deploy(); } } } // below is just function logic, which I do not fully understand. but it works. char* subStr (char* input_string, char *separator, int segment_number) { char *act, *sub, *ptr; static char copy[MAX_STRING_LEN]; int i; strcpy(copy, input_string); for (i = 1, act = copy; i <= segment_number; i++, act = NULL) { sub = strtok_r(act, separator, &ptr); if (sub == NULL) break; } return sub; } void clearRegisters(){ for(int i = numOfRegisterPins - 1; i >= 0; i--){ registers[i] = LOW; } } void writeRegisters(){ digitalWrite(RCLK_Pin, LOW); for(int i = numOfRegisterPins - 1; i >= 0; i--){ digitalWrite(SRCLK_Pin, LOW); int val = registers[i]; digitalWrite(SER_Pin, val); digitalWrite(SRCLK_Pin, HIGH); } digitalWrite(RCLK_Pin, HIGH); } //set an individual pin HIGH or LOW void setRegisterPin(int index, int value){ registers[index] = value; } void spinto(int target) { //digitalWrite(led2, LOW); while(current > target){ Serial.println(current); esc.write(current); delay(15); current--; } while(current < target){ Serial.println(current); esc.write(current); delay(15); current++; } } void debug(){ setRegisterPin(2, HIGH); setRegisterPin(1, LOW); writeRegisters(); left_servo_pos = atoi(subStr(serialbuf, ",", 1)); lcd.write("Lft Servo:"); lcd.write(subStr(serialbuf, ",", 1)); //witres the first bit of content before the first comma (or other seperator) to the lcd left_servo.write(left_servo_pos); lcd.setCursor(0, 1); right_servo_pos = atoi(subStr(serialbuf, ",", 2)); lcd.write("Rgt Servo:"); //this signifies that the first seperation has occured lcd.write(subStr(serialbuf, ",", 2)); //same thing as 2 lines above, but with the second parts. this can be repeated right_servo.write(right_servo_pos); analogWrite(esc_pwm, atoi(subStr(serialbuf, ",", 3))); } void deploy(){ setRegisterPin(2, LOW); setRegisterPin(1, HIGH); writeRegisters(); left_servo.write(atoi(subStr(serialbuf, ",", 1))); right_servo.write(atoi(subStr(serialbuf, ",", 2))); analogWrite(esc_pwm, atoi(subStr(serialbuf, ",", 3))); } void out_deploy(){ Serial.print(analogRead(0)); Serial.print(","); Serial.print(analogRead(1)); Serial.print(","); Serial.print(analogRead(2)); Serial.println(""); } //esologic.com //Thanks to http://arduino.cc/forum/index.php?topic=119429 |
The visual basic program which I’m calling “Vehicle Companion” can be found here in all of it’s glory. The picture below also shows the whole system.
Now all I need is the money to make this thing wireless because I’ve got a way to make it into a moving prototype using materials I already have. I’ll put a donate button somewhere on this website eventually if you want to help me out.
Thanks for reading.