pin LOW when a condition is reached after setting PWM on that PIN

Hello to everybody,

I have settled the PWM on the pin 10 of my Arduino Mega to 1 kHz using Timer 2. After certain time, when a condition is reached (counter==1000), I want to output low signal (0V) from that pin. The problem is that my PIN will not go down even if i state digitalWrite(10, LOW);

That's my simple code:


const byte PULSES = 10; // Timer 2 "A" output: OC2A --> 1 kHz
const byte home_switch=9; // Pin 9 connected to Home Switch (Photointerrupter)
#define encoderPinA 2
#define encoderPinB 3
volatile int counter =0;
unsigned long time;
int incomingByte = 0; // for incoming serial data

void setup() {
pinMode (PULSES, OUTPUT);
pinMode(home_switch, INPUT_PULLUP);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
attachInterrupt(digitalPinToInterrupt(encoderPinA), isr,RISING);
Serial.begin(9600);

delay(5); //

// set up Timer 2
int myEraserPulses = 7; // this is 111 in binary and is used as an eraser
TCCR2B &= ~myEraserPulses; // this operation (AND plus NOT), set the three bits in TCCR2B to 0

TCCR2A = _BV(COM2A0) | _BV(WGM21) | _BV(WGM20); // fast PWM
TCCR2B = _BV(WGM22) | _BV(CS21) | _BV(CS22); // 16MHz/256=62.5kHz
OCR2A = 30; // 62.5kHz/1kHz=62.5 (50% duty--> 30)

} // end of setup

void loop() {

if(counter==1000)
digitalWrite(10, LOW); //output 0 V so the motor will stop
else
digitalWrite(10, HIGH); // continue to output PWM at 1kHz

if (Serial.available() >= 0) { // read the incoming byte:
incomingByte = Serial.read();

Serial.print(counter);
Serial.print("\t");

Serial.print("Time: ");
time = millis();
Serial.println(time); //prints time since program started

if (incomingByte=='0') { //pressing 0 into the serial monitor to stop the program
while(1) { }
}
}
}
//Interrupts
void isr(){

int channel_A = digitalRead(encoderPinA);
int channel_B = digitalRead(encoderPinB);

if(channel_A == channel_B){
counter++;
}
else{
counter--;
}
}

Thanks for your help.

I think you will have to turn off the PWM output before you try to set the output. I think setting TCCR2A to 0 will stop the PWM output (by setting COM2A0 and COM2A1 to 0).

Thanks for the prompt answer. Do you mean something like that?

void setup() {
pinMode (PULSES, OUTPUT);
pinMode(home_switch, INPUT_PULLUP);
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
attachInterrupt(digitalPinToInterrupt(encoderPinA), isr,RISING);
Serial.begin(9600);

delay(5); //

// set up Timer 2
int myEraserPulses = 7; // this is 111 in binary and is used as an eraser
TCCR2B &= ~myEraserPulses; // this operation (AND plus NOT), set the three bits in TCCR2B to 0

TCCR2A = _BV(COM2A0) | _BV(WGM21) | _BV(WGM20); // fast PWM
TCCR2B = _BV(WGM22) | _BV(CS21) | _BV(CS22); // 16MHz/256=62.5kHz
OCR2A = 30; // 62.5kHz/1kHz=62.5 (50% duty--> 30)

} // end of setup

void loop() {

if (counter==-1000)
TCCR2A &= ~(_BV(COM2A0));
else
TCCR2A = _BV(COM2A0) | _BV(WGM21) | _BV(WGM20);
}


I tried but it doesn't work.

D10S:
Thanks for the prompt answer. Do you mean something like that?

void loop() {

if (counter==-1000)
   TCCR2A &= ~(_BV(COM2A0));
 else
   TCCR2A = _BV(COM2A0) | _BV(WGM21) | _BV(WGM20);
}



I tried but it doesn't work.

More like:

void loop()
{
  if (counter == -1000)
  {
    Serial.println(F("PWM OUTPUT OFF"));
    TCCR2A &= ~(_BV(COM2A0));  // Turn off PWM output
    digitalWrite(PULSES, LOW); //output 0 V so the motor will stop
  }
  else
  {
    TCCR2A |= _BV(COM2A0);  // Make sure PWM output is on
  }

It actually doesn't work. In the serial port it will show "PWM OUTPUT OFF" but the the motor will not stop since the pwm is still at 1 Khz. It isn't dropping to 0V.

See "fail" attached.

This is probably because count is a VOLATILE INT?

I still think the problem is that the PWM is not going out because it is actually able to understand when count is 1000

Please post the entire revised code. Also please bracket it with code tags as you can see done in reply#3. There are instructions on how to do that in the sticky threads at the top of the forum.

Error messages should be posted that way, too.

That's the revised code. Apologize for that

const byte PULSES = 10;  // Timer 2 "A" output: OC2A --> 1 kHz
const byte home_switch=9; // Pin 9 connected to Home Switch (Photointerrupter)


#define encoderPinA 2 // encoder channel A
#define encoderPinB 3 // encoder channel B
volatile int counter =0; // pulses counter of the encoder
unsigned long time;
int incomingByte = 0;   // for incoming serial data

void setup() {
pinMode (PULSES, OUTPUT); // set the pulses pin as output
pinMode(home_switch, INPUT_PULLUP); // set the photointerrupter as an input
pinMode(encoderPinA, INPUT); // set the encoder as an input
pinMode(encoderPinB, INPUT); // set the encoder as an input
attachInterrupt(digitalPinToInterrupt(encoderPinA), isr,RISING); //pulses counting
Serial.begin(9600);

 delay(5);  //
 
  // set up Timer 2
int myEraserPulses = 7;             // this is 111 in binary and is used as an eraser
TCCR2B &= ~myEraserPulses;   // this operation (AND plus NOT),  set the three bits in TCCR2B to 0

TCCR2A = _BV(COM2A0) | _BV(WGM21) | _BV(WGM20); // fast PWM
TCCR2B = _BV(WGM22) | _BV(CS21) | _BV(CS22); // 16MHz/256=62.5kHz
OCR2A = 30; // 62.5kHz/1kHz=62.5 (50% duty--> 30)       

}  // end of setup

void loop()
{
  if (counter == -1000)
  {
    Serial.println(F("PWM OUTPUT OFF"));
    TCCR2A &= ~(_BV(COM2A0));  // Turn off PWM output
    digitalWrite(PULSES, LOW); //output 0 V so the motor will stop
  }
  else
  {
    TCCR2A |= _BV(COM2A0);  // Make sure PWM output is on
  }

if (Serial.available() >= 0) {  // read the incoming byte:
  incomingByte = Serial.read();
 
  Serial.print(counter);
  Serial.print("\t");
 
  Serial.print("Time: ");
  time = millis();
  Serial.println(time); //prints time since program started
 
if (incomingByte=='0') { //pressing 0 into the serial monitor to stop the program
   while(1) { }
}
}
}
//Interrupts
void isr(){

    int channel_A = digitalRead(encoderPinA);
    int channel_B = digitalRead(encoderPinB);
 
   if(channel_A == channel_B){
    counter++;
   }
   else{
    counter--;
   }       
}

Even if it is able to understand when count reaches -1000, the signal on the PULSE input will not drop to 0. Therefore the motor is not stopping

I actually SOLVED it! The problem was that the encoder readings might not be 1000 but 1002 or 996, so i just picked a range of values:

void loop()
{
  if (counter > -1005 && counter < -995)
  {
    Serial.println(F("PWM OUTPUT OFF"));
    TCCR2A &= ~(_BV(COM2A0));  // Turn off PWM output
    digitalWrite(PULSES, LOW); //output 0 V so the motor will stop
  }
  else
  {
    TCCR2A |= _BV(COM2A0);  // Make sure PWM output is on
  }

Thanks guys!