NXTBee and The Flying Fortress LEGO Blimp

Flying Fortress Blimp with the NXTBee

We recently discovered this fantastic video of a LEGO MINDSTORMS creation: The Flying Fortress LEGO Blimp.  The project is a fantastic two-ballooned flying blimp made of LEGOs and controlled with a pair of NXTBees.

Youtuber Tyler shared the code, written in RobotC with us.  You can see the video below; it looks like a fun test flight in a high school gym.  The balloon is controlled using two NXTBees and powered with adjustable, rotatable propellers.

The Blimp Program:


#pragma config(Sensor, S1, Ultra, sensorSONAR)
 #pragma config(Sensor, S2, SoundSensor, sensorSoundDBA)
 #pragma config(Sensor, S3, HTIRL, sensorI2CCustom)
 #pragma config(Motor, motorB, Tilt, tmotorNXT, PIDControl, reversed, encoder)
 #pragma config(Motor, motorC, Light, tmotorNXT, PIDControl, encoder)
 //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
//#include "drivers/hitechnic-irlink.h"
 #include "Sample ProgramsNXT3rd Party Sensor Driversdriverscommon.h" //Xander's
 #include "hitechnic-irlink.h"
 task Estop
 {
 wait1Msec(500);
 while (SensorValue(SoundSensor) < 50) {
 //nxtDisplayCenteredTextLine(1, "%d", SensorValue(SoundSensor));
 wait1Msec(25);
 };
 nxtDisplayCenteredTextLine(3, "AHHHHH!");
 StopAllTasks();
 }
 //// Stop the motors
 //void stopMotors() {
 // PFcomboDirectMode(HTIRL, 0, CDM_MOTOR_BRAKE, CDM_MOTOR_BRAKE);
 //}
 int IncMess = 0;
bool Run_EStop = false; // True for testing, False when flying
 task main()
 {
 //Initialize
 nxtEnableHSPort(); //Enable High Speed Port #4
 nxtSetHSBaudRate(9600); //Xbee Default Speed
 nxtHS_Mode = hsRawMode; //Set to Raw Mode (vs. Master/Slave Mode)
 short bytesRead;
 ubyte incomingData;
eraseDisplay();
 if (Run_EStop == true) StartTask(Estop);
 nMotorEncoder[Tilt]=0;
 //bFloatDuringInactiveMotorPWM = true;
//11, 12, 13
 //21, 22, 23
 //31, 32, 33
 //40 to 49
 byte speed = 5;
 byte Brake = 8; // Reverse speed
 byte FWspeed = speed;// Forward speed
 byte RVspeed = 16 - speed; // Reverse speed
int Position = 0; //current position
 int TargetPosition = 0;
 const int Factor = 125;
 int TiltMotorSpeed = 20;
 int Thresh = 5;
 int count = 0;
 int PreviousSignal = 0;
 int Timeout = 1250;
 int CrashTime = 4000;
 int CrashDistance = 15;
tPFmotor BluePort = pfmotor_S3_C1_B; //PFMotor(BluePort, (ePWMMotorCommand)7);
 tPFmotor RedPort = pfmotor_S3_C1_A; //PFMotor(BluePort, (ePWMMotorCommand)7);
//Blimp
 time1[T2] = 0;
 while(true)
 {
 time1[T1] = 0;
 while (nxtGetAvailHSBytes() == false && time1[T1] < CrashTime); //Check to see if we have any data coming in if (time1[T1] >= CrashTime){ // Crash sequence
 StopTask(Estop);
 motor[Tilt] = TiltMotorSpeed;
 while(nMotorEncoder[Tilt] < 5*Factor); motor[Tilt] = 0; while (nxtGetAvailHSBytes() == false){ while (SensorValue[Ultra] > CrashDistance && nxtGetAvailHSBytes() == false){
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)FWspeed, (ePWMMotorCommand)FWspeed);
 }
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)Brake, (ePWMMotorCommand)Brake);
 }
 if (Run_EStop == true) StartTask(Estop);
 }
nxtDisplayCenteredBigTextLine(6, "CT:%i", count++);
 nxtReadRawHS(&incomingData, 1);
 IncMess = (int)incomingData;
 nxtDisplayTextLine(0, "Message: %i", IncMess);
 //PreviousSignal = IncMess;
 time1[T2] = 0;
 switch (IncMess)
 {
 case 11:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)FWspeed, (ePWMMotorCommand)Brake);
 break;
 case 12:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)FWspeed, (ePWMMotorCommand)FWspeed);
 break;
 case 13:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)Brake, (ePWMMotorCommand)FWspeed);
 break;
 case 21:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)FWspeed, (ePWMMotorCommand)RVspeed);
 break;
 case 22:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)Brake, (ePWMMotorCommand)Brake);
 break;
 case 23:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)RVspeed, (ePWMMotorCommand)FWspeed);
 break;
 case 31:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)RVspeed, (ePWMMotorCommand)Brake);
 break;
 case 32:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)RVspeed, (ePWMMotorCommand)RVspeed);
 break;
 case 33:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)Brake, (ePWMMotorCommand)RVspeed);
 break;
case 40:
 TargetPosition = -5*Factor;
 break;
 case 41:
 TargetPosition = -4*Factor;
 break;
 case 42:
 TargetPosition = -3*Factor;
 break;
 case 43:
 TargetPosition = -2*Factor;
 break;
 case 44:
 TargetPosition = -1*Factor;
 break;
 case 45:
 TargetPosition = 0*Factor;
 break;
 case 46:
 TargetPosition = 1*Factor;
 break;
 case 47:
 TargetPosition = 2*Factor;
 break;
 case 48:
 TargetPosition = 3*Factor;
 break;
 case 49:
 TargetPosition = 4*Factor;
 break;
 case 50:
 TargetPosition = 5*Factor;
 break;
default:
 PFcomboPwmMode(HTIRL, 0, (ePWMMotorCommand)Brake, (ePWMMotorCommand)Brake);
 motor[Tilt] = 0;
 }
if (IncMess >= 40 && IncMess= TargetPosition - Thresh && Position motor[Tilt] = 0;
 }
 else if (Position < TargetPosition + Thresh){ motor[Tilt] = TiltMotorSpeed; while(TargetPosition > nMotorEncoder[Tilt] && IncMess == PreviousSignal){
 nxtReadRawHS(&incomingData, 1);
 IncMess = (int)incomingData;
 }
 motor[Tilt] = 0;
 }
 else if (Position > TargetPosition - Thresh){
 motor[Tilt] = -TiltMotorSpeed;
 while(TargetPosition < nMotorEncoder[Tilt] && IncMess == PreviousSignal){
 nxtReadRawHS(&incomingData, 1);
 IncMess = (int)incomingData;
 }
 motor[Tilt] = 0;
 }
 }
 }
 StopTask(Estop);
 nxtDisableHSPort(); //Disable HS Port #4
 }
 [/sourcecode]
The Controller Program:
[sourcecode language="cpp"]
 #pragma config(Sensor, S1, Button, sensorTouch)
 #pragma config(Motor, motorA, ForRev, tmotorNXT, openLoop, reversed, encoder)
 #pragma config(Motor, motorB, LeftRight, tmotorNXT, openLoop, reversed, encoder)
 #pragma config(Motor, motorC, Tilt, tmotorNXT, PIDControl, encoder)
 //*!!Code automatically generated by 'ROBOTC' configuration wizard !!*//
//#include "drivers/lego-touch.h"
 #include "Sample ProgramsNXT3rd Party Sensor Driversdriverscommon.h" //Xander's
 #include "lego-touch.h"
 task main()
 {
 // Initialize
 nxtEnableHSPort(); //Enable High Speed Port #4
 nxtSetHSBaudRate(9600); //Xbee Default Speed
 nxtHS_Mode = hsRawMode; //Set to Raw Mode (vs. Master/Slave Mode)
bFloatDuringInactiveMotorPWM = true;
 nMotorPIDSpeedCtrl[ForRev] = mtrSpeedReg;
 nMotorPIDSpeedCtrl[LeftRight] = mtrSpeedReg;
 nMotorEncoder[ForRev] = 0;
 nMotorEncoder[LeftRight] = 0;
 nMotorEncoder[Tilt] = 0;
motor[ForRev] =10;
 while(nMotorEncoder[ForRev] < 40);
 motor[ForRev] = 0;
 nMotorEncoder[ForRev] = 0;
motor[LeftRight] =10;
 while(nMotorEncoder[LeftRight] < 30);
 motor[LeftRight] = 0;
 nMotorEncoder[LeftRight] = 0;
 bFloatDuringInactiveMotorPWM = true;
nMotorPIDSpeedCtrl[ForRev] = mtrNoReg;
 nMotorPIDSpeedCtrl[LeftRight] = mtrNoReg;
 int LR_ME = 0;
 int FR_ME = 0;
 int TiltAngle = 0;
 int Cont_Message = 0;
 int LRMssg = 0;
 int FRMssg = 0;
 int Factor = 20;
 ubyte myChar;
//Controller
 while(true){
 if(TSreadState(Button) == 1){
 LR_ME = nMotorEncoder[LeftRight];
 FR_ME = nMotorEncoder[ForRev];
if(LR_ME < -20){ LRMssg = 1; } else if (LR_ME >= -20 && LR_ME +20){
 LRMssg = 3;
 }
if(FR_ME < -20){ FRMssg = 30; } else if (FR_ME >= -20 && FR_ME +20){
 FRMssg=10;
 }
 Cont_Message = LRMssg + FRMssg;
 }
else if (TSreadState(Button) == 0){
TiltAngle = nMotorEncoder[Tilt];
 if (TiltAngle > -6*Factor && TiltAngle -5*Factor && TiltAngle -4*Factor && TiltAngle -3*Factor && TiltAngle -2*Factor && TiltAngle -1*Factor && TiltAngle 1*Factor && TiltAngle 2*Factor && TiltAngle 3*Factor && TiltAngle 4*Factor && TiltAngle 5*Factor && TiltAngle 6*Factor){
 Cont_Message = 50;
 }
 else if (TiltAngle < -6*Factor){
 Cont_Message = 40;
 }
 }
 eraseDisplay();
 myChar = (ubyte)Cont_Message;
 nxtWriteRawHS(&myChar, 1); //Write the data (paras: char to send, length of data)
 nxtDisplayCenteredBigTextLine(1, "%d", Cont_Message);
 wait1Msec(250);
 }
 nxtDisableHSPort(); //Disable HS Port #4
 }

Got a project to share?  Contact us through Facebook, Twitter, or our website!

3 Comments

Leave a reply