setting up timer 1 for 16khz motor controller

I know how to set the prescaler but Im having trouble with the rest of it. The signal from Pin 9 goes to a mosfer driver. I am using the analogWright and a pot to adjust the pulse width. The freq can be between 13 and 16 khz, the exact freq is not that important. Any input would be great so I can stop. Using timer 0 and get higher than 8 khz.

So I got 16 khz on pin 10, but I cant figure out how to set the duty to zero when the throttle is zero.

The Code that I'm using is :

Timer:

TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1);
TCCR1B = _BV (WGM12) | _BV (WGM13) | _BV (CS10);
OCR1A = 1000;

Pot:

duty = (analogRead(0));
duty = map(p, 0, 1023, 0, 999);

pwm:

OCR1B = duty;

Just turn the timer off for a duty cycle of zero.

so

something like this?

if (throttle < 0) TCCR1A =0;
else TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1);

OOPS

I mean

if (throttle <= 0) TCCR1A =0;
else TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1);

If I set OCR1A = -1 , what happens?
Will this work also, as the counter starts at 0, so it will never reach the top?
or what other ways can I stop timer1?

This will stop it:

TCCR1B = 0;  // no clock source

Thanks for your help, I really appreciate it!

I not sure I understand the difference between stopping TCCR1A vs TCCR1B.
If I stop TCC1B then to restart it I must reset all the modes and prescalers?

Is this code what you mean?

If (throttle <= 0) TCCR1B = 0;
else  {
TCCR1B = _BV (WGM12) | _BV (WGM13) | _BV (CS10); 
OCR1B = throttle; 
}

Also what does happen when you set OCR1B = -1?

Look at table 15-5 in the datasheet. The way to stop the clock is to set the prescaler bits to 000. And yes, to restart it you have to put the prescaler back.

Also what does happen when you set OCR1B = -1?

It's an unsigned field so you are really asking what happens if you set it to 0xFFFF (65535). It would count up to 65536 I imagine.

Ok , ive looked at 15.5 and it makes more sense.
When I restart the clock do i need to set the mode to or can i just set the prescaler?

Like this:

// stopping timer
TCCR1B = 0;

//starting timer
TCCR1B = _BV (CS10);

Also i have it set up for fast pwm, but I really would like phase correct, but I cant seem to get that mode to work.
Could you possibly show how I can change the mode to phase correct?

azhillman:
Also i have it set up for fast pwm, but I really would like phase correct, but I cant seem to get that mode to work.
Could you possibly show how I can change the mode to phase correct?

Perhaps if you showed what you tried.

  TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (WGM13) | _BV (COM1B1) | _BV (CS10); // set up timer1
  OCR1A = 500; // set F_clock / 500*2 = 16khz?
  OCR1B = 1023; // sets pwm = 0

I really am struggling with this timer stuff. So if I've got this right, I've set it to phase correct mode, with no prescaler or a prescale of 1.

When i run this with a led in the output pin and adjust OCR1B it works, but I can not set the rollover point for the frequency with OCR1A, probably because I do not have this set correctly or even calling that register. How do I remedy this situation? Thanks!

For a start, WGM13 is in TCCR1B, not TCCR1A.

, I've set it to phase correct mode, with no prescaler or a prescale of 1.

The prescaler is in TCCR1B, which you haven't shown.

Also CS10 is in TCCR1B.

Ok.

I was thinking about what I had posted on the way to school today, and I kept thinking that needed to include TCCR1B. This just shows how little I understand the timers.

If I get what your saying then I need to change the code to this:

  TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1); sets to phase correct
  TCCR1B = _BV (WGM13) | _BV (CS10); // sets it phase correct whith prescale of 1
  OCR1A = 500; // set F_clock / 500*2 = 16khz?   500 up then 500 down right?
  OCR1B = 1000; // sets pwm = 0

Correct?

I noticed that there was some errors in what I posted, but I fixed them and ran a test using an LED on the pin that was PWM.
I set the prescale to 256 and OCR1A to 31250 which should give me a 1 Hz pulse, I also set OCR1B to 500 or 100% duty. Using a stop watch I timed about 30 seconds and I had 30 pulses.
Seems like it is right! :smiley:

Hear is the code:

  //  Sets Timer1 to Phase Correct
  //  F_CLOCK / ( Prescaler * ORCR1A * 2 ) = Freq in Hz
  //  16000000 / (1 * 500 * 2 ) = 16000 Hz
  TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1);  // Phase Correct
  TCCR1B = _BV (WGM13) | _BV (CS12);                  // Phase Correct / Prescale 1
  OCR1A = 500;                                        // Sets Top to 500 
  OCR1B = 0;                                          // Sets Pwm = 0

This sketch appears to work, and is based almost entirely on one of my sketches on my timers page:

const byte LED = 10;  // Timer 1 "B" output: OC1B
const byte POTENTIOMETER = A0;
// Clock frequency divided by 15 KHz frequency desired
const long timer1_OCR1A_Setting = F_CPU / 15000L;
void setup() 
 {
  pinMode (LED, OUTPUT);
  // Fast PWM top at OCR1A
  TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1); // fast PWM, clear OC1B on compare
  TCCR1B = _BV (WGM12) | _BV (WGM13) | _BV (CS10);   // fast PWM, no prescaler
  OCR1A =  timer1_OCR1A_Setting - 1;  // zero relative 
  }  // end of setup

void loop() 
  { 
  // alter Timer 1 duty cycle in accordance with pot reading
  OCR1B = (((long) (analogRead (POTENTIOMETER) + 1) * timer1_OCR1A_Setting) / 1024L) - 1;
  }

This sketch appears to work, and is based almost entirely on one of my sketches on my timers page:

The Sketch that I posted or the one that you posted?

Because your 38Khz sketch is what I pretty much copied to get the fast PWM at 16 khz.
The second is also based on what I learned, your 38 khz, and what you showed me.

azhillman:
The Sketch that I posted or the one that you posted?

You haven't posted a sketch. If you want me to test it post something that compiles. I don't want to seem unhelpful, but a few lines hide what might be important details. For example:

  OCR1A = 500;                                        // Sets Top to 500 
  OCR1B = 0;                                          // Sets Pwm = 0

The top looks low, and the duty cycle looks low too. With a prescaler of 1, and a clock speed of 16 MHz, the OCR1A would need to be around 1000 to get 16 kHz output.

  TCCR1B = _BV (WGM13) | _BV (CS12);                  // Phase Correct / Prescale 1

That's a prescaler of 256, your output is way too slow. I measured 62.5 Hz.

This is my test sketch.

int d = 0;            // pwm value

void setup()

{
  //  Sets Timer1 to Phase Correct
  //  F_CLOCK / ( Prescaler * ORCR1A * 2 ) = Freq in Hz
  //  16000000 / (1 * 512 * 2 ) = 15625 Hz
  TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1);  // Phase Correct
  TCCR1B = _BV (WGM13) | _BV (CS12);                  // Phase Correct / Prescale 1
  OCR1A = 512;                                        // Sets Top to 512 
  OCR1B = 0;                                          // Sets Pwm = 0			

  	pinMode(10, OUTPUT);           
        pinMode(0, INPUT);                 
       
}  

void loop()

{
  d = (analogRead(0)); 
  d = map(d, 0, 1023, 0, 512);
  OCR1B = d;

}