Friday Night Robotics – Portable… Fish.. Tank… Robot… ???
This FNR I continued work on the blinky blink NXT LED fish! I added wheels to it, sensors, and the NXT brick. Basically, this now makes it a ‘portable fish tank robot’!

The idea stemmed from the want to make a robot that can drive around on a table but not fall off. In particular, the table would be the table for the Autonomous Robotics Club at the admissions open house activity fair
Ultrasonic sensors are usually the best for this, since it depends on distance. Though, one could easily make a mechanism to trigger a touch sensor… or one could use a light sensor, but there is more possibility for error with a light sensor.

The design right now has the ultrasonic sensor sticking out more that that, since it wasn’t far enough out… this means that sometimes the NXT couldn’t tell the motors to stop in time, and it would fall off the table.
The motors are geared to be fast, since I want it to be fast like a fish!

The screen displays the ‘water level’ for the LED fish. In the picture, it used a method of drawing the level line by line, but I later refined it so that it uses a rectangle, and increments 3 pixels more so that it’s noticable when one presses the button.

The robot can zip around pretty quickly, which produces some interesting artsy stuff:

The LED fish are on the back of the robot, and the speed of their blinks is determined by how much ‘food’ they have. The more food, the more fast it is, the less food, the slower it is. When you press the button to feed the fish, it makes a bloop sound

The LED fish is what makes this project. No one can resist the power of super-cute LED fish. They’re just so happy!
Here’s a video of the robot in action. It’s running the old program, but it’s all pretty much the same thing
The code for this is pretty cool. The NXT can handle up to 10 different simultaneous tasks! I use this to check the sensors for food and water, drive the robot, and blink the LED fish at the same time. Now, I’m still experimenting with the code, which is why there are bugs, random functions, and no comments in it.
-
#pragma config(Sensor, S1, HTPB, sensorI2CCustom9V)
-
#pragma config(Sensor, S2, sonicSensor, sensorSONAR)
-
#pragma config(Sensor, S3, touchSensor1, sensorTouch)
-
#pragma config(Sensor, S4, touchSensor2, sensorTouch)
-
//*!!Code automatically generated by ‘ROBOTC’ configuration wizard !!*//
-
-
/*
-
Crazy LEDs!
-
Erin K
-
Oct. 9th, 2009
-
*/
-
-
#include "drivers/common.h"
-
#include "drivers/HTPB-driver.h"
-
-
byte theLEDs[] = { 0×01, 0×02, 0×04, 0×08, 0×10, 0×20 };
-
int theTime = 50;
-
int theWaterLevel = 32;
-
int foodButton = 0;
-
int waterButton = 0;
-
int averageTouch1Level = 0;
-
int averageTouch2Level = 0;
-
-
void fishTank(int theTime);
-
void drawWaterLevel();
-
void doSomething();
-
-
task blinkFish() {
-
while(true) {
-
fishTank(theTime);
-
}
-
}
-
-
task checkFoodSensor() {
-
-
while(true) {
-
-
if(SensorValue(touchSensor1) == 1) {
-
theTime-=10; // Make fish faster
-
PlaySoundFile("bloop4.rso");
-
wait1Msec(1000);
-
}
-
-
}
-
-
}
-
-
task checkWaterSensor() {
-
-
while(true) {
-
-
if(SensorValue(touchSensor2) == 1) {
-
theWaterLevel+=3; // Add water
-
PlaySoundFile("waterSPLASH.rso");
-
wait1Msec(1000);
-
}
-
-
}
-
-
}
-
-
task drainWaterAndFood() {
-
-
while(true) {
-
-
wait1Msec(5000); // Wait 10 seconds
-
theTime += 10; // Make fish slower
-
theWaterLevel -= 2; // Drain water
-
-
}
-
-
}
-
-
void drawWaterLevel() {
-
eraseDisplay();
-
nxtFillRect(0, theWaterLevel, 99, 0);
-
}
-
-
task main() {
-
-
// Setup all the digital IO ports as outputs (0xFF)
-
if (!HTPBsetupIO(HTPB, 0xFF)) StopAllTasks();
-
wait1Msec(200);
-
-
eraseDisplay();
-
drawWaterLevel();
-
-
float averageSonicLevel = 0;
-
-
for(int i=0; i<5; i++) {
-
averageSonicLevel += SensorValue(sonicSensor);
-
wait1Msec(500);
-
}
-
-
averageSonicLevel /= 5;
-
-
StartTask(blinkFish);
-
StartTask(checkFoodSensor);
-
StartTask(checkWaterSensor);
-
StartTask(drainWaterAndFood);
-
-
float sonicThresh = 10.0;
-
-
bool driveMotors = false;
-
-
while(true) {
-
-
if((SensorValue(sonicSensor) > (averageSonicLevel-sonicThresh) || SensorValue(sonicSensor) < (averageSonicLevel+sonicThresh))) {
-
-
doSomething();
-
-
} else {
-
motor[motorB] = -40;
-
motor[motorC] = -40;
-
wait1Msec(1000);
-
}
-
-
drawWaterLevel();
-
alive();
-
-
}
-
-
}
-
-
-
int doSomethingIterations = 0;
-
-
void doSomething() {
-
-
doSomethingIterations++;
-
-
motor[motorB] = 40;
-
motor[motorC] = 40;
-
-
wait1Msec(100);
-
-
}
-
-
-
void fishTank(int theTime) {
-
-
// LEDs going up
-
for(int i=0; i<6; i++) {
-
if (!HTPBwriteIO(HTPB, theLEDs[i])) nxtDisplayTextLine(5, "ERR WRITE");
-
wait1Msec(theTime);
-
}
-
-
// LEDs going down
-
for(int i=5; i>=0; i–) {
-
if (!HTPBwriteIO(HTPB, theLEDs[i])) nxtDisplayTextLine(5, "ERR WRITE");
-
wait1Msec(theTime);
-
}
-
-
}
Eventually, I want to have the robot able to drive around in a square (a big square) autonomously. The square is around one of the dorm buildings, so there’s brick walls, stairs, fences, and people to avoid. I think it would be cool because the square is just so confusing at first. You can walk around it 5 times, and still think that you have gone somewhere.
Since a lot of smart people do this, if a robot does it we could imply that it is smart! Bahaha! Logic prevails!
I mentioned that this was originally intended for the activities fair. I also had MANOI there, doing its handshake routine! It went really good. We had a good 15 people show interest, which is surprisingly more than the orchestra, and the tables adjacent to ARC.
But, the table got hit by a frisbee. (Yes, my robot got hit by a frisbee) So, thanks to the jerks at the frisbee club, they messed up MANOI’s other knee (the good one– or what was the good one). So now MANOI has two bad knees, and can’t walk. The goal that I just obtained got wrecked. By a frisbee. Frisbee sucks, really bad.
(so, don’t join frisbee club, they’re morons)
December 19th, 2009 at 2:57 PM
Great effort to put them altogether.