Servo to move down after cycle has finished

Hey all,

Probably most of you have seen this tutorial on heat seeking fan on instructables:
Heat-Seeking-Desk-Fan-using-Arduino

so i have done it for my my project in college, but i want to add something to it.
I have added a second servo to the project so the sensor can move left to right, up and down.
I am alright with hardware and electronics, but programming i have to learn much more....
So i was wandering could you please give me some clues or hints on how to write a code which move servo down only twice e.g. servo is at 0 degrees, does a program cycle, moves down 30 degrees, does a program cycle, moves 30 degrees, does a cycle and returns to 0 degrees and repeats....

One of the teachers advised me to add counter, which will count how many cycles program has done and every time it has finished a cycle it adds 1 to a counter

int counter = 0;

(I do not know how to let program know when it has finished one cycle and how do i set up a counter)

finished 1st cycle = 0
finished 2nd cycle +1 = 1
finished 3rd cycle +1 = 2

(also, how do you make a program remember how many cycles it has finished before?)

So then we have three cases
Case0
Case1
Case2

case '0':
servoMain.write(30);
break;
case '1':
servoMain.write(60);
break;
case '2':
servoMain.write(0);
break;

I will greatly appreciate any help provided any tips given will memorized and learnt

Thank you very much guys

Karlou :slight_smile:

Suppose you have a small function that controls the extra servo and which is called from loop()

void moveServo() {
   myServo.write(servoPos);
}

Then your other code just needs to update the value of servoPos at the end of each cycle - for example

servoPos += 30;
if (servoPos > 60) {
   servoPos = 0;
}

...R

Thank you for your reply!

about the second code,

Do i put it inside void loop() at the end of all code?
As far as i know, servo cannot send its position back to arduino. So can i really use second code for that?

Original code(credit goes to right people, not me):

//TrackFan//
//Code and concept by ePums
//tempRead code by Dave Eaton and SensorJunkie

#include <Servo.h>
#include <i2cmaster.h>

Servo mrservo;

int j = 0;
int pos;
int posVals[]= {
5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120 };
double tempVals[24];
int hotPos;

void tempRead(){

//Define function for reading the temperature from the IR Sensor.
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);

i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();

//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB
double tempData = 0x0000;
int frac;

// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;
tempData = tempData - 273.15;

tempVals[j] = tempData;
j+=1;
}

void servoSweep(){
Serial.println("Sweeping area.....");
j = 0;
pos = 0;
//reset pos and temp indices
delay(500);
Serial.println("Positions: ");
//return servo to initial position
for (pos = 5; pos < 130; pos +=5)
{
mrservo.write(pos);
//move servo 10 degrees
delay(250);
//allow sensor to settle
tempRead();
Serial.println(pos);
//read and store temp data
delay(250);
}
}

void findHot(){
Serial.println ("Finding hottest spot");
//find highest temperature, move servo to corresponding position
int i = 0;
//local search index
int q = 0;
double hotTemp = tempVals[0];
//the position data associated with the highest temperature in a given sweep
for (i=0; i < 24; i+=1) {
if (tempVals >= hotTemp) {
_ hotTemp =tempVals*;_
_
Serial.print("#" + String(i) + " Hottest Temperature: ");_
_
Serial.println(hotTemp);_
_
delay(50);_
_
q = i;_
_
//retrieve index for highest temp value in tempVals array*_
* }*
* }*
* hotPos = posVals[q];*
_ Serial.println("*** Hottest Position at " + String(hotPos) + "degrees");_

* //retrieve the corresponding pos value from posVals index*
* if (mrservo.attached()) {*
* Serial.println("This is reading output right now");*
* }*
* delay(500);*
* mrservo.detach();*
* mrservo.attach(3);*
* mrservo.write(hotPos);*
* delay(500);*
* //move the servo*
* Serial.println("Returning to hottest position....");*

_ /////////DELAY BETWEEN SCANS////////////////
* delay(10000);*
* i=0;*
}
void setup(){
* Serial.begin(9600);*
* i2c_init();
_
PORTC = (1 << PORTC4) | (1 << PORTC5);*

}
void loop(){
* mrservo.attach(3);*
* delay(500);*
* mrservo.write(0);*
* i2c_init();
_
servoSweep();_
_
Serial.println("Temperatures!");_
_
for (int n=0; n < 2; n += 1) {_
_
Serial.println(tempVals[n]);_
_
delay(50);_
_
}_
_
findHot();_
_
mrservo.detach();_
_
delay(100);_
_
}*_
Regards

Karlou:
about the second code,

Do i put it inside void loop() at the end of all code?
As far as i know, servo cannot send its position back to arduino. So can i really use second code for that?

Your long code is too hard to read quickly because it is not in code tags (the scroll with <>)

