Might see me often the next few days, sorry. if this is too much to read, Ill come back and edit it down, thought it best to be thorough. Skip down to “the problem” for the explanation. Thank you in advance. Here’s the actual question:
How do I sweep a turret left and right looking for Pixy blocks, map where these blocks are (mapping frame coordinates to servoangle), and then later, accurately aim the turret at those blocks?
Idea: Create a mock firefighter turret that searches for lightsources and high temperatures in a small area, aim at them, and “fire” (beep a few times).
Design: I have a pixy2 sat on top of a turret. Directly underneath the turret is a flame sensor, made to detect change in temp. The Pixy’s signature 1 is set up to only take in extreme sources of light like a lightbulb or a lighter and the room the pixy is in, when in operation, has no other sources of light available than two lightbulbs for testing. The turret can pan and tilt. The pan/tilt control and all other functions are handled by an Arduino Nano Every and not the Pixy’s servo headers.
Function: What the Pixy should do is first, before anything else, come to “rest” where the pan and tilt servos center themselves parallell to the ground.
Next, the Pixy will take in whatever blocks are present at the “Rest” orientation (may be a light bulb, may be nothing and thus no blocks to process) and save the m_x and m_y of whatever blocks are present to the first element in an array of structs.
Next, the turret will pan left and right looking for more lights. It will pan left and right in steps of 25 degrees between limits 140 degrees (“left”) and 40 degrees (“right”) with 90 degrees being “rest”.
Next, for each 25 degree step, the pixy will see if blocks are avail. If so, the Arduino will use the map function to map the m_x and m_y of the block[s] to the current angle of the pan servo in relation to the difference between the limits from above which is 100 degrees, so ±50 degrees either side of the whereever the pan servo currently is. Thats the problem.
The Problem: That drawing shows my thought process. The shaded areas, first off, can be ignored: they show blocks that will be ignored becauuse the block is outside the 140/40 degree limit range. The idea is that for example, with the frame marked “A” in the picture, the Pixy should map the lightsource to 190/90 degrees servo centered @ 140 deg., the same way it would map the lightsource if it was directly in front of the turret and the ligihtsource was 140/40 degrees servo centered @ 90 deg. And this mapped value will give me a position that after the turret is done panning and the Pixy is done looking for more lightsources, the turrent can accurately turn back to this angle and “shoot water at the fire”. But I’m getting random values for the x map and the y map is the same every time I run the code. *Also, the Arduino will check in an array of structs if the servoangle of the center of the block is already present in the one of the structs, within ±10 deg. in order to dispose of duplicates. This seems to be a second problem I may reach out for in a second forum post or maybe on a different forum since it’s related to comparing elements in an array of structs and not the PixyCam.
So that this post doesnt become twice as long, Im posting the relevant code but if anyone wants to see the full code Ill provide it immediatly:
// Pre-processor Directives #include <Servo.h> #include <Pixy2SPI_SS.h> //The Arduino Helpers Library [2] #include <Arduino_Helpers.h> #include <AH/STL/algorithm> #include <AH/STL/iterator> // Class/object declarations Servo recoil_servo; //Create servo objects. Servo pan_servo; Servo tilt_servo; Pixy2SPI_SS pixy; //Create PixyCam2 object using the SPI/Arduino interface. struct light_type{ int x; int y; int frame_angle_x; int angle_x; int angle_y; int temp; }; light_type light[3];
…
void record_xy_location(){ Serial.println("+++++In record_xy_location..."); if(pixy.ccc.numBlocks == 0){ Serial.println("There are no blocks in this frame."); return; } for(int l = 0;l<pixy.ccc.numBlocks;l++){ Serial.print("We are dealing with block# ");Serial.print(l+1);Serial.print(" of ");Serial.println(pixy.ccc.numBlocks); Serial.print("pixy.ccc.blocks[l].m_x = ");Serial.println(pixy.ccc.blocks[l].m_x); Serial.print("pixy.ccc.blocks[l].m_y = ");Serial.println(pixy.ccc.blocks[l].m_y); int j = map(pixy.ccc.blocks[l].m_x,0,315,pan_servo.read()+50,pan_servo.read()-50); int k = map(pixy.ccc.blocks[l].m_y,0,207,tilt_servo.read()+20,tilt_servo.read()-20); Serial.print("Mapped angles of light = (j,k)(x,y)");Serial.print(j);Serial.print(" , ");Serial.println(k); //beta3 if(j < pan_limit_1 || j > pan_limit_2 ){ //https://stackoverflow.com/questions/6302227/how-to-break-out-of-a-function/6302235 Serial.println("J is out of bounds of delta(pan_limit_1,pan_limit_2)"); return; } if(k < tilt_limit_1 || k > tilt_limit_2 ){ //https://stackoverflow.com/questions/6302227/how-to-break-out-of-a-function/6302235 Serial.println("k is out of bounds of delta(tilt_limit_1,tilt_limit_2)"); return; } //beta2 for (int i = 0; i<3; i++){ if(light[i].angle_x!=0){ if((j < (light[i].angle_x + 20)) || (j > (light[i].angle_x - 20))){ newVal=false; } else{ newVal=true; } } else{ isEmpty = i; Serial.println("For loop broken"); break; //this is an empty spot (equal to 0), theres no more need to compare. We can assume all values after this spot are empty too. break the for loop. } if (newVal=true){ Serial.println("Adding new val"); light[isEmpty].x=pixy.ccc.blocks[l].m_x; light[isEmpty].y=pixy.ccc.blocks[l].m_y; light[isEmpty].frame_angle_x=pan_servo.read(); light[isEmpty].angle_x=j; light[isEmpty].angle_y=k; newVal=false; } } } //Debugging prints Serial.println("After recording xy is complete:"); for(int i = 0; i<3; i++){ Serial.print("i = ");Serial.print(i); Serial.print(" x = ");Serial.print(light[i].x); Serial.print(" y = ");Serial.print(light[i].y); Serial.print(" frame_angle_x = ");Serial.print(light[i].frame_angle_x); Serial.print(" angle_x = ");Serial.println(light[i].angle_x); } }