//=========================================================================== // Flocking X by Nicholas Mei // created 11/4/08 //=========================================================================== #include #include #pragma hdrstop #include "Unit1.h" #include "stdlib.h" #include #include //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- //=========================================================================== // COM1 COMMUNICATIONS MANAGEMENT: GLOBAL VARIABLES //=========================================================================== //taken from theremin program written by Nick Gessler HANDLE hComm = NULL; COMMTIMEOUTS ctmoNew = {0}, ctmoOld; //=========================================================================== // EZIO VARIABLES //=========================================================================== //Taken from theremin program written by Nick Gessler DWORD dwBytesRead; // Required for ReadFile() int InBuff[100]; // Data for ReadFile() char InASCII[100]; // Data for ReadFile() int data; // Data for ReadFile() DWORD dwWritten = 0; // Required for WriteFile() char buffer, portBuffer, hiloBuffer; // Data for WriteFile() bool out1, out2, out3, out4, out5; // Data for WriteFile() bool out6, out7, out8, out9, out10; // Data for WriteFile() bool monitorDigitalInputs = false; bool monitorAnalogInputs = false; bool scopeSelectedPort = false; int port; //--------------------------------------------------- Color Ramp Version 2008 //Written by Nick Gessler TColor colorRamp(int part, int whole) { if (whole == 0) whole++; // prevent divide by zero int pixelDistanceAlongEdges = (part * 1792) / whole; int red, green, blue; // Which edge of the color cube are we on? if (pixelDistanceAlongEdges < 256) { // from BLACK to BLUE red = 0; green = 0; blue = pixelDistanceAlongEdges; } else if (pixelDistanceAlongEdges < 512) { // from BLUE to CYAN red = 0; green = pixelDistanceAlongEdges - 256; blue = 255; } else if (pixelDistanceAlongEdges < 768) { // from CYAN to GREEN red = 0; green = 255; blue = 255 - (pixelDistanceAlongEdges - 512); } else if (pixelDistanceAlongEdges < 1024) { // from GREEN to YELLOW red = (pixelDistanceAlongEdges - 768); green = 255; blue = 0; } else if (pixelDistanceAlongEdges < 1280) { // from YELLOW to RED red = 255; green= 255-(pixelDistanceAlongEdges - 1024); blue = 0; } else if (pixelDistanceAlongEdges < 1536) { // from RED to MAGENTA red = 255; green= 0; blue = pixelDistanceAlongEdges - 1280; } else { // from MAGENTA to WHITE red = 255; green = pixelDistanceAlongEdges - 1537; blue = 255; } return static_cast(RGB(red, green, blue)); } //=========================================================================== // Variables //=========================================================================== //Used in the color ramp function and in agent class //so needs to be defined first int max_neighbors = 60; class an_agent { // describes an abstract class for an-agent public: double velocity; double direction; double intended_direction; int attention_radius; int too_close_neighbors; int neighbors; int size; float x; float y; TPoint points[3]; //Visualize the agent itself void visualize() { Form1->PaintBox1->Canvas->Pen->Color = colorRamp(neighbors, max_neighbors); Form1->PaintBox1->Canvas->Brush->Color = colorRamp(neighbors, max_neighbors); Form1->PaintBox1->Canvas->Brush->Style = bsSolid; Form1->PaintBox1->Canvas->Polygon(points, 2); } //Erase the image of the agent void erase() { Form1->PaintBox1->Canvas->Pen->Color = clBtnFace; Form1->PaintBox1->Canvas->Brush->Color = clBtnFace; Form1->PaintBox1->Canvas->Brush->Style = bsSolid; Form1->PaintBox1->Canvas->Polygon(points, 2); } //Visualize the attention radius of the agent void radius() { Form1->PaintBox1->Canvas->Pen->Color = clRed; Form1->PaintBox1->Canvas->Brush->Style = bsClear; Form1->PaintBox1->Canvas->Ellipse (x - attention_radius, y - attention_radius, x + attention_radius, y + attention_radius); } //Erase the attention radius of the agent void erase_radius() { Form1->PaintBox1->Canvas->Pen->Color = clBtnFace; Form1->PaintBox1->Canvas->Brush->Style = bsSolid; Form1->PaintBox1->Canvas->Brush->Color = clBtnFace; Form1->PaintBox1->Canvas->Ellipse (x - attention_radius, y - attention_radius, x + attention_radius, y + attention_radius); } } agent[1000]; //creates an index of neighbors for each agent int neighbor_index[1000][300]; //variables for changing the attention radius size int previous_attention_multiplier = 1; int attention_multiplier = 1; bool multiplier_changed = false; //set how much we want flocking to occur int flocking_degree = 50; //Chaotic weave mode? bool chaotic_weave = false; //show attention fields? bool show_attention = false; //draw only mode? bool draw_only = false; //sensor mode on? bool sensor_flag = false; //Initial population of agents that we start with int current_pop = 200; int former_pop = 200; bool stop = true; //movement variance int move_variance = 10; int group_variance = 10; //Width and Height of the Paintbox which agents live in double width; double height; //for analog (sensor) inputs int input1 = 0; int input2 = 0; int input3 = 0; int input4 = 0; int input5 = 0; int input6 = 0; //=========================================================================== // Functions //=========================================================================== //------------------------------------------------------READ ONE ANALOG INPUT //taken from theremin program written by Nick Gessler int readAnalogInput (int port) { portBuffer = port; WriteFile(hComm, "A", 1, &dwWritten, NULL); WriteFile(hComm, &portBuffer, 1, &dwWritten, NULL); ReadFile(hComm, InBuff, 50, &dwBytesRead, NULL); data = *InBuff; return data; } //-------------------------------------------------------------smooth wander //not being used currently void smooth_wander(int i, int variance) { double temp_r; double temp_r_2; double variance_radius, variance_radius_2; double xx, yy; variance_radius = variance; variance_radius_2 = pow(variance_radius, 2); Randomize(); temp_r = (agent[i].size/2); temp_r_2 = pow(temp_r, 2); xx = temp_r * cos((M_PI/180)*agent[i].direction); yy = temp_r * -sin((M_PI/180)*agent[i].direction); } //------------------------------------------------------check visual field //We want to check the visual attention field around agent[i] void check_simple_visual_field(int i) { int temp_neighbors = 0; int close_neighbors = 0; //go through all agents currenly in play for (int j = 0; j < current_pop; j++) { //check for agents that are in agent[i]'s attention radius if ( agent[j].x > agent[i].x - agent[i].attention_radius && agent[j].x < agent[i].x + agent[i].attention_radius) { if (agent[j].y > agent[i].y - agent[i].attention_radius && agent[j].y < agent[i].y + agent[i].attention_radius) { //if another agent is within the attention radius of //agent[i], record what agent it is in the neighbor_index neighbor_index[i][temp_neighbors]=j; //keeps count of how many neighbors agent[i] has temp_neighbors++; } } //check for agents that are too close to agent[i] //check radius a function of agent size //based around the agent triangle tip if (agent[j].x > agent[i].x - (agent[i].size/2) && agent[j].x < agent[i].x + (agent[i].size/2)) { if (agent[j].y > agent[i].y - (agent[i].size/2) && agent[j].y < agent[i].y + (agent[i].size/2)) { //keeps count of how many close neighbors agent[i] has close_neighbors++; } } } //record down how many neighbors as well as how many close neighbors agent[i].neighbors = temp_neighbors; agent[i].too_close_neighbors = close_neighbors; } //----------------------------------------------------------------flock //This is where we get complex behavior from void flock (int i) { //local variables double num_neighbors = 0; double flocking_multiplier; double number_to_flock; double sum_direction, sum_velocity; sum_direction = agent[i].direction; sum_velocity = agent[i].velocity; num_neighbors = agent[i].neighbors; flocking_multiplier = flocking_degree/double(100); number_to_flock = floor(flocking_multiplier*num_neighbors); //range of analog input goes form 0 to 140 //input has a "normal" value of ~50-60 //Used for when there are sensors //divides the paintbox into 6 parts //if a sensor gets activated above a certain threshold //it makes it so that the agent won't flock if (agent[i].x < double(width*(1.0/6.0))) { if (input1 > 90) { number_to_flock = 0; } } if (agent[i].x < double(width*(2.0/6.0)) && agent[i].x > double(width*(1.0/6.0))) { if (input2 > 90) { number_to_flock = 0; } } if (agent[i].x < double(width*(3.0/6.0)) && agent[i].x > double(width*(2.0/6.0))) { if (input3 > 90) { number_to_flock = 0; } } if (agent[i].x < double(width*(4.0/6.0)) && agent[i].x > double(width*(3.0/6.0))) { if (input4 > 90) { number_to_flock = 0; } } if (agent[i].x < double(width*(5.0/6.0)) && agent[i].x > double(width*(4.0/6.0))) { if (input5 > 90) { number_to_flock = 0; } } if (agent[i].x < double(width*(6.0/6.0)) && agent[i].x > double(width*(5.0/6.0))) { if (input6 > 90) { number_to_flock = 0; } } //number to flock is influenced by flocking degree for (int j = 0; j < number_to_flock; j++) { //making sure that we don't get agents adding more than 300 degrees //difference from one another //doesn't really make a huge difference... //180 instead of 300 would probably be mroe realistic //but visually looks inferior if (abs(agent[i].direction - agent[neighbor_index[i][j]].direction) < 300) { sum_direction+=agent[neighbor_index[i][j]].direction; } sum_velocity+=agent[neighbor_index[i][j]].velocity; } //if we have summed up more than 1 agent's velocity and directions then //we need to average direction and velocity if (number_to_flock != 0) { sum_direction = sum_direction/(number_to_flock+1); sum_velocity = sum_velocity/(number_to_flock+1); Randomize(); //adds some random variation to velocity within certain limits if (random(2) != 0) { if (agent[i].velocity < 4) { sum_velocity += 0.1*random(2); } } else { if (agent[i].velocity > 0.3) { sum_velocity -= 0.1*random(2); } } //adds some random variation to group movement if (random(2) == 0) { sum_direction += double(random(group_variance)/double(2)); } else { sum_direction -= double(random(group_variance)/double(2)); } // after transformations to sum direction we only have the agent // adopt the new direction if it's less then 70 degrees difference // prevents some of the wierd spinning behaviors if (abs(agent[i].direction - sum_direction) < 70) { agent[i].direction = sum_direction; agent[i].intended_direction = sum_direction; } //after transformation to sum velocity we only have the agent //adop the new velocity if it's fairly close //for realism... if (abs(agent[i].velocity - sum_velocity) < 0.6) { agent[i].velocity = sum_velocity; } } } //----------------------------------------------------------find_max_neighbors //Finds how many neighbors an agent has //utilized solely for the colorramp function void find_max_neighbors (void) { int temp_max = 0; for (int i = 0; i < current_pop; i++) { if (temp_max < agent[i].neighbors) { temp_max = agent[i].neighbors; } } //if the temp max is larger than the current recorded max we update it if (temp_max > max_neighbors) { max_neighbors = temp_max; } //if the temp max is smaller, then we scale down the max neighbors if (temp_max < max_neighbors && max_neighbors > 80) { max_neighbors -= (max_neighbors-temp_max); } //the result is that color should accurately update if we suddenly remove //a lot of agents or we increase then decrease the attention radius } //----------------------------------------------------------------Initialize void initialize () { //initializes all the agents and gives them some basic starting parameters width = Form1->PaintBox1->Width; height = Form1->PaintBox1->Height; Randomize(); //creating the agents' "center" point //giving them a random size for (int i = 0; i < 1000; i++) { //agent position and size agent[i].x = random(Form1->PaintBox1->Width); agent[i].y = random(Form1->PaintBox1->Height); agent[i].size = random(19) + 3; //velocity and direction //intended direction is not currently being used agent[i].velocity = (random(2)+3); agent[i].intended_direction = random(360); agent[i].direction = agent[i].intended_direction; //creating the outer points that define the agent based on size agent[i].points[0] = Point(agent[i].x, agent[i].y ); agent[i].points[1] = Point(agent[i].x + ((agent[i].size)/2), agent[i].y + (agent[i].size+3)); agent[i].points[2] = Point(agent[i].x -((agent[i].size)/2), agent[i].y + (agent[i].size+3)); agent[i].attention_radius = agent[i].size*2; agent[i].neighbors = 0; } } //---------------------------------------------------------------------- step void step (void) { double x1, y1, x2, y2; double r, const_degrees, temp_degrees, new_degrees1, new_degrees2, agent_angle; //run as long as user hasn't pressed stop while (stop == false) { Application->ProcessMessages(); for (int i = 0; i < current_pop; i++) { //if user changes the attention multiplier update values for attention radius if (multiplier_changed == true) { for (int k = 0; k < 1000; k++) { agent[k].attention_radius = (agent[k].attention_radius/ previous_attention_multiplier)*attention_multiplier; } multiplier_changed = false; } //normal default if (chaotic_weave == false) { if (draw_only == false) { //erases the agent agent[i].erase(); } if (show_attention == true) { //erases the agent radius agent[i].erase_radius(); } } //Wrapped world if (agent[i].size > 0) { if (agent[i].x > width) { agent[i].x = 0; } if (agent[i].y > height) { agent[i].y = 0; } if (agent[i].x < 0) { agent[i].x = width; } if (agent[i].y < 0) { agent[i].y = height; } } //random wander movement - not smooth movement Randomize(); //add some motion variance if (random(2) == 0) { agent[i].direction += double(random(move_variance)/double(1.5)); } else { agent[i].direction -= double(random(move_variance)/double(1.5)); } check_simple_visual_field(i); //don't flock on the first iteration because values haven't //been correctly updated yet //also don't flock unless agent has greater than 2 neighbors //because "3's a crowd" if (i != 0 && agent[i].neighbors > 2) { flock(i); } Randomize(); //if our agent is too close to others we want to either make it //speed up, or slow down. if (agent[i].too_close_neighbors > 4) { if (random(2) == 0) { if (agent[i].velocity < 7) { agent[i].velocity += 1; } } else { if (agent[i].velocity > 1.2) { agent[i].velocity -= 1; } } } //movement algorithm for agent center... agent[i].x+=cos(M_PI/180*agent[i].direction)*double(agent[i].velocity); agent[i].y-=sin(M_PI/180*agent[i].direction)*double(agent[i].velocity); //smooth_wander(i, move_variance); //chaotic weave option if (chaotic_weave == true) { agent[i].erase(); if (show_attention == true) { agent[i].erase_radius(); } } //storing agent points into temp values for rotation x1 = agent[i].x + ((agent[i].size)/2); y1 = agent[i].y + (agent[i].size+3); x2 = agent[i].x -((agent[i].size)/2); y2 = agent[i].y + (agent[i].size+3); //=================================================rotation //shift coordinate system to (0,0) x1 -= agent[i].x; y1 -= agent[i].y; x2 -= agent[i].x; y2 -= agent[i].y; //find the magnitude of the hypotenuse r = sqrt(pow((agent[i].size)/2, 2) + pow(agent[i].size+3, 2)); //degrees to be held constant between points and agent[i].x and agent[i].y const_degrees = atan2(((agent[i].size)/2), (agent[i].size +3)); //const_degrees = (180/M_PI)*const_degrees; agent_angle = (M_PI/180)*agent[i].direction; //we want the degree measure exactly opposite of where the agent is heading temp_degrees = (agent_angle + M_PI); //we want to add the constant degree to the temporary degree for point 1 new_degrees1 = (temp_degrees + const_degrees); //we want to subtract the constant degree from the temporary degree for point 2 new_degrees2 = (temp_degrees - const_degrees); //check degrees to radians conversion!!! //recalculate point based on hypotenuse mag and angle //need to multiply y by -1 for some reason.... x1 = r*cos(new_degrees1); y1 = r*-sin(new_degrees1); x2 = r*cos(new_degrees2); y2 = r*-sin(new_degrees2); //shift coordinates back x1 += agent[i].x; y1 += agent[i].y; x2 += agent[i].x; y2 += agent[i].y; //====================================================rotation //creating the outer points that define the agent based on size agent[i].points[0] = Point(agent[i].x, agent[i].y); agent[i].points[1] = Point(x1, y1); agent[i].points[2] = Point(x2, y2); if (chaotic_weave == false) { //Let's draw the agent! agent[i].visualize(); } //optionally draw the attention radius if (show_attention == true) { agent[i].radius(); } } find_max_neighbors(); //range of analog input goes form 0 to 140 //input has a "normal" value of ~50-60 } } //----------------------------------------------------------------------- Run //when the user presses the run button... void run (void) { Form1->PaintBox1->Refresh(); initialize(); stop = false; while (stop == false) { step(); Application->ProcessMessages(); } } //=========================================================================== // Event Handlers //=========================================================================== void __fastcall TForm1::Button1Click(TObject *Sender) { stop = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { stop = false; run(); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button4Click(TObject *Sender) { initialize(); } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBar1Change(TObject *Sender) { former_pop = current_pop; current_pop = Form1->TrackBar1->Position; Form1->Edit1->Text = current_pop; //when we remove agents we need to erase all traces of them if (former_pop > current_pop) { //don't remove if it's in draw only mode if (draw_only == false) { for (int i = current_pop; i < former_pop; i++) { agent[i].erase(); if (show_attention == true) { agent[i].erase_radius(); } } } } } //--------------------------------------------------------------------------- void __fastcall TForm1::Button3Click(TObject *Sender) { //resets colors max_neighbors = 60; } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox1Click(TObject *Sender) { //chaotic weave options if (Form1->CheckBox1->Checked == true && Form1->CheckBox2->Checked == true) { chaotic_weave = true; } else { chaotic_weave = false; Form1->PaintBox1->Refresh(); } } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox2Click(TObject *Sender) { //shwoing attention radius options if (Form1->CheckBox2->Checked == true) { show_attention = true; } else { show_attention = false; for (int i = 0; i < current_pop; i++) { agent[i].erase_radius(); } } } //--------------------------------------------------------------------------- void __fastcall TForm1::FormResize(TObject *Sender) { //when the form gets resized height = Form1->Height; Form1->PaintBox1->Height = Form1->Height; width = Form1->Width; Form1->PaintBox1->Width = Form1->Width; Form1->Button1->Left = width - 165; Form1->Button2->Left = width - 165; Form1->GroupBox1->Left = width - 229; Form1->GroupBox2->Left = width - 229; Form1->GroupBox3->Left = width - 229; Form1->GroupBox4->Left = width - 229; Form1->GroupBox5->Left = width - 229; } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBar2Change(TObject *Sender) { move_variance = Form1->TrackBar2->Position; Form1->Edit2->Text = move_variance; } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBar3Change(TObject *Sender) { flocking_degree = Form1->TrackBar3->Position; Form1->Edit3->Text = flocking_degree; } //--------------------------------------------------------------------------- void __fastcall TForm1::ShowControls2Click(TObject *Sender) { //disappearing menu functionality if (Form1->ShowControls2->Checked == true) { Form1->ShowControls2->Checked = false; Form1->Button1->Visible = false; Form1->Button1->Enabled = false; Form1->Button2->Visible = false; Form1->Button2->Enabled = false; Form1->Edit1->Visible = false; Form1->Edit1->Enabled = false; Form1->Edit2->Visible = false; Form1->Edit2->Enabled = false; Form1->Edit3->Visible = false; Form1->Edit3->Enabled = false; Form1->TrackBar1->Visible = false; Form1->TrackBar1->Enabled = false; Form1->TrackBar2->Visible = false; Form1->TrackBar2->Enabled = false; Form1->TrackBar3->Visible = false; Form1->TrackBar3->Enabled = false; Form1->Label1->Visible = false; Form1->Label1->Enabled = false; Form1->Label2->Visible = false; Form1->Label2->Enabled = false; Form1->CheckBox1->Visible = false; Form1->CheckBox1->Enabled = false; Form1->CheckBox2->Visible = false; Form1->CheckBox2->Enabled = false; Form1->GroupBox1->Visible = false; Form1->GroupBox1->Enabled = false; Form1->GroupBox2->Visible = false; Form1->GroupBox2->Enabled = false; Form1->GroupBox3->Visible = false; Form1->GroupBox3->Enabled = false; Form1->GroupBox4->Visible = false; Form1->GroupBox4->Enabled = false; Form1->Edit4->Visible = false; Form1->Edit4->Enabled = false; Form1->TrackBar4->Visible = false; Form1->TrackBar4->Enabled = false; Form1->GroupBox5->Visible = false; Form1->GroupBox5->Enabled = false; Form1->Label3->Visible = false; Form1->Label3->Enabled = false; Form1->CheckBox3->Visible = false; Form1->CheckBox3->Enabled = false; Form1->CheckBox4->Visible = false; Form1->CheckBox4->Enabled = false; Form1->Label6->Visible = false; Form1->Label6->Enabled = false; } else { Form1->ShowControls2->Checked = true; Form1->Button1->Visible = true; Form1->Button1->Enabled = true; Form1->Button2->Visible = true; Form1->Button2->Enabled = true; Form1->Edit1->Visible = true; Form1->Edit1->Enabled = true; Form1->Edit2->Visible = true; Form1->Edit2->Enabled = true; Form1->Edit3->Visible = true; Form1->Edit3->Enabled = true; Form1->TrackBar1->Visible = true; Form1->TrackBar1->Enabled = true; Form1->TrackBar2->Visible = true; Form1->TrackBar2->Enabled = true; Form1->TrackBar3->Visible = true; Form1->TrackBar3->Enabled = true; Form1->Label1->Visible = true; Form1->Label1->Enabled = true; Form1->Label2->Visible = true; Form1->Label2->Enabled = true; Form1->CheckBox1->Visible = true; Form1->CheckBox1->Enabled = true; Form1->CheckBox2->Visible = true; Form1->CheckBox2->Enabled = true; Form1->GroupBox1->Visible = true; Form1->GroupBox1->Enabled = true; Form1->GroupBox2->Visible = true; Form1->GroupBox2->Enabled = true; Form1->GroupBox3->Visible = true; Form1->GroupBox3->Enabled = true; Form1->GroupBox4->Visible = true; Form1->GroupBox4->Enabled = true; Form1->Edit4->Visible = true; Form1->Edit4->Enabled = true; Form1->TrackBar4->Visible = true; Form1->TrackBar4->Enabled = true; Form1->GroupBox5->Visible = true; Form1->GroupBox5->Enabled = true; Form1->Label3->Visible = true; Form1->Label3->Enabled = true; Form1->CheckBox3->Visible = true; Form1->CheckBox3->Enabled = true; Form1->CheckBox4->Visible = true; Form1->CheckBox4->Enabled = true; Form1->Label6->Visible = true; Form1->Label6->Enabled = true; } } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBar4Change(TObject *Sender) { previous_attention_multiplier = attention_multiplier; attention_multiplier = Form1->TrackBar4->Position; if (attention_multiplier == 1) { Form1->Edit4->Text = "x1"; multiplier_changed = true; } if (attention_multiplier == 2) { Form1->Edit4->Text = "x2"; multiplier_changed = true; } if (attention_multiplier == 3) { Form1->Edit4->Text = "x3"; multiplier_changed = true; } if (attention_multiplier == 4) { Form1->Edit4->Text = "x4"; multiplier_changed = true; } if (attention_multiplier == 5) { Form1->Edit4->Text = "x5"; multiplier_changed = true; } } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox3Click(TObject *Sender) { if (Form1->CheckBox3->Checked == true) { draw_only = true; } else { draw_only = false; Form1->PaintBox1->Refresh(); } } //--------------------------------------------------------------------------- void __fastcall TForm1::TrackBar5Change(TObject *Sender) { group_variance = Form1->TrackBar5->Position; Form1->Edit5->Text = group_variance; } //--------------------------------------------------------------------------- //=========================================================================== // COM1 COMMUNICATIONS MANAGEMENT: ON FORM CREATE //=========================================================================== //taken from theremin program written by Nick Gessler void __fastcall TForm1::FormCreate(TObject *Sender) { // FOR EZIO COMMUNICATION DCB dcbCommPort; // OPEN THE COMM PORT. hComm = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); // IF THE PORT CANNOT BE OPENED, BAIL OUT. if(hComm == INVALID_HANDLE_VALUE) Application->Terminate(); // SET THE COMM TIMEOUTS IN OUR EXAMPLE. GetCommTimeouts(hComm,&ctmoOld); ctmoNew.ReadTotalTimeoutConstant = 10; ctmoNew.ReadTotalTimeoutMultiplier = 0; ctmoNew.WriteTotalTimeoutMultiplier = 0; ctmoNew.WriteTotalTimeoutConstant = 0; SetCommTimeouts(hComm, &ctmoNew); // SET BAUD RATE, PARITY, WORD SIZE, AND STOP BITS. // THERE ARE OTHER WAYS OF DOING SETTING THESE BUT THIS IS THE EASIEST. dcbCommPort.DCBlength = sizeof(DCB); GetCommState(hComm, &dcbCommPort); BuildCommDCB("57600,N,8,1", &dcbCommPort); SetCommState(hComm, &dcbCommPort); } //--------------------------------------------------------------------------- //=========================================================================== // COM1 COMMUNICATIONS MANAGEMENT: ON FORM CLOSE //=========================================================================== //taken from theremin program written by Nick Gessler void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { // WAIT FOR THREAD TO TERMINATE, // PURGE THE INTERNAL COMM BUFFER, // RESTORE THE PREVIOUS TIMEOUT SETTINGS, // AND CLOSE THE COMM PORT. Sleep(250); PurgeComm(hComm, PURGE_RXABORT); SetCommTimeouts(hComm, &ctmoOld); CloseHandle(hComm); } //--------------------------------------------------------------------------- void __fastcall TForm1::CheckBox4Click(TObject *Sender) { //Do we want to check sensor ports of input? if (Form1->CheckBox4->Checked == true) { sensor_flag = true; } else { sensor_flag = false; } } //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender) { //Timer that has sensors take in input every 2 seconds... if (sensor_flag == true) { input1 = readAnalogInput(0); input2 = readAnalogInput(1); input3 = readAnalogInput(2); input4 = readAnalogInput(3); input5 = readAnalogInput(4); input6 = readAnalogInput(5); } } //---------------------------------------------------------------------------