so it looks like this

The second code should go wherever in your program you need to update the position.

The function (the first code) can go anywhere as long as it is not inside another function. I usually put my functions after the loop() function.

I don't understand your question about not being able to read the servo position - I had no thought of doing that.

...R

//**TrackFan**//
//Code and concept by ePums
//tempRead code by Dave Eaton and SensorJunkie

#include <Servo.h>
#include <i2cmaster.h>

Servo mrservo;

int j = 0;
int pos;
int posVals[]= {
 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120 };
double tempVals[24];
int hotPos;

void tempRead(){

//Define function for reading the temperature from the IR Sensor.
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);


i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();

//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB
double tempData = 0x0000;
int frac;

// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;
tempData = tempData - 273.15;

tempVals[j] = tempData;
j+=1;
}


void servoSweep(){
Serial.println("Sweeping area.....");
j = 0;
pos = 0;
//reset pos and temp indices
delay(500);
Serial.println("Positions: ");
//return servo to initial position
for (pos = 5; pos < 130; pos +=5)
{
  mrservo.write(pos);
  //move servo 10 degrees
  delay(250);
  //allow sensor to settle
  tempRead();
  Serial.println(pos);
  //read and store temp data
  delay(250);
}
}

void findHot(){
Serial.println ("Finding hottest spot");
//find highest temperature, move servo to corresponding position
int i = 0;
//local search index
int q = 0;
double hotTemp = tempVals[0];
//the position data associated with the highest temperature in a given sweep
for (i=0; i < 24; i+=1) {
  if (tempVals >= hotTemp) {
    hotTemp =tempVals;
    Serial.print("#" + String(i) + " Hottest Temperature: ");
    Serial.println(hotTemp);
    delay(50);
    q = i;
    //retrieve index for highest temp value in tempVals array
  }
}
hotPos = posVals[q];
Serial.println("*** Hottest Position at " + String(hotPos) + "degrees");

//retrieve the corresponding pos value from posVals index
if (mrservo.attached()) {
  Serial.println("This is reading output right now");
}
delay(500);
mrservo.detach();
mrservo.attach(3);
mrservo.write(hotPos);
delay(500);
//move the servo
Serial.println("Returning to hottest position....");


/////////**DELAY BETWEEN SCANS**////////////////
delay(10000);

i=0;
}


void setup(){
Serial.begin(9600);
i2c_init();
PORTC = (1 << PORTC4) | (1 << PORTC5);
}

void loop(){
mrservo.attach(3);
delay(500);
mrservo.write(0);
i2c_init();
servoSweep();
Serial.println("Temperatures!");
for (int n=0; n < 2; n += 1) {
  Serial.println(tempVals[n]);
  delay(50);
}
findHot();

mrservo.detach();
delay(100);
}

Thanks for putting your code is code tags. I have now had a look at it in my text editor.

A few things spring to mind
== you have an awful lot of delay()s - you might wish to look at several things at a time which illustrates how to manage time without using the delay() function.

== I would only attach the servo in setup() and leave it attached all the time.

== You are making good use of functions to split up your code. However I think calling an important function servoSweep() may be hiding its true activity - which is to scan temperatures - in a sense the servo is subservient to that. I suspect if you restructure that part it will be more obvious where the extra code for the other servo should go.

The logic I have in mind is
start temp scan
increment horizontal position
if horizontal position is max
increment vertical position
if vertical pos is max
exit from function
set horizontal pos to 0
read and save temperature
repeat as necessary

You did not answer my question about your question about reading the servo position.

...R

Thank you very much for your help, you saved my days (or weeks) :)))

oh and that question, forget it i have tried your code on its own and it is working fine, this is how i have done it:

#include <Servo.h>

Servo myServo;

int servoPos;

void setup(){
myServo.attach(1);
}

void loop(){
  moveServo();
}

void moveServo() {
  
   myServo.write(servoPos);
   servoPos += 15;
  delay(500);
if (servoPos > 30) {
   servoPos = 0;
}
}

and i put it inside original code and it is working perfectly fine, moves down after every cycle and returns to original position after two cycles :)))

I am very thankful for your help !!!!!

Now i have cracked basics in arduino and C++ :smiley:

At first i was getting vertical servo to move up in pulses, until i understood that i have connect it to digital pin 1, which is TX and every time it is sends a signal to horizontal servo, it also sends pulses to digital pin 1 aka vertical servo. ;/

Karlou:
At first i was getting vertical servo to move up in pulses, until i understood that i have connect it to digital pin 1, which is TX and every time it is sends a signal to horizontal servo, it also sends pulses to digital pin 1 aka vertical servo. ;/

I presume that means that you are now NOT using pin1 for your servo?

Good to hear it is working.

...R