Components and supplies
Arduino Nano R3
Tools and machines
3D Printer (generic)
Project description
Code
Portal turret w Radio (RED)
c_cpp
Code used for turret. This includes code that will enable control by the Master Turret Control, featured on another page. Different flavours require tweaking.
1// 2/* Portal Turret - Option With Radio!! 3 * Chris Nowak - Feb 2019 4 * https://www.instructables.com/member/ChrisN219/ 5 * https://create.arduino.cc/projecthub/Novachris/talking-portal-2-turret-gun-637bf3 6 * 7 * This code includes all the features needed to perform the Cara Mia Opera, 8 * Chat Time and Manual mode, as controlled by the Maseter Turret Control (MTC). 9 * The MTC is a separate controller featured on another build. The turret 10 * will operate autonomously using this code without the MTC. 11 * 12 * The code is built to work with three turrets, but each will operate independently. 13 * Lots of debugging code left in. Use or clean up as desired. It's mostly debugged, 14 * but isn't perfect. Given the price you paid, I figure that's ok! ;) 15 * ================= RED ==================== 16 */ 17 18#include <Wire.h> 19#include <VL53L0X.h> 20#include "Arduino.h" 21#include <SoftwareSerial.h> 22#include <Servo.h> 23#include <DFMiniMp3.h> 24#include <RF24.h> 25#include <RF24Network.h> 26#include <SPI.h> 27class Mp3Notify 28{ 29public: 30 static void OnError(uint8_t errorCode) 31 { 32 // see DfMp3_Error for code meaning 33 Serial.println(); 34 Serial.print("Com Error "); 35 Serial.println(errorCode); 36 } 37 static void OnPlayFinished(uint8_t globalTrack) 38 { 39 Serial.println(); 40 Serial.print("Play finished for #"); 41 Serial.println(globalTrack); 42 } 43 static void OnCardOnline(uint8_t code) 44 { 45 Serial.println(); 46 Serial.print("Card online "); 47 Serial.println(code); 48 } 49 static void OnCardInserted(uint8_t code) 50 { 51 Serial.println(); 52 Serial.print("Card inserted "); 53 Serial.println(code); 54 } 55 static void OnCardRemoved(uint8_t code) 56 { 57 Serial.println(); 58 Serial.print("Card removed "); 59 Serial.println(code); 60 } 61}; 62 63Servo servo_pivot; 64Servo servo_wings; 65Servo servo_pitch; 66VL53L0X sensor; 67 68// Setup for soundcard 69SoftwareSerial secondarySerial(4, 2); // RX, TX 70DFMiniMp3<SoftwareSerial, Mp3Notify> mp3(secondarySerial); 71 72// Setup for radio 73RF24 radio(10, 9); // nRF24L01 (CE,CSN) 74RF24Network network(radio); // Include the radio in the network 75const uint64_t this_node = 01; // This turret - Red - in Octal format ( 04,031, etc) 76const uint64_t WHT = 02; // Turret 02 - White 77const uint64_t BLU = 03; // Turret 03 - Blue 78const uint64_t MTC = 00; // Master Turret Control 79unsigned long previousMillis1 = 0; 80unsigned long previousMillis2 = 0; 81unsigned long previousMillis3 = 0; 82byte LED_LH_up = A1; 83byte LED_LH_down = A2; 84byte LED_CENTRE = A3; 85byte LED_RH_up = 7; 86byte LED_RH_down = 8; 87byte PIVOT = 6; //white 88byte WINGS = 3; //yellow 89byte PITCH = 5; //blue 90byte parkPIVOT = 96; //Smaller number rotates CW as viewed from the top 91byte posPIVOT = 96; 92byte maxPIVOT = 116; 93byte minPIVOT = 76; 94byte WINGclose = 165; 95byte WINGopen = 10; 96byte WINGpos = 160; 97byte parkPITCH = 86; 98byte posPITCH = 86; 99byte maxPITCH = 96; 100byte minPITCH = 75; 101byte pos = 90; 102byte pulse = 20; 103byte pitchCW = 1; 104byte pivotCW = 1; 105byte randomWake; 106byte randomOpen; 107byte randomFalse; 108byte randomStart; 109byte randomDisengage; 110int triggerDistance = 300; 111byte buttonStatus; 112byte busyRed = 1; 113byte restModeWhite; 114byte goState; 115int x; 116int y; 117byte pb1State; // Fire 118byte pb2State; // say random comment 119byte pb3State; 120byte randomPic; 121// Payload from Master Turret Control (MTC) 122// int payload [] = {0, 1, 2 , 3 , 4 , 5 }; 123// int payload [] = {x, y, pb1State, pb2State, pb3State, goState}; 124int payload [6]; 125 126/* This is the "conversation" map for "Chat Time". 127 * 0-99 = Red Turret sayings 128 * 100-199 = White Turret sayings 129 * 200-299 = Blue Turret sayings 130 * Files on all SD cards are saved as 0-100. 131 * Add 100 to the file number here for White, 200 for Blue. 132 * File 204 would be BLUE turret, file number 0004. 133 */ 134int chatSayings [] = { 135 0, // Start pause on i = 0, followed by "rounds"... 136 204, 164, 25, // 1 137 205, 127, 76, // 2 138 208, 162, 65, // 3 139 143, 230, 23, // 4 140 130, 41, 225, // 5 141 153, 31, 133, // 6 142 234, 49, 155, // 7 143 229, 175, 74, // 8 144 231, 58, 226, // 9 145 161, 223, 59, // 10 146 227, 68, 236, // 11 147 136, 50, 224, // 12 148 34, 160, 78, // 13 149 222, 42 // End 150}; 151 152/* This is the RED and WHITE turret timing map. They share sayings. 153 * These timings correspond to the time needed 154 * to play the individual sayings, in milliseconds. 155 * Change the sayings above as desired, but do not change these timings. 156 * For example, i = 2 will take 0.8 seconds (NormalTimings[2]) 157 * to play the chatSayings[2] file. 158 */ 159int NormalTimings [] = { 1601000, // Start pause on i = 0, followed by "rounds"... 1612600, 800, 2800, 900, 1700, 1600, 1300, 2500, 1400, 1900, // 1 - 10 1621600, 2300, 800, 3000, 300, 100, 200, 0, 0, 300, // 11 - 20 163298000, 1300, 2600, 1300, 1400, 2100, 1900, 1600, 800, 1700, // 21 - 30 1641100, 1000, 1000, 2100, 1500, 1300, 1100, 800, 1200, 1000, // 31 - 40 1652200, 1700, 1300, 1400, 1500, 1000, 2000, 500, 2700, 9000, // 41 - 50 1661100, 1200, 900, 2400, 1200, 1100, 2100, 2000, 2500, 1700, // 51 - 60 1671100, 1000, 1100, 500, 1900, 0, 1300, 2100, 1700, 900, // 61 - 70 1681100, 800, 1100, 1700, 1100, 1100, 1500, 1500, 500, 900, // 71 - 80 1692100 // 81 170}; 171/* This is the BLUE turret timing map. 172 * These timings correspond to the time needed 173 * to play the individual sayings, in seconds. 174 * For example, i = 2 will take 0.9 seconds (DefectiveTimings[2]) 175 * to play the chatSayings [2] file. 176 */ 177int DefectiveTimings [] = { 1781000, // Start pause on i = 0, followed by "rounds"... 1791700, 900, 2000, 600, 1100, 1800, 1900, 3000, 1500, 800, // 1 - 10 1802100, 800, 1900, 900, 3200, 2700, 0, 0, 0, 2000, // 11 - 20 1814400, 800, 3200, 900, 1400, 2000, 2100, 1200, 1300, 1000, // 21 - 30 1821100, 1400, 2100, 1000, 1600, 1000, 1200 // 31 - 40 183}; 184/////////////////////////////////////////////////////////////////// 185//======================= SETUP =================================// 186/////////////////////////////////////////////////////////////////// 187void setup(){ 188 secondarySerial.begin(9600);// 189 Serial.begin(9600);// 190 mp3.begin(); 191 mp3.setVolume(22); 192 Wire.begin(); 193 SPI.begin(); // Radio setup 194 radio.begin(); 195 radio.setPALevel(RF24_PA_LOW); // set radio to low power. All near each other 196 radio.setDataRate(RF24_2MBPS); // I find this works best with multiple radios 197 network.begin(70, this_node); //(channel, node address) 198 sensor_read(); 199 pinMode(LED_LH_up, OUTPUT); 200 pinMode(LED_LH_down, OUTPUT); 201 pinMode(LED_CENTRE, OUTPUT); 202 pinMode(LED_RH_up, OUTPUT); 203 pinMode(LED_RH_down, OUTPUT); 204 digitalWrite(LED_CENTRE, HIGH); 205 activate_servos(); 206 servo_wings.write(WINGopen); // open wings 207 servo_pivot.write(parkPIVOT); // park pivot 208 servo_pitch.write(parkPITCH); // park pitch 209 randomWake = random(1, 3); 210 mp3.playMp3FolderTrack(1); // play waking up comment 211 delay(2000); 212 servo_wings.write(WINGclose); // close wings 213 delay(1500); 214 digitalWrite(LED_CENTRE, LOW); 215 turn_off_servos(); 216 busyRed = 0; 217} 218/////////////////////////////////////////////////////////////////// 219//======================= MAIN LOOP =============================// 220/////////////////////////////////////////////////////////////////// 221void loop(){ 222 while (sensor.readRangeSingleMillimeters()>triggerDistance) { //nothing in front of sensor, do nothing 223 ReadNet(); 224 WriteNet(); 225 output_sensor(); 226 if (payload[5] == 1) { // Conditions used with MTC. Turret will work automatically without MTC 227 delay(500); 228 WriteNet(); 229 Cara_Mia(); // Opera time!! 230 } 231 else if (payload[5] == 2) { 232 delay(500); 233 WriteNet(); 234 Chatty_time(); // Chatty time!!} 235 ReadNet(); 236 } 237 else if (payload[5] == 3) { 238 delay(500); 239 WriteNet(); 240 ManualControl (); // Manual Control 241 } 242 } 243 244 if (sensor.readRangeSingleMillimeters()<triggerDistance){ //something in front of sensor 245 delay (200); //wait before checking again to see if someone still there... 246 if (sensor.readRangeSingleMillimeters()<triggerDistance){ //someone there (not false trigger) 247 busyRed = 1; 248 ReadNet(); 249 WriteNet(); 250 output_sensor(); 251 activate_servos(); // wake up servos 252 activate(); // open wings and say "I see you" comment 253 if (sensor.readRangeSingleMillimeters()>triggerDistance){ // opened up and person gone 254 falseActivate(); //say "where'd you go?" comment and close up 255 delay (2000); 256 scanArea(); //perform scan of area 257 } 258 else { // someone definitely there - open fire!! 259 engage(); 260 delay (2400); 261 for (int j=0; j <= 2; j++){ 262 if (sensor.readRangeSingleMillimeters()<triggerDistance){ // as long as someone there... 263 for (int i=0; i <= 25; i++){ // fire for a short period 264 fire();} // shoot them... 265 output_sensor(); 266 } 267 } 268 } 269 output_sensor(); 270 disengage(); // no more target, stop firing and prepare to close 271 } 272 else { 273 output_sensor(); 274 delay(350); 275 } 276 } 277} 278 279/////////////////////////////////////////////////////////////////// 280//======================= SUBROUTINES ===========================// 281/////////////////////////////////////////////////////////////////// 282 283//===== read the VLX53 sensor =====// 284void sensor_read(){ 285 sensor.init(); 286 sensor.setTimeout(100); 287 // lower the return signal rate limit (default is 0.25 MCPS) 288 sensor.setSignalRateLimit(0.25); // started with 0.1 289 // increase laser pulse periods (defaults are 14 and 10 PCLKs) 290 sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 14); //started with 18 291 sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 10); //started with 14 292} 293//===== monitor output for debugging =====// 294void output_sensor(){ // Option out or delete if not interested. 295 Serial.println(); 296 Serial.print ("-RED- "); 297 Serial.print("Distance "); Serial.print(sensor.readRangeSingleMillimeters()); Serial.print ("\ "); 298 if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } 299 Serial.print(F("Pivot< ")); Serial.print (posPIVOT); Serial.print (" "); 300 Serial.print(F("Pitch< ")); Serial.print (posPITCH); Serial.print (" "); 301 Serial.print(F("Wings< ")); Serial.print (WINGpos); Serial.print (" "); 302 Serial.print(F("busyRed: "));Serial.print (busyRed); Serial.print (" "); 303 Serial.print(F("x :"));Serial.print (payload[0]); Serial.print ("\ "); 304 Serial.print(F("y :"));Serial.print (payload[1]); Serial.print ("\ "); 305 Serial.print(F("pb1 :"));Serial.print (payload[2]); Serial.print (" "); 306 Serial.print(F("pb2 :"));Serial.print (payload[3]); Serial.print (" "); 307 Serial.print(F("pb3 :"));Serial.print (payload[4]); Serial.print (" "); 308 Serial.print(F("goState: ")); Serial.print(payload[5]);Serial.print (" "); 309} 310//===== update servo positions =====// 311void increment_servos(){ 312 if (pitchCW == 0) posPITCH = posPITCH - 3; // the higher the number, the jerkier the motion 313 if (pitchCW == 1) posPITCH = posPITCH + 3; 314 if (pivotCW == 0) posPIVOT = posPIVOT - 3; 315 if (pivotCW == 1) posPIVOT = posPIVOT + 3; 316 if (posPIVOT >= maxPIVOT) pivotCW = 0; 317 if (posPIVOT <= minPIVOT) pivotCW = 1; 318 if (posPITCH >= maxPITCH) pitchCW = 0; 319 if (posPITCH <= minPITCH) pitchCW = 1; 320} 321/////////////////////////////////////////////////////////////////// 322//======================= ACTIVATE ==============================// 323/////////////////////////////////////////////////////////////////// 324void activate(){ // open up wings and say something 325 busyRed = 1; 326 ReadNet(); 327 WriteNet(); 328 output_sensor(); 329 digitalWrite(LED_CENTRE, HIGH); //LED eye on 330 randomOpen = random(3, 6);// pick random opening comment 331 mp3.playMp3FolderTrack(randomOpen); // play random "I see you" comment 332 servo_wings.write(WINGopen); // open wings 333 output_sensor(); 334 delay (3400); 335} 336/////////////////////////////////////////////////////////////////// 337//====================FALSE ACTIVATE ============================// 338/////////////////////////////////////////////////////////////////// 339void falseActivate(){ // 340 busyRed = 1; 341 ReadNet(); 342 WriteNet(); 343 output_sensor(); 344 randomFalse = random(6, 9);// pick random opening comment 345 mp3.playMp3FolderTrack(randomFalse); // play random "where'd you go?" comment 346 delay (1800); 347} 348/////////////////////////////////////////////////////////////////// 349//======================= SCAN AREA =============================// 350/////////////////////////////////////////////////////////////////// 351void scanArea(){ // continue scanning for a bit after falseActivate 352 busyRed = 1; 353 ReadNet(); 354 WriteNet(); 355 output_sensor(); 356 mp3.playMp3FolderTrack(2); // "searching..." 357 servo_pitch.write(parkPITCH); 358 delay(1600); 359 servo_pitch.detach(); 360 servo_wings.detach(); 361 mp3.playMp3FolderTrack(21); 362 for (int i=0; i <= 220; i++){ //scan for a little bit... 363 output_sensor(); 364 if (pivotCW == 0) posPIVOT = posPIVOT - 1; // increment one step CW if CW = 0 365 if (pivotCW == 1) posPIVOT = posPIVOT + 1; // otherwise go one step other direction 366 if (posPIVOT >= maxPIVOT) pivotCW = 0; // if max rotation clockwise, switch to counterclockwise 367 if (posPIVOT <= minPIVOT) pivotCW = 1; // if min rotation counterclockwise,switch to clockwise 368 servo_pivot.write(posPIVOT); 369 if (sensor.readRangeSingleMillimeters()<triggerDistance/2){ //Somebody stepped in front 370 i = 350; 371 engage(); 372 delay (2500); 373 activate_servos(); 374 for (int i=0; i <= 25; i++){ // fire for a short period 375 fire(); // shoot them... 376 } 377 } 378 } 379 activate_servos(); // fully scanned with no one passing... 380 servo_pivot.write(parkPIVOT); //close up. 381 output_sensor(); 382 delay(1200); 383} 384/////////////////////////////////////////////////////////////////// 385//======================= ENGAGE ================================// 386/////////////////////////////////////////////////////////////////// 387void engage(){ //smartass comment before firing 388 busyRed = 1; 389 ReadNet(); 390 WriteNet(); 391 output_sensor(); 392 randomStart = random(9, 12);// pick random smartass comment before firing 393 mp3.playMp3FolderTrack(randomStart); 394 output_sensor(); 395} 396/////////////////////////////////////////////////////////////////// 397//======================= FIRE ==================================// 398/////////////////////////////////////////////////////////////////// 399void fire(){ // fire sound and turret movement 400 401 ReadNet(); 402 WriteNet(); 403 output_sensor(); 404 mp3.playMp3FolderTrack(15); 405 servo_pivot.write(posPIVOT); 406 servo_pitch.write(posPITCH); 407 digitalWrite(LED_CENTRE, HIGH); 408 digitalWrite(LED_LH_up, LOW); 409 digitalWrite(LED_LH_down, HIGH); 410 digitalWrite(LED_RH_up, LOW); 411 digitalWrite(LED_RH_down, HIGH); 412 delay(pulse*2); 413 servo_pivot.write(posPIVOT); 414 servo_pitch.write(posPITCH); 415 digitalWrite(LED_LH_up, HIGH); 416 digitalWrite(LED_LH_down, LOW); 417 digitalWrite(LED_RH_up, HIGH); 418 digitalWrite(LED_RH_down, LOW); 419 delay(pulse); 420 digitalWrite(LED_LH_up, LOW); 421 digitalWrite(LED_RH_up, LOW); 422 increment_servos(); // update servo position 423} 424/////////////////////////////////////////////////////////////////// 425//======================= DISENGAGE =============================// 426/////////////////////////////////////////////////////////////////// 427void disengage(){ //re-align wings (pitch) and pivot home before closing wings 428 busyRed = 1; 429 ReadNet(); 430 WriteNet(); 431 output_sensor(); 432 delay(2000); 433 randomDisengage = random(12, 15); 434 mp3.playMp3FolderTrack(randomDisengage); // "Goodbye" comment 435 servo_pivot.write(parkPIVOT); 436 servo_pitch.write(parkPITCH); 437 digitalWrite(LED_LH_up, LOW); 438 digitalWrite(LED_LH_down, LOW); 439 digitalWrite(LED_RH_up, LOW); 440 digitalWrite(LED_RH_down, LOW); // turn off firing LEDs 441 delay (2000); 442 servo_wings.write(WINGclose); 443 delay (1500); 444 digitalWrite(LED_CENTRE, LOW); // turn off central LED 445 delay (100); 446 output_sensor(); 447 turn_off_servos(); 448 busyRed = 0; 449} 450void turn_off_servos(){ // detach servos so they're not engaged 451 servo_pivot.detach(); 452 servo_pitch.detach(); 453 servo_wings.detach(); 454} 455void activate_servos(){ // activate servos for movement 456 servo_pivot.attach(PIVOT); 457 servo_pitch.attach(PITCH); 458 servo_wings.attach(WINGS); 459} 460 461/////////////////////////////////////////////////////////////////// 462//======================= CARA MIA OPERA ========================// 463/////////////////////////////////////////////////////////////////// 464void Cara_Mia(){ 465 busyRed = 1; 466 WriteNet(); 467 digitalWrite(LED_CENTRE, HIGH); 468 int randomWingPos; 469 activate_servos(); 470 unsigned long endTimer[] = {8200, 40000, 100000}; // 471 unsigned long startTimer; 472 for (int i=0; i <= 2; i++) { 473 startTimer = millis(); 474 mp3.playMp3FolderTrack(100 + i); 475 while (millis() < (startTimer + endTimer[i])){ 476 ReadNet(); 477 WriteNet(); 478 if (payload[4] == 0) { 479 disengage(); 480 busyRed = 0; 481 WriteNet(); 482 return;} 483 // debugging print below. Delete or comment out as desired. 484 Serial.print(F("millis() ")); Serial.print (millis()); Serial.print (" "); 485 Serial.print(F("startTimer ")); Serial.print (startTimer); Serial.print (" "); 486 Serial.print(F("endTimer ")); Serial.print (endTimer[i]); Serial.print (" "); 487 Serial.print(F("End Time ")); Serial.print (endTimer[i] + startTimer); Serial.print (" "); 488 Serial.print(F("previousMillis1 ")); Serial.print (previousMillis1); Serial.print (" "); 489 Serial.println(); 490 if ((millis() - previousMillis1) >= (850 + (i * 100))) { // 1050 491 randomWingPos = random(10 + (i*20), (60 + (i*20))); 492 servo_wings.write(randomWingPos); 493 previousMillis1 = millis(); 494 } 495 } 496 } 497 disengage(); 498 busyRed = 0; 499 goState = 0; 500 mp3.stop(); 501 ReadNet(); 502 delay(1000); 503} 504/////////////////////////////////////////////////////////////////// 505//======================= CHATTY TIME ===========================// 506/////////////////////////////////////////////////////////////////// 507void Chatty_time(){ 508 busyRed = 1; 509 WriteNet(); 510 int i = 0; 511 int talk; 512 int saying; 513 int timeadder = 750; 514 int talkTime = NormalTimings[i]; 515 int randomPivotPos; 516 activate_servos(); 517 servo_wings.write(WINGopen); 518 digitalWrite(LED_CENTRE, HIGH); 519 do { 520 ReadNet(); 521 WriteNet(); 522 //output_sensor(); // used for debugging... 523 if (i >= 43) { // end of sequence 524 busyRed = 0; 525 WriteNet(); 526 disengage(); 527 return; 528 } 529 unsigned long currentMillis = millis(); // grab current time 530 if ((unsigned long)(currentMillis - previousMillis3) >= talkTime) { 531 if (chatSayings[i] < 100) { // RED Turret talking 532 talk = chatSayings[i]; 533 saying = chatSayings[i]; 534 talkTime = (NormalTimings[saying] + timeadder); 535 } 536 else if ((chatSayings[i] > 99) && (chatSayings[i] < 200)) { // WHITE turret talking 537 talk = 0; 538 saying = chatSayings[i] - 100; 539 talkTime = (NormalTimings[saying] + timeadder); 540 } 541 542 else { // BLUE turret talking 543 talk = 0; 544 saying = chatSayings[i] - 200; // sound file # of BLUE 545 talkTime = (DefectiveTimings[saying] + timeadder); // Time for that saying 546 } 547 548 if (talk == 0) { 549 digitalWrite(LED_CENTRE, LOW); 550 } 551 else { 552 digitalWrite(LED_CENTRE, HIGH); 553 mp3.playMp3FolderTrack(talk); 554 } 555 randomPivotPos = random(minPIVOT, maxPIVOT); 556 servo_pivot.write(randomPivotPos); 557 Serial.println(); 558 Serial.print(F("i: ")); Serial.print (i); Serial.print ("\ "); 559 Serial.print(F("chatSayings[i] ")); Serial.print (chatSayings[i]); Serial.print ("\ "); 560 Serial.print(F("Saying ")); Serial.print (saying); Serial.print ("\ "); 561 Serial.print(F("talk ")); Serial.print (talk); Serial.print ("\ "); 562 Serial.print(F("chat time ")); Serial.print (talkTime); Serial.print ("\ "); 563 Serial.print(F("busyRed: "));Serial.print (busyRed); Serial.print (" "); 564 previousMillis3 = millis(); 565 i++; 566 } 567 } 568 while (payload[4] == 1); 569 busyRed = 0; 570 WriteNet(); 571 digitalWrite(LED_CENTRE, LOW); 572 disengage(); 573} 574/////////////////////////////////////////////////////////////////// 575//======================= MANUAL CONTROL =======================// 576/////////////////////////////////////////////////////////////////// 577void ManualControl(){ 578 int servoWings; 579 int servoPitch; 580 int servoPivot; 581 activate_servos(); 582 servo_wings.write(WINGopen); 583 digitalWrite(LED_CENTRE, HIGH); 584 ReadNet(); 585 do { 586 output_sensor(); 587 ReadNet(); 588 servoPivot = map(payload[0], 1023, 0, minPIVOT, maxPIVOT); 589 servoPitch = map(payload[1], 1023, 0, minPITCH, maxPITCH); 590 servo_pivot.write(servoPivot); 591 servo_pitch.write(servoPitch); 592 unsigned long currentMillis = millis(); // grab current time 593 if (payload[3] == 0) { 594 if ((unsigned long)(currentMillis - previousMillis1) >= 2500) { 595 randomPic = random(1, 20); 596 mp3.playMp3FolderTrack(randomPic); 597 previousMillis1 = millis(); 598 } 599 } 600 if (payload[2] == 0){ 601 fire(); 602 } 603 } 604 while (payload[5] == 3); 605 disengage(); 606 busyRed = 0; 607 WriteNet(); 608 digitalWrite(LED_CENTRE, LOW); 609} 610/////////////////////////////////////////////////////////////////// 611//========================= RECEIVING ===========================// 612/////////////////////////////////////////////////////////////////// 613void ReadNet(){ 614 network.update(); 615 if ( network.available() ) { 616 RF24NetworkHeader header; 617 network.peek(header); 618 network.read(header, &payload, sizeof(payload));} // Read the package 619} 620/////////////////////////////////////////////////////////////////// 621//========================= SENDING =============================// 622/////////////////////////////////////////////////////////////////// 623void WriteNet(){ 624 network.update(); 625 RF24NetworkHeader header4(MTC); 626 bool ok4 = network.write(header4, &busyRed, sizeof(busyRed)); 627/* if (ok4) { // used for debugging... 628 Serial.print("MTC ok4 ");} 629 else { 630 Serial.print("------- ");} 631 */ 632} 633 634
Portal turret w Radio (RED)
c_cpp
Code used for turret. This includes code that will enable control by the Master Turret Control, featured on another page. Different flavours require tweaking.
1// 2/* Portal Turret - Option With Radio!! 3 * Chris Nowak - Feb 2019 4 * https://www.instructables.com/member/ChrisN219/ 5 * https://create.arduino.cc/projecthub/Novachris/talking-portal-2-turret-gun-637bf3 6 * 7 * This code includes all the features needed to perform the Cara Mia Opera, 8 * Chat Time and Manual mode, as controlled by the Maseter Turret Control (MTC). 9 * The MTC is a separate controller featured on another build. The turret 10 * will operate autonomously using this code without the MTC. 11 * 12 * The code is built to work with three turrets, but each will operate independently. 13 * Lots of debugging code left in. Use or clean up as desired. It's mostly debugged, 14 * but isn't perfect. Given the price you paid, I figure that's ok! ;) 15 * ================= RED ==================== 16 */ 17 18#include <Wire.h> 19#include <VL53L0X.h> 20#include "Arduino.h" 21#include <SoftwareSerial.h> 22#include <Servo.h> 23#include <DFMiniMp3.h> 24#include <RF24.h> 25#include <RF24Network.h> 26#include <SPI.h> 27class Mp3Notify 28{ 29public: 30 static void OnError(uint8_t errorCode) 31 { 32 // see DfMp3_Error for code meaning 33 Serial.println(); 34 Serial.print("Com Error "); 35 Serial.println(errorCode); 36 } 37 static void OnPlayFinished(uint8_t globalTrack) 38 { 39 Serial.println(); 40 Serial.print("Play finished for #"); 41 Serial.println(globalTrack); 42 } 43 static void OnCardOnline(uint8_t code) 44 { 45 Serial.println(); 46 Serial.print("Card online "); 47 Serial.println(code); 48 } 49 static void OnCardInserted(uint8_t code) 50 { 51 Serial.println(); 52 Serial.print("Card inserted "); 53 Serial.println(code); 54 } 55 static void OnCardRemoved(uint8_t code) 56 { 57 Serial.println(); 58 Serial.print("Card removed "); 59 Serial.println(code); 60 } 61}; 62 63Servo servo_pivot; 64Servo servo_wings; 65Servo servo_pitch; 66VL53L0X sensor; 67 68// Setup for soundcard 69SoftwareSerial secondarySerial(4, 2); // RX, TX 70DFMiniMp3<SoftwareSerial, Mp3Notify> mp3(secondarySerial); 71 72// Setup for radio 73RF24 radio(10, 9); // nRF24L01 (CE,CSN) 74RF24Network network(radio); // Include the radio in the network 75const uint64_t this_node = 01; // This turret - Red - in Octal format ( 04,031, etc) 76const uint64_t WHT = 02; // Turret 02 - White 77const uint64_t BLU = 03; // Turret 03 - Blue 78const uint64_t MTC = 00; // Master Turret Control 79unsigned long previousMillis1 = 0; 80unsigned long previousMillis2 = 0; 81unsigned long previousMillis3 = 0; 82byte LED_LH_up = A1; 83byte LED_LH_down = A2; 84byte LED_CENTRE = A3; 85byte LED_RH_up = 7; 86byte LED_RH_down = 8; 87byte PIVOT = 6; //white 88byte WINGS = 3; //yellow 89byte PITCH = 5; //blue 90byte parkPIVOT = 96; //Smaller number rotates CW as viewed from the top 91byte posPIVOT = 96; 92byte maxPIVOT = 116; 93byte minPIVOT = 76; 94byte WINGclose = 165; 95byte WINGopen = 10; 96byte WINGpos = 160; 97byte parkPITCH = 86; 98byte posPITCH = 86; 99byte maxPITCH = 96; 100byte minPITCH = 75; 101byte pos = 90; 102byte pulse = 20; 103byte pitchCW = 1; 104byte pivotCW = 1; 105byte randomWake; 106byte randomOpen; 107byte randomFalse; 108byte randomStart; 109byte randomDisengage; 110int triggerDistance = 300; 111byte buttonStatus; 112byte busyRed = 1; 113byte restModeWhite; 114byte goState; 115int x; 116int y; 117byte pb1State; // Fire 118byte pb2State; // say random comment 119byte pb3State; 120byte randomPic; 121// Payload from Master Turret Control (MTC) 122// int payload [] = {0, 1, 2 , 3 , 4 , 5 }; 123// int payload [] = {x, y, pb1State, pb2State, pb3State, goState}; 124int payload [6]; 125 126/* This is the "conversation" map for "Chat Time". 127 * 0-99 = Red Turret sayings 128 * 100-199 = White Turret sayings 129 * 200-299 = Blue Turret sayings 130 * Files on all SD cards are saved as 0-100. 131 * Add 100 to the file number here for White, 200 for Blue. 132 * File 204 would be BLUE turret, file number 0004. 133 */ 134int chatSayings [] = { 135 0, // Start pause on i = 0, followed by "rounds"... 136 204, 164, 25, // 1 137 205, 127, 76, // 2 138 208, 162, 65, // 3 139 143, 230, 23, // 4 140 130, 41, 225, // 5 141 153, 31, 133, // 6 142 234, 49, 155, // 7 143 229, 175, 74, // 8 144 231, 58, 226, // 9 145 161, 223, 59, // 10 146 227, 68, 236, // 11 147 136, 50, 224, // 12 148 34, 160, 78, // 13 149 222, 42 // End 150}; 151 152/* This is the RED and WHITE turret timing map. They share sayings. 153 * These timings correspond to the time needed 154 * to play the individual sayings, in milliseconds. 155 * Change the sayings above as desired, but do not change these timings. 156 * For example, i = 2 will take 0.8 seconds (NormalTimings[2]) 157 * to play the chatSayings[2] file. 158 */ 159int NormalTimings [] = { 1601000, // Start pause on i = 0, followed by "rounds"... 1612600, 800, 2800, 900, 1700, 1600, 1300, 2500, 1400, 1900, // 1 - 10 1621600, 2300, 800, 3000, 300, 100, 200, 0, 0, 300, // 11 - 20 163298000, 1300, 2600, 1300, 1400, 2100, 1900, 1600, 800, 1700, // 21 - 30 1641100, 1000, 1000, 2100, 1500, 1300, 1100, 800, 1200, 1000, // 31 - 40 1652200, 1700, 1300, 1400, 1500, 1000, 2000, 500, 2700, 9000, // 41 - 50 1661100, 1200, 900, 2400, 1200, 1100, 2100, 2000, 2500, 1700, // 51 - 60 1671100, 1000, 1100, 500, 1900, 0, 1300, 2100, 1700, 900, // 61 - 70 1681100, 800, 1100, 1700, 1100, 1100, 1500, 1500, 500, 900, // 71 - 80 1692100 // 81 170}; 171/* This is the BLUE turret timing map. 172 * These timings correspond to the time needed 173 * to play the individual sayings, in seconds. 174 * For example, i = 2 will take 0.9 seconds (DefectiveTimings[2]) 175 * to play the chatSayings [2] file. 176 */ 177int DefectiveTimings [] = { 1781000, // Start pause on i = 0, followed by "rounds"... 1791700, 900, 2000, 600, 1100, 1800, 1900, 3000, 1500, 800, // 1 - 10 1802100, 800, 1900, 900, 3200, 2700, 0, 0, 0, 2000, // 11 - 20 1814400, 800, 3200, 900, 1400, 2000, 2100, 1200, 1300, 1000, // 21 - 30 1821100, 1400, 2100, 1000, 1600, 1000, 1200 // 31 - 40 183}; 184/////////////////////////////////////////////////////////////////// 185//======================= SETUP =================================// 186/////////////////////////////////////////////////////////////////// 187void setup(){ 188 secondarySerial.begin(9600);// 189 Serial.begin(9600);// 190 mp3.begin(); 191 mp3.setVolume(22); 192 Wire.begin(); 193 SPI.begin(); // Radio setup 194 radio.begin(); 195 radio.setPALevel(RF24_PA_LOW); // set radio to low power. All near each other 196 radio.setDataRate(RF24_2MBPS); // I find this works best with multiple radios 197 network.begin(70, this_node); //(channel, node address) 198 sensor_read(); 199 pinMode(LED_LH_up, OUTPUT); 200 pinMode(LED_LH_down, OUTPUT); 201 pinMode(LED_CENTRE, OUTPUT); 202 pinMode(LED_RH_up, OUTPUT); 203 pinMode(LED_RH_down, OUTPUT); 204 digitalWrite(LED_CENTRE, HIGH); 205 activate_servos(); 206 servo_wings.write(WINGopen); // open wings 207 servo_pivot.write(parkPIVOT); // park pivot 208 servo_pitch.write(parkPITCH); // park pitch 209 randomWake = random(1, 3); 210 mp3.playMp3FolderTrack(1); // play waking up comment 211 delay(2000); 212 servo_wings.write(WINGclose); // close wings 213 delay(1500); 214 digitalWrite(LED_CENTRE, LOW); 215 turn_off_servos(); 216 busyRed = 0; 217} 218/////////////////////////////////////////////////////////////////// 219//======================= MAIN LOOP =============================// 220/////////////////////////////////////////////////////////////////// 221void loop(){ 222 while (sensor.readRangeSingleMillimeters()>triggerDistance) { //nothing in front of sensor, do nothing 223 ReadNet(); 224 WriteNet(); 225 output_sensor(); 226 if (payload[5] == 1) { // Conditions used with MTC. Turret will work automatically without MTC 227 delay(500); 228 WriteNet(); 229 Cara_Mia(); // Opera time!! 230 } 231 else if (payload[5] == 2) { 232 delay(500); 233 WriteNet(); 234 Chatty_time(); // Chatty time!!} 235 ReadNet(); 236 } 237 else if (payload[5] == 3) { 238 delay(500); 239 WriteNet(); 240 ManualControl (); // Manual Control 241 } 242 } 243 244 if (sensor.readRangeSingleMillimeters()<triggerDistance){ //something in front of sensor 245 delay (200); //wait before checking again to see if someone still there... 246 if (sensor.readRangeSingleMillimeters()<triggerDistance){ //someone there (not false trigger) 247 busyRed = 1; 248 ReadNet(); 249 WriteNet(); 250 output_sensor(); 251 activate_servos(); // wake up servos 252 activate(); // open wings and say "I see you" comment 253 if (sensor.readRangeSingleMillimeters()>triggerDistance){ // opened up and person gone 254 falseActivate(); //say "where'd you go?" comment and close up 255 delay (2000); 256 scanArea(); //perform scan of area 257 } 258 else { // someone definitely there - open fire!! 259 engage(); 260 delay (2400); 261 for (int j=0; j <= 2; j++){ 262 if (sensor.readRangeSingleMillimeters()<triggerDistance){ // as long as someone there... 263 for (int i=0; i <= 25; i++){ // fire for a short period 264 fire();} // shoot them... 265 output_sensor(); 266 } 267 } 268 } 269 output_sensor(); 270 disengage(); // no more target, stop firing and prepare to close 271 } 272 else { 273 output_sensor(); 274 delay(350); 275 } 276 } 277} 278 279/////////////////////////////////////////////////////////////////// 280//======================= SUBROUTINES ===========================// 281/////////////////////////////////////////////////////////////////// 282 283//===== read the VLX53 sensor =====// 284void sensor_read(){ 285 sensor.init(); 286 sensor.setTimeout(100); 287 // lower the return signal rate limit (default is 0.25 MCPS) 288 sensor.setSignalRateLimit(0.25); // started with 0.1 289 // increase laser pulse periods (defaults are 14 and 10 PCLKs) 290 sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodPreRange, 14); //started with 18 291 sensor.setVcselPulsePeriod(VL53L0X::VcselPeriodFinalRange, 10); //started with 14 292} 293//===== monitor output for debugging =====// 294void output_sensor(){ // Option out or delete if not interested. 295 Serial.println(); 296 Serial.print ("-RED- "); 297 Serial.print("Distance "); Serial.print(sensor.readRangeSingleMillimeters()); Serial.print ("\ "); 298 if (sensor.timeoutOccurred()) { Serial.print(" TIMEOUT"); } 299 Serial.print(F("Pivot< ")); Serial.print (posPIVOT); Serial.print (" "); 300 Serial.print(F("Pitch< ")); Serial.print (posPITCH); Serial.print (" "); 301 Serial.print(F("Wings< ")); Serial.print (WINGpos); Serial.print (" "); 302 Serial.print(F("busyRed: "));Serial.print (busyRed); Serial.print (" "); 303 Serial.print(F("x :"));Serial.print (payload[0]); Serial.print ("\ "); 304 Serial.print(F("y :"));Serial.print (payload[1]); Serial.print ("\ "); 305 Serial.print(F("pb1 :"));Serial.print (payload[2]); Serial.print (" "); 306 Serial.print(F("pb2 :"));Serial.print (payload[3]); Serial.print (" "); 307 Serial.print(F("pb3 :"));Serial.print (payload[4]); Serial.print (" "); 308 Serial.print(F("goState: ")); Serial.print(payload[5]);Serial.print (" "); 309} 310//===== update servo positions =====// 311void increment_servos(){ 312 if (pitchCW == 0) posPITCH = posPITCH - 3; // the higher the number, the jerkier the motion 313 if (pitchCW == 1) posPITCH = posPITCH + 3; 314 if (pivotCW == 0) posPIVOT = posPIVOT - 3; 315 if (pivotCW == 1) posPIVOT = posPIVOT + 3; 316 if (posPIVOT >= maxPIVOT) pivotCW = 0; 317 if (posPIVOT <= minPIVOT) pivotCW = 1; 318 if (posPITCH >= maxPITCH) pitchCW = 0; 319 if (posPITCH <= minPITCH) pitchCW = 1; 320} 321/////////////////////////////////////////////////////////////////// 322//======================= ACTIVATE ==============================// 323/////////////////////////////////////////////////////////////////// 324void activate(){ // open up wings and say something 325 busyRed = 1; 326 ReadNet(); 327 WriteNet(); 328 output_sensor(); 329 digitalWrite(LED_CENTRE, HIGH); //LED eye on 330 randomOpen = random(3, 6);// pick random opening comment 331 mp3.playMp3FolderTrack(randomOpen); // play random "I see you" comment 332 servo_wings.write(WINGopen); // open wings 333 output_sensor(); 334 delay (3400); 335} 336/////////////////////////////////////////////////////////////////// 337//====================FALSE ACTIVATE ============================// 338/////////////////////////////////////////////////////////////////// 339void falseActivate(){ // 340 busyRed = 1; 341 ReadNet(); 342 WriteNet(); 343 output_sensor(); 344 randomFalse = random(6, 9);// pick random opening comment 345 mp3.playMp3FolderTrack(randomFalse); // play random "where'd you go?" comment 346 delay (1800); 347} 348/////////////////////////////////////////////////////////////////// 349//======================= SCAN AREA =============================// 350/////////////////////////////////////////////////////////////////// 351void scanArea(){ // continue scanning for a bit after falseActivate 352 busyRed = 1; 353 ReadNet(); 354 WriteNet(); 355 output_sensor(); 356 mp3.playMp3FolderTrack(2); // "searching..." 357 servo_pitch.write(parkPITCH); 358 delay(1600); 359 servo_pitch.detach(); 360 servo_wings.detach(); 361 mp3.playMp3FolderTrack(21); 362 for (int i=0; i <= 220; i++){ //scan for a little bit... 363 output_sensor(); 364 if (pivotCW == 0) posPIVOT = posPIVOT - 1; // increment one step CW if CW = 0 365 if (pivotCW == 1) posPIVOT = posPIVOT + 1; // otherwise go one step other direction 366 if (posPIVOT >= maxPIVOT) pivotCW = 0; // if max rotation clockwise, switch to counterclockwise 367 if (posPIVOT <= minPIVOT) pivotCW = 1; // if min rotation counterclockwise,switch to clockwise 368 servo_pivot.write(posPIVOT); 369 if (sensor.readRangeSingleMillimeters()<triggerDistance/2){ //Somebody stepped in front 370 i = 350; 371 engage(); 372 delay (2500); 373 activate_servos(); 374 for (int i=0; i <= 25; i++){ // fire for a short period 375 fire(); // shoot them... 376 } 377 } 378 } 379 activate_servos(); // fully scanned with no one passing... 380 servo_pivot.write(parkPIVOT); //close up. 381 output_sensor(); 382 delay(1200); 383} 384/////////////////////////////////////////////////////////////////// 385//======================= ENGAGE ================================// 386/////////////////////////////////////////////////////////////////// 387void engage(){ //smartass comment before firing 388 busyRed = 1; 389 ReadNet(); 390 WriteNet(); 391 output_sensor(); 392 randomStart = random(9, 12);// pick random smartass comment before firing 393 mp3.playMp3FolderTrack(randomStart); 394 output_sensor(); 395} 396/////////////////////////////////////////////////////////////////// 397//======================= FIRE ==================================// 398/////////////////////////////////////////////////////////////////// 399void fire(){ // fire sound and turret movement 400 401 ReadNet(); 402 WriteNet(); 403 output_sensor(); 404 mp3.playMp3FolderTrack(15); 405 servo_pivot.write(posPIVOT); 406 servo_pitch.write(posPITCH); 407 digitalWrite(LED_CENTRE, HIGH); 408 digitalWrite(LED_LH_up, LOW); 409 digitalWrite(LED_LH_down, HIGH); 410 digitalWrite(LED_RH_up, LOW); 411 digitalWrite(LED_RH_down, HIGH); 412 delay(pulse*2); 413 servo_pivot.write(posPIVOT); 414 servo_pitch.write(posPITCH); 415 digitalWrite(LED_LH_up, HIGH); 416 digitalWrite(LED_LH_down, LOW); 417 digitalWrite(LED_RH_up, HIGH); 418 digitalWrite(LED_RH_down, LOW); 419 delay(pulse); 420 digitalWrite(LED_LH_up, LOW); 421 digitalWrite(LED_RH_up, LOW); 422 increment_servos(); // update servo position 423} 424/////////////////////////////////////////////////////////////////// 425//======================= DISENGAGE =============================// 426/////////////////////////////////////////////////////////////////// 427void disengage(){ //re-align wings (pitch) and pivot home before closing wings 428 busyRed = 1; 429 ReadNet(); 430 WriteNet(); 431 output_sensor(); 432 delay(2000); 433 randomDisengage = random(12, 15); 434 mp3.playMp3FolderTrack(randomDisengage); // "Goodbye" comment 435 servo_pivot.write(parkPIVOT); 436 servo_pitch.write(parkPITCH); 437 digitalWrite(LED_LH_up, LOW); 438 digitalWrite(LED_LH_down, LOW); 439 digitalWrite(LED_RH_up, LOW); 440 digitalWrite(LED_RH_down, LOW); // turn off firing LEDs 441 delay (2000); 442 servo_wings.write(WINGclose); 443 delay (1500); 444 digitalWrite(LED_CENTRE, LOW); // turn off central LED 445 delay (100); 446 output_sensor(); 447 turn_off_servos(); 448 busyRed = 0; 449} 450void turn_off_servos(){ // detach servos so they're not engaged 451 servo_pivot.detach(); 452 servo_pitch.detach(); 453 servo_wings.detach(); 454} 455void activate_servos(){ // activate servos for movement 456 servo_pivot.attach(PIVOT); 457 servo_pitch.attach(PITCH); 458 servo_wings.attach(WINGS); 459} 460 461/////////////////////////////////////////////////////////////////// 462//======================= CARA MIA OPERA ========================// 463/////////////////////////////////////////////////////////////////// 464void Cara_Mia(){ 465 busyRed = 1; 466 WriteNet(); 467 digitalWrite(LED_CENTRE, HIGH); 468 int randomWingPos; 469 activate_servos(); 470 unsigned long endTimer[] = {8200, 40000, 100000}; // 471 unsigned long startTimer; 472 for (int i=0; i <= 2; i++) { 473 startTimer = millis(); 474 mp3.playMp3FolderTrack(100 + i); 475 while (millis() < (startTimer + endTimer[i])){ 476 ReadNet(); 477 WriteNet(); 478 if (payload[4] == 0) { 479 disengage(); 480 busyRed = 0; 481 WriteNet(); 482 return;} 483 // debugging print below. Delete or comment out as desired. 484 Serial.print(F("millis() ")); Serial.print (millis()); Serial.print (" "); 485 Serial.print(F("startTimer ")); Serial.print (startTimer); Serial.print (" "); 486 Serial.print(F("endTimer ")); Serial.print (endTimer[i]); Serial.print (" "); 487 Serial.print(F("End Time ")); Serial.print (endTimer[i] + startTimer); Serial.print (" "); 488 Serial.print(F("previousMillis1 ")); Serial.print (previousMillis1); Serial.print (" "); 489 Serial.println(); 490 if ((millis() - previousMillis1) >= (850 + (i * 100))) { // 1050 491 randomWingPos = random(10 + (i*20), (60 + (i*20))); 492 servo_wings.write(randomWingPos); 493 previousMillis1 = millis(); 494 } 495 } 496 } 497 disengage(); 498 busyRed = 0; 499 goState = 0; 500 mp3.stop(); 501 ReadNet(); 502 delay(1000); 503} 504/////////////////////////////////////////////////////////////////// 505//======================= CHATTY TIME ===========================// 506/////////////////////////////////////////////////////////////////// 507void Chatty_time(){ 508 busyRed = 1; 509 WriteNet(); 510 int i = 0; 511 int talk; 512 int saying; 513 int timeadder = 750; 514 int talkTime = NormalTimings[i]; 515 int randomPivotPos; 516 activate_servos(); 517 servo_wings.write(WINGopen); 518 digitalWrite(LED_CENTRE, HIGH); 519 do { 520 ReadNet(); 521 WriteNet(); 522 //output_sensor(); // used for debugging... 523 if (i >= 43) { // end of sequence 524 busyRed = 0; 525 WriteNet(); 526 disengage(); 527 return; 528 } 529 unsigned long currentMillis = millis(); // grab current time 530 if ((unsigned long)(currentMillis - previousMillis3) >= talkTime) { 531 if (chatSayings[i] < 100) { // RED Turret talking 532 talk = chatSayings[i]; 533 saying = chatSayings[i]; 534 talkTime = (NormalTimings[saying] + timeadder); 535 } 536 else if ((chatSayings[i] > 99) && (chatSayings[i] < 200)) { // WHITE turret talking 537 talk = 0; 538 saying = chatSayings[i] - 100; 539 talkTime = (NormalTimings[saying] + timeadder); 540 } 541 542 else { // BLUE turret talking 543 talk = 0; 544 saying = chatSayings[i] - 200; // sound file # of BLUE 545 talkTime = (DefectiveTimings[saying] + timeadder); // Time for that saying 546 } 547 548 if (talk == 0) { 549 digitalWrite(LED_CENTRE, LOW); 550 } 551 else { 552 digitalWrite(LED_CENTRE, HIGH); 553 mp3.playMp3FolderTrack(talk); 554 } 555 randomPivotPos = random(minPIVOT, maxPIVOT); 556 servo_pivot.write(randomPivotPos); 557 Serial.println(); 558 Serial.print(F("i: ")); Serial.print (i); Serial.print ("\ "); 559 Serial.print(F("chatSayings[i] ")); Serial.print (chatSayings[i]); Serial.print ("\ "); 560 Serial.print(F("Saying ")); Serial.print (saying); Serial.print ("\ "); 561 Serial.print(F("talk ")); Serial.print (talk); Serial.print ("\ "); 562 Serial.print(F("chat time ")); Serial.print (talkTime); Serial.print ("\ "); 563 Serial.print(F("busyRed: "));Serial.print (busyRed); Serial.print (" "); 564 previousMillis3 = millis(); 565 i++; 566 } 567 } 568 while (payload[4] == 1); 569 busyRed = 0; 570 WriteNet(); 571 digitalWrite(LED_CENTRE, LOW); 572 disengage(); 573} 574/////////////////////////////////////////////////////////////////// 575//======================= MANUAL CONTROL =======================// 576/////////////////////////////////////////////////////////////////// 577void ManualControl(){ 578 int servoWings; 579 int servoPitch; 580 int servoPivot; 581 activate_servos(); 582 servo_wings.write(WINGopen); 583 digitalWrite(LED_CENTRE, HIGH); 584 ReadNet(); 585 do { 586 output_sensor(); 587 ReadNet(); 588 servoPivot = map(payload[0], 1023, 0, minPIVOT, maxPIVOT); 589 servoPitch = map(payload[1], 1023, 0, minPITCH, maxPITCH); 590 servo_pivot.write(servoPivot); 591 servo_pitch.write(servoPitch); 592 unsigned long currentMillis = millis(); // grab current time 593 if (payload[3] == 0) { 594 if ((unsigned long)(currentMillis - previousMillis1) >= 2500) { 595 randomPic = random(1, 20); 596 mp3.playMp3FolderTrack(randomPic); 597 previousMillis1 = millis(); 598 } 599 } 600 if (payload[2] == 0){ 601 fire(); 602 } 603 } 604 while (payload[5] == 3); 605 disengage(); 606 busyRed = 0; 607 WriteNet(); 608 digitalWrite(LED_CENTRE, LOW); 609} 610/////////////////////////////////////////////////////////////////// 611//========================= RECEIVING ===========================// 612/////////////////////////////////////////////////////////////////// 613void ReadNet(){ 614 network.update(); 615 if ( network.available() ) { 616 RF24NetworkHeader header; 617 network.peek(header); 618 network.read(header, &payload, sizeof(payload));} // Read the package 619} 620/////////////////////////////////////////////////////////////////// 621//========================= SENDING =============================// 622/////////////////////////////////////////////////////////////////// 623void WriteNet(){ 624 network.update(); 625 RF24NetworkHeader header4(MTC); 626 bool ok4 = network.write(header4, &busyRed, sizeof(busyRed)); 627/* if (ok4) { // used for debugging... 628 Serial.print("MTC ok4 ");} 629 else { 630 Serial.print("------- ");} 631 */ 632} 633 634
Downloadable files
Wiring Schematic - radio option
Schematic that I made for building the turret.
Wiring Schematic - radio option
Wiring Schematic - radio option
Schematic that I made for building the turret.
Wiring Schematic - radio option
Documentation
Body-LHS+w+components+v4.stl
Body-LHS+w+components+v4.stl
Leg+-+REAR+test.stl
Leg+-+REAR+test.stl
Pitch+Frame+-+modified+1.stl
Pitch+Frame+-+modified+1.stl
Body-RHS+v4.stl
Body-RHS+v4.stl
Pitch+Frame+v4.stl
Pitch+Frame+v4.stl
Wing+LH+bottom+v4.stl
Wing+LH+bottom+v4.stl
Leg+-+REAR+v4.stl
Leg+-+REAR+v4.stl
Wing+RH+top+v4.stl
Wing+RH+top+v4.stl
Wing+RH+bottom+v4.stl
Wing+RH+bottom+v4.stl
Infill+strips+v3.stl
Infill+strips+v3.stl
Wing+LH+top+v4.stl
Wing+LH+top+v4.stl
Pitch+Frame+v4.stl
Pitch+Frame+v4.stl
Wing+LH+bottom+v4.stl
Wing+LH+bottom+v4.stl
Arduino+Base+w+Radio.stl
Arduino+Base+w+Radio.stl
Pitch+Frame+-+modified+1.stl
Pitch+Frame+-+modified+1.stl
Infill+strips+v3.stl
Infill+strips+v3.stl
Body-RHS+v4.stl
Body-RHS+v4.stl
Wing+RH+top+v4.stl
Wing+RH+top+v4.stl
Leg+-+REAR+test.stl
Leg+-+REAR+test.stl
Lens+v3b.stl
Lens+v3b.stl
Wing+RH+bottom+v4.stl
Wing+RH+bottom+v4.stl
Leg+-+REAR+v4.stl
Leg+-+REAR+v4.stl
Body-LHS+w+components+v4.stl
Body-LHS+w+components+v4.stl
Arduino+Base+w+Radio.stl
Arduino+Base+w+Radio.stl
Wing+LH+top+v4.stl
Wing+LH+top+v4.stl
Comments
Only logged in users can leave comments