I couldn't run a servo motor from interrupt.

#include <EEPROM.h>
#include <Servo.h>

Servo servo; 

int sensorPin = A0;
int sensorValue = 0;
int percentValue = 0;

int servo_speed = 3000;

bool servostate = false;


bool direct  = false;
int pos = 0;
int address1 = 0;
int address2 = 1;

int timer1_counter;
void setup() 
{
  Serial.begin(9600);

  servo.attach(6);
  pos = EEPROM.read(address1);
  direct = EEPROM.read(address2);
  
  cli(); 
  TCCR2A = 0;
  TCCR2B = 0;
  TCNT2  = 0;

  OCR2A = 246;

  TCCR2A |= (1 << WGM21);
  TCCR2B |= (1 << CS21);   
  TIMSK2 |= (1 << OCIE2A);
  sei();
}

ISR(TIMER2_COMPA_vect)
{
  Serial.println("-------------Kesmede-------------");
  sensorValue = analogRead(sensorPin);
  Serial.print("\n\nAnalog Value: ");
  Serial.println(sensorValue);
  percentValue = map(sensorValue, 1023, 200, 0, 100);
  Serial.print("\nPercentValue: ");
  Serial.print(percentValue);
  Serial.println("%");
  
  if(percentValue > 50)
  {
    servostate = false;
  }
  else if(percentValue < 5)
  {
    servostate = true;
  }
  
}

void loop() 
{

  if(servostate)
  {
      servo.write(pos);
    
      if(pos == 180) 
      {
        direct = true;
        EEPROM.write(address2, direct);
      }
      else if (pos == 0) 
      {
        direct = false;
        EEPROM.write(address2, direct);
      }
  
      if(direct) pos--;
      else pos++;
      
      EEPROM.write(address1, pos);
  
      delay(servo_speed/180);
  }
    
 }

I have soil moisture, the value read by analogRead is below 50 servo work, over 50 servo should not work.

The code I’ve written seems to be smooth when I debug with serial.print.
But while the sensor reads the value, the servo motor doesnt work. I’m getting this issue because the servo motor library uses timer1. How can I solve this problem using interrupt?
(I must use interrupt) Thanks…

You know when we say “don’t do serial I/O in interrupt context” ?

We really, really mean it.

Sorry I couldnt understand, do you mean if I remove serial lines it'll be work fine ?

No, I mean, don’t do it.

so how can i read analog value and use servo with interrupt ?

@yoobibikunn, please post your program as a single piece so we don't have to stick the bits together.

And please do that in your next Reply rather than modifying your earlier Post which has already been commented on.

...R

Well you could use the end of conversion interrupt for the analogue input, and the Servo library already uses timer interrupts.

AWOL:
Well you could use the end of conversion interrupt for the analogue input, and the Servo library already uses timer interrupts.

I'm sorry but I dont understand "end of conversion interrupt" what kind of interrupt can you explain.

The ADC is a successive approximation convertor, and at the end of the conversion (typically around 100 microseconds after conversion start) the convertor can generate an end-of-conversion interrupt.
Enabling this interrupt and providing an interrupt service routine will give you the result you desire.

It is documented in the processor's datasheet.

Mind you, the concept of a “newbie” daring to use interrupts for any purpose is a concern, suggesting that the whole plan is wrong. :astonished:

Another XY problem! :roll_eyes:

Paul__B:
Another XY problem! :roll_eyes:

More likely homework.

Robin2:
@yoobibikunn, please post your program as a single piece so we don't have to stick the bits together.

And please do that in your next Reply rather than modifying your earlier Post which has already been commented on.

@yoobibikunn, how come you deliberately ignored my second request?

...R

Robin2:
@yoobibikunn, how come you deliberately ignored my second request?

...R

Sorry i didnt understand you :frowning:

yoobibikunn:
Sorry i didnt understand you :frowning:

I can't see what is difficult about the sentence "please do that in your next Reply rather than modifying your earlier Post which has already been commented on"

...R

yoobibikunn:
Sorry i didn’t understand you :frowning:

OK, clearly you do not understand how to write a program to do what you want to do.

I suspect it is actually quite simple. You have posed the classic “XY problem” (check out the link!); you have shown a program attempting to do something in the manner you - wrongly - thought it might be done instead of simply detailing what the problem is.

So please, sit down and write out the plan - the requirements of the project - for us.

I get the idea from your first description that this is a relatively simple task where you read an analog input and compare it to a threshold value. If it is above a threshold, nothing happens, if it is below a threshold a servo needs to to something. What is that “something” then? Does it have to move from one position to another or does it have to repetitively perform a reciprocating action? When the threshold is again exceeded, does the servo need to return to a rest value or does it not matter?

If you can present a properly detailed plan, we can pull from your unfortunate code, the elements needed to do it properly. :grinning:

