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.
#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 Programs\NXT\3rd Party Sensor Drivers\drivers\common.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
}
The Controller Program:
#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 Programs\NXT\3rd Party Sensor Drivers\drivers\common.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!



Pingback: MAKE | Mindstorms Blimp Drone
Pingback: Build Your Own LEGO Drone Blimp Thanks To These Geniuses | Gizmodo Australia
Pingback: This DIY LEGO Drone Blimp Could Be Watching You From The Sky « www.SteffanLewis.com