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 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
You must be logged in to post a comment.