Paul__B:
OK, clearly you do not understand how to write a program to do what you want to do.

If you can present a properly detailed plan, we can pull from your unfortunate code, the elements needed to do it properly. :grinning:

The project that I try to do is the smart garden water system, the sensor “Soil Moisture Sensor for Arduino | Smart Prototyping” that I use is measuring the humidity in the soil and I want the servo to work if the humidity in the soil is below 5% and the servo motor doesn’t work if it is above 50%. I do the value reading from the sensor in the interrupt, I tried to run the servo motor in the loop, but the servo does not work. So my X problem is how I can start and stop the servo suddenly according to the value in the sensor.

#include <TimerOne.h>
#include <Servo.h>
#include <EEPROM.h>

Servo servo;

int sensorPin = A0;
int sensorValue = 0;
int percentValue = 0;

int servo_speed = 3000;
bool state = false;
bool servostate = false;

bool direct  = false;
int pos = 0;
int address1 = 0;
int address2 = 1;


void setup() 
{
  Serial.begin(9600);

  servo.attach(6);
  pos = EEPROM.read(address1);
  direct = EEPROM.read(address2);
  
  Timer1.initialize(1000000);
  Timer1.attachInterrupt( timerIsr ); // enable the timer
}


void timerIsr()
{
  Timer1.detachInterrupt();  //stop the timer
  sensorValue = analogRead(sensorPin);
  Serial.print("\n\nAnalog Value: ");
  Serial.println(sensorValue);
  percentValue = map(sensorValue, 1023, 200, 0, 100);
  Serial.print("\nPercentValue: ");
  Serial.print(percentValue);
  Serial.println("%");
  
  if(percentValue > 50)
  {
    servostate = false;
  }
  else if(percentValue < 5)
  {
    servostate = true;
  }
  Timer1.attachInterrupt( timerIsr );  //enable the timer
}

void loop() {
  if(servostate)
  {
      servo.write(pos);
    
      if(pos == 180) 
      {
        direct = true;
        EEPROM.write(address2, direct);
      }
      else if (pos == 0) 
      {
        direct = false;
        EEPROM.write(address2, direct);
      }
  
      if(direct) pos--;
      else pos++;
      
      EEPROM.write(address1, pos);
  
      delay(servo_speed/180);
  }

}

Im using EEPROM for save servo direct and pos.

I download timer library here → Google Code Archive - Long-term storage for Google Code Project Hosting.

OK, here's the situation.

You supposedly know what it is you want to do, but you fail to understand that we do not know what that is because you have not disclosed it. It is a matter of failed communication.

You continue to use completely nonsensical terms such as "run the servo motor" and "start and stop the servo". What is this servo motor? What does it do? What does "the servo motor doesn't work if it is above 50%" mean? I begin to wonder if you even know yourself! :astonished:

You have got yourself wound up with completely irrelevant things such as interrupts and a timer library. Neither of these is in any way even remotely relevant to your project and posting code which includes them is a waste of everyone's time.

To follow from @Paul__B's question in Reply #16 please answer these questions.

  • How often does the soil moisture content need to be checked? (my guess is that two or three times a day would be enough).
  • If the soil is too dry what mechanism do you have to add water to it?
  • How big is the area of soil that you wish to manage?

...R

Why are you using an interrupt anyway. The timer should only be used to time when the soil moisture reading is taken. The speed and angle determine the time the servo will move.
I think it should be something like this : read moisture if moisture good do nothing else if moisture bad turn servo ( tap on ) read moisture if moisture good turn servo opposite direction ( tap off) else if moisture bad do nothing ( leave tap on ).
There is no way to trigger an interrupt using software ,it must be done using an input.
If you still need to use interrupt try using a digital write ( high) on a pin example pin 9. Run a wire from pin 9 to your chosen interrupt pin. When you require the interrupt the digitalWrite command on pin 9 will send a high signal to the interrupt pin and trigger the interrupt.

Ripcrow:
Why are you using an interrupt anyway.

Due to complete ignorance of what an interrupt is in a microcontroller/ computer. :astonished:

Ripcrow:
I think it should be something like this : read moisture if moisture good do nothing else if moisture bad turn servo ( tap on ) read moisture if moisture good turn servo opposite direction ( tap off) else if moisture bad do nothing ( leave tap on ).

I am probing for some description of whether the servo is supposed to turn a tap (in which case a little "hobby" servo would not be capable) or whether it must operate a bucket pump (same problem) or what! :grinning:

Ripcrow:
If you still need to use interrupt try using a digital write ( high) on a pin example pin 9. Run a wire from pin 9 to your chosen interrupt pin. When you require the interrupt the digitalWrite command on pin 9 will send a high signal to the interrupt pin and trigger the interrupt.

Absolutely, incontestably, no possible use whatsoever for an interrupt. :roll_eyes: