Pwm Duty Cycle motor speed using registers

when i press pulsador the motor starts at 100% speed then when it hits sensor 1 a led turns on and the cycle reduces to 80%(motor speed), after that it hits sensor 3 and the motor turns off then it comes a delay of 2000 ms after that delay the motor starts at 65% duty cycle(motor speed), and finally when it hits sensor 4 the motor and led goes off.
My question is, does this code work? because the osciloscope doesnt´t work properly on thinkercad with timer 1.
i commented digitalWrite(Motor,HIGH); is it necessary to add it when i change the duty with OCR1B?

   // C++ code
int p=1;
  #define pulsador 9
  #define sensor1 6
  #define sensor2 5
  #define sensor3 7
  #define led 12 
  #define motor 11
  
void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
   
  pinMode(sensor1, INPUT); //SENSOR1
  
  pinMode(motor, OUTPUT);//SALIDA1
  pinMode(led, OUTPUT);  //LED X
  pinMode(sensor2, INPUT); //SENSOR2
  pinMode(sensor3, INPUT); //SENSOR3
  pinMode(pulsador, INPUT_PULLUP);
  
}
void InitPWM1() {
  cli();
  OCR1A =2500; //64 Preescaler
  OCR1B = 0;
  TCCR1B |= (1 << WGM12) | (1 << WGM13);
  TCCR1A |= (1 << WGM10) | (1 << WGM11);     
  //Timer 1 Preescaler 64
  TCCR1B &= ~(1 << CS12);
  TCCR1B |= (1 << CS11);
  TCCR1B |= (1 << CS10);
  TCCR1A |= (1 << COM1B1);
  TCCR1A &= ~ (1 << COM1B0);
  TIMSK1 |= (1 << OCIE1A);    
  sei();
}


int main(void){
  
  DDRB |= (1 << DDB3); //osciloscopio pin 11 motor
  InitPWM1();

  while(1){
   
   if ((digitalRead(sensor1)==HIGH) and(p==1)){
     digitalWrite(led, HIGH);
     OCR1B = 2000; //80% duty, the speed of the motor
     //digitalWrite(motor, HIGH);
     p=0;
   }if (digitalRead(pulsador)==LOW) {
     
     digitalWrite(motor, HIGH);
     
   }if ((digitalRead(sensor2) == HIGH) and (p==0)){
      digitalWrite(motor, LOW);
      delay(2000);
      OCR1B = 1625;//65% duty, the speed of the motor
      //digitalWrite(motor, HIGH);
      
      
      p=2;
   }if ((digitalRead(sensor3) == HIGH) and (p==2)){
      
      
      digitalWrite(led, LOW);
      digitalWrite(motor, LOW);
      p=1;
    }   
  
  }
}    
    
   
   

80% duty cycle means the motor is at 80% speed

I think when you assign timer functions to a pin (e.g. COMxBy) you disconnect the pin from the PORTB register. To force a high or low using digitalWrite() you also need to set COM1B1 and COM1B0 (in this case) to 00.

When you want to resume timer control of the pin, reset the two bits as before.

Can you give me an example? So you set comb1 and comb0 to 0 in the setup and then? How do i reset the bits?

What if i do this?

  #define pulsador 9
  #define sensor1 6
  #define sensor2 5
  #define sensor3 7
  #define led 12 
  #define motor 11
  
void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
   
  pinMode(sensor1, INPUT); //SENSOR1
  
  pinMode(motor, OUTPUT);//SALIDA1
  pinMode(led, OUTPUT);  //LED X
  pinMode(sensor2, INPUT); //SENSOR2
  pinMode(sensor3, INPUT); //SENSOR3
  pinMode(pulsador, INPUT_PULLUP);
  
}
void InitPWM1() {
  cli();
  OCR1A =2500; //64 Preescaler
  OCR1B = 0;
  TCCR1B |= (1 << WGM12) | (1 << WGM13);
  TCCR1A |= (1 << WGM10) | (1 << WGM11);     
  //Timer 1 Preescaler 64
  TCCR1B &= ~(1 << CS12);
  TCCR1B |= (1 << CS11);
  TCCR1B |= (1 << CS10);
  TCCR1A |= (1 << COM1B1);
  TCCR1A &= ~ (1 << COM1B0);
  TIMSK1 |= (1 << OCIE1A);    
  sei();
}


