PWM motor speed control with feedback

Dear all,

Until now I've been succesful in letting the motor run on various constant speeds using PWM. However, this is under constant load, which will not be the case for the final system.

If I let the motor run on a given speed I see a frequency of approximately 2000Hz on the oscilloscope for the PWM blocks. Where this frequency comes from is unclear to me. My attiny2313 uses a prescaler of 1 (TCCR0B = (1 << CS00); ), thus 8 MHz. Now I believe that a PWM block is devided by 256, as OCR0A = 255; gives a duty cycle of 100%, and OCR0A = 0; a duty cycle of 0%. Now if I multiply these numbers I find a pulsefrequency of 256 x 2000 = 512000 Hz, which is unequal to the expected 8 MHz. Is my reasoning correct here or am I missing something?

Next thing which is unclear to me is how the sequence of PWM and code is handeled.
Let's say I write

speed = 128;

while(true){
   OCR0A = speed; 

duration = pulseIn(PD6,HIGH);

if (duration > desired){
speed --
}
else{
speed++
}

Where PD6 is the encoder which feedbacks counts per rotation. Is here the OCR0A handeled first, whereafter the pulseIn starts counting? Or after OCR0A is set to 128, the pulseIn starts counting immediatly? In what sequence is the code handeled? I have looked on google, but can't find the correct searching terms.
With the current code I get some strange oscilating behavior.

Hope somebody can help me in the right direction.

speed = 128;

while(true){
   OCR0A = speed; 

duration = pulseIn(PD6,HIGH);

if (duration > desired){
speed --
}
else{
speed++
}

That's not your real code is it ?

Full script is here. Last part is messy, because I've tryed many things there now.

/* --------------------------------------------------
/ Pin connection:
/					  	  ----------	
/        		RST	 -PA2	VCC-  VCC
/		 SW_vselect	 -PD0	PB7-  LED_v1
/		 SW_confirm	 -PD1	PB6-  LED_v2
/				 -PA1	PB5-  LED_v3
/  				 -PA0	PB4-  LED_v4
/				 -PD2	PB3-  LED_operate
/				 -PD3	PB2-  PWM_1
/				 -PD4	PB1-  enable
/		      PWM_2      -PD5	PB0-
/			GND	 -GND	PD6-  encoder 
/						  ----------
/
/ ******************************************************************************/

/* libraries */
#include <avr/io.h>
#include <util/delay.h>
#include <math.h>

/* clock speed*/
#define F_CPU 1000000

/* define pins */
#define led_v1 PB7
#define led_v2 PB6 
#define led_v3 PB5
#define led_v4 PB4
#define led_op PB3                                                                                                                   
#define in_vselect PD0
#define in_enable PD1
#define sn_enable PB1
#define pwm1 PB2
#define pwm2 PD5
#define encoder PD6


/* variables */
int buttoncount  = 1;      /* v1        */
int speedsample  = 0x08;   /* 1 mm/s    */ 
int desiredus = 20;   /* #pulses   */
int countus = 0;             /* #pulses   */
boolean enabled  = false;  /* measuring */
int buttonread_vselect;
int buttonread_enable;


/* main function */
int main(){
  
  /* ---------------------------- Initializing --------------------------- */
  /* specify in and outputs 1:output, 0:input */
  DDRB = 0b11111111;
  DDRD = 0b00000000;
  
  /* blink leds when turned on */
  blinkleds();
  
  /* turn on led v1 */
  PORTB &= ~(1 << led_v1);
  /* --------------------------------------------------------------------- */
  
  
  /* --------------------------- Select Speed ---------------------------- */ 
  while(!enabled){
        
    buttonread_vselect = digitalRead(in_vselect); /* Reads vselect */
    buttonread_enable  = digitalRead(in_enable);   /* Reads enable */
    
    if (buttonread_vselect == LOW){
      
      _delay_ms(250); /* Avoid multiple inputs */
      
      vselect();
    } 
    else if (buttonread_enable == LOW){
      
      _delay_ms(250); /* Avoid multiple inputs */
      
      PORTB &= ~(1 << led_op);
      enabled = true;       
    }    
  }
  /* ---------------------------------------------------------------------- */
  
  /* --------------------------- Rotate motor ----------------------------- */
   _delay_ms(2000); /* Wait two seconds before start */
    
  TCCR0A = (1 << COM0A1) | (1 << WGM00);
  TCCR0B = (1 << CS00);   // clock source = CLK/1

  
  switch (buttoncount){
        
    case 1: 
        PORTB ^= sn_enable; 
        PORTB ^= pwm1;
      while(true){
        OCR0A = 150;
      }
      
    case 2: 
      rotate();
      break  ;
    case 3: 
      rotate();  
      break  ;
    case 0: //fastest (= button 4) 
      rotate();  
      break;  
  }  
  
}


  
void blinkleds(){
    
  for (int i = 1; i<=5; i++){
   
    PORTB = 0b00001000;
    _delay_ms(200);
    PORTB = 0b11111000;
    _delay_ms(200);
  }
}
  
void vselect(){
   
   buttoncount++;
   
   switch (buttoncount){
     case 1:
       speedsample = 0x08;
       desiredus = 10;
       PORTB = 0b01111000;
       break;
     case 2:
       speedsample = 0x3A;
       desiredus = 26;
       PORTB = 0b10111000;
       break;
     case 3:
       speedsample = 0x6F;
       desiredus = 111;
       PORTB = 0b11011000;
       break;
     case 4:
       speedsample = 0xFF;
       desiredus = 240;
       PORTB = 0b11101000;
       buttoncount = 0; 
       break;
   }  
}
    
void rotate(){
  
  OCR0A = 0;
  PORTB ^= sn_enable; 
  PORTB ^= pwm1;
  
  while(true){
    
    OCR0A = speedsample;
    
    for (int i = 1; i<255; i++){
      if (digitalRead(encoder)==HIGH){
        countus ++;
      }
    }      
    
    
    if (desiredus <= countus){
      speedsample = speedsample - 1;     
    }
    else if (desiredus >= countus){  
      speedsample = speedsample + 1;
    }
    countus = 0;
    
  }
}
  switch (buttoncount){
        
    case 1: 
        PORTB ^= sn_enable; 
        PORTB ^= pwm1;
      while(true){
        OCR0A = 150;
      }
      
    case 2:

You don't have a break at the end of this case, which will cause problems, and won'twhile(true)always be true ?

Is there some reason why you're hitting the hardware directly instead of using the Arduino Wiring runtime framework? You don't seem to be using the Arduino runtime at all. There's nothing wrong with doing that if you want, but in that case it might be more appropriate to ask for help on an AVR forum.