int main(void){
  
  DDRB |= (1 << DDB3); //osciloscopio pin 11 motor
  InitPWM1();

  while(1){
   
   if ((digitalRead(sensor1)==HIGH) and(p==1)){
     digitalWrite(led, HIGH);
     OCR1B = 2000; //80% duty, the speed of the motor
     //digitalWrite(motor, HIGH);
     p=0;
   }if (digitalRead(pulsador)==LOW) {
     
     //digitalWrite(motor, HIGH);
      OCR1B = 2500;
   }if ((digitalRead(sensor2) == HIGH) and (p==0)){
      //digitalWrite(motor, LOW);
      
      OCR1B = 0;
      
      delay(2000);
      OCR1B = 1625;//65% duty, the speed of the motor
      //digitalWrite(motor, HIGH);
      
      
      p=2;
   }if ((digitalRead(sensor3) == HIGH) and (p==2)){
      
      
      digitalWrite(led, LOW);
      //digitalWrite(motor, LOW);
      OCR1B = 0;
      
      p=1;
    }   
  
  }
}    

I mean something like this:

NOTE: I'm not sure which Arduino you're using. I tested this on a Mega2560 and adjusted the OC1B (motor) output and LED pins accordingly. YMMV.

uint8_t p = 1;

const uint8_t pulsador = 9;
const uint8_t sensor1 = 6;
const uint8_t sensor2 = 5;
const uint8_t sensor3 = 7;

//const uint8_t led = 12;
const uint8_t led = LED_BUILTIN; 
//on Uno OC1B goes to pin 10
//const uint8_t motor = 10;
//on Mega2560 OC1B goes to pin 12
const uint8_t motor = 12;

#define PERIOD  2499

void setup()
{
    Serial.begin(115200);
    
    pinMode(LED_BUILTIN, OUTPUT);   
    pinMode(sensor1, INPUT); //SENSOR1  
    pinMode(motor, OUTPUT);//SALIDA1
    pinMode(led, OUTPUT);  //LED X
    pinMode(sensor2, INPUT); //SENSOR2
    pinMode(sensor3, INPUT); //SENSOR3
    pinMode(pulsador, INPUT_PULLUP);

    DDRB |= (1 << DDB3); //osciloscopio pin 11 motor
    InitPWM1();

}//setup

void InitPWM1() 
{
    noInterrupts();    
    //WGM15, /64
    digitalWrite( motor, LOW );
    TCCR1A = _BV(WGM11) | _BV(WGM10);
    TCCR1B = _BV(WGM13) | _BV(WGM11) | _BV(CS11) | _BV(CS10);
    OCR1A = PERIOD; //with /64 prescaler gives 100Hz
    OCR1B = 0;
    
    //TIMSK1 |= (1 << OCIE1A);    //needed/used?
    interrupts();
    
}//InitPWM1

int main(void)
{  
    while(1)
    {   
    if( (digitalRead(sensor1) == HIGH) and (p == 1) )
    {
        digitalWrite(led, HIGH);
        SetDuty( 80 );
        p=0;
        
    }//if
    
    if( digitalRead(pulsador) == LOW ) 
    {             
        SetDuty( 100 );
        
    }//if
    
    if( (digitalRead(sensor2) == HIGH) and (p == 0) )
    {
        SetDuty( 65 );      
        p=2;
    }
   
    if( (digitalRead(sensor3) == HIGH) and (p == 2) )
    {           
        digitalWrite(led, LOW);
        SetDuty( 0 );
        p=1;
    }
  
  }//while
  
}//main

void SetDuty( uint8_t dc )
{
    switch( dc )
    {
        case    0:
            digitalWrite( motor, LOW );
            TCCR1A &= ~(_BV(COM1B1));
        break;

        case    100:
            digitalWrite( motor, HIGH );
            TCCR1A &= ~(_BV(COM1B1));
        break;

        default:
            OCR1B = (uint16_t)( (float)PERIOD * (float)dc/100.0 );
            TCCR1A |= _BV(COM1B1);
            
        break;
        
    }//switch
        
}//SetDuty

Arduino uno atmega326

Hi, @tj_1

Why aren't you using the code analogWrite PWM function?

I can just about guarantee that 80% duty cycle will not equal 80% max speed, likewise 65%.

when i press pulsador the motor starts at 100% speed
then when it hits sensor 1 a led turns on and the cycle reduces to 80%(motor speed),
after that it hits sensor 3 and the motor turns off
then it comes a delay of 2000 ms
after that delay the motor starts at 65% duty cycle(motor speed),
finally when it hits sensor 4 the motor and led goes off.

What happened to sensor2?

Tom.. :smiley: :+1: :coffee: :australia:

WARNING: When you define your own 'main()', your 'setup()' and the library initialization functions are not called. I recommend you change:

int main(void)
{  
    while(1)
    { 

to

void loop()
{