Help with Variable Fast PWM with Attiny84

This page has given me a little inside knowledge about how to generate a square wave faster than a few kHz: https://andreasrohner.at/posts/Electronics/How-to-set-the-PWM-frequency-for-the-Attiny84/

I need help understanding how I can change the TOP value of this fast PWM and set up a range of 25kHz - 65kHz that can be swept with a potentiometer (set up a voltage divider and an analogRead).

This code is generating a 250kHz square wave on my scope but I am confused on how to change it to my parameters.

void setup() {
    pinMode(6, OUTPUT);

    /*
     * WGM10, WGM12: Fast PWM, 8-bit TOP=255
     * CS10: No prescaler
     * COM1A1: Pin 6 to LOW on match with OCR1A and to HIGH on TOP
     */
    TCCR1A = _BV(COM1A1) | _BV(WGM10);
    TCCR1B = _BV(CS10) | _BV(WGM12);
    /*
     * 50% duty cycle
     * 32 kHz with 8MHz CPU clock
     */
    OCR1A = 127;
}

void loop() {
}

What I've come to understand is that I cannot change the frequency as easily as I thought, but what if I use something like a modulo to divide the frequency and have the potentiometer sweep through the modulo division number, ultimately changing the frequency.

See table 12-5 in the datasheet.

You currently have it set for 8 bit fast PWM (WGM13~10 = 0101), where TOP is 0xFF.

If you want to change TOP, you need to use a different WGM - you would typically want to use WGM 14 (WGM13~10 = 1110) which uses the value in ICR1 as TOP.

To get a 50% duty cycle squarewave you also have to change OCR1A to half of what you set ICR1 to.

Adjusting it with a pot is a matter of reading the value from the analog pin and mapping that to the values of TOP to generate that frequency range.

Your analogRead() on the potential divider gives a value 0 to 1023 (assuming you wire it between vcc and ground.. ICR1 is a 16 bit register, so you have to multiply the value obtained from the voltage divider by 64 (obtained from 65536/1024) and to get the value of OCR1A, multiply it by 32 for a 50% duty cycle.

You two are a beam of light (DrAzzy and 6v6gt).

What is ICR1? and what does TOP mean?

Could you help fill in the blanks? How could I translate this code to using the Fast PWM terminology? I have never worked with fast PWM before and it seems like an advanced topic for my arduino knowledge. This was my original code that ran fine on the Uno, but on the tiny84 tone() doesnt seem to run.

const int pot = 0;
const int clk = 6;
//Variable will change
int potVal = 0;             // pot pin value
int lastPotVal = 0;         // previous state of pot pin

void setup() {
  pinMode(pot, INPUT);
  pinMode(clk, OUTPUT);

}
void loop() {

   //first read in warp pot value
  potVal = analogRead(pot);

  //change the value if the pot moved
  if (potVal != lastPotVal){
    
        // read sensor value from warp read pin
         int potVal = analogRead(pot);
  
       // map sensor value to range for pwm freq
         int potValmapped = map(potVal, 1, 1023, 25000, 80000);

       // save current value for next time through the loop
          lastPotVal = potVal; 

       // output that value to clk pin for FV-1

         tone(clk, potValmapped);
  }
  // Delay a little bit to avoid bouncing
    delay(5);
  // save the current state as the last state,
  // for next time through the loop
  lastPotVal = potVal;
}

try adding this to setup:

        // wgm 14, prescaler 1, output pin OC1A
    TCCR1A = _BV(COM1A1) | _BV(WGM11);
    TCCR1B = _BV(CS10) | _BV(WGM12)  | _BV(WGM13);

and this to the loop ater you have determined that you have a new value from the potentiometer.

       ICR1 = potValmapped ;        // sets frequency (TOP limit, the number of prescaled clock cycles 
                                    //   before the timer counter is reset and OC1A is set
       OCR1A = potValmapped / 2  ;  // 50% duty cycle. The point at which OC1A is cleared.

You'll have to play with your mapping rule to get the desired frequency range. ICR1 is (in Wave generation mode 14) a TOP, that is when the timer counter get to this limit, it resets thus governing the frequency. The prescaler governs the number of machine cycles which must occur before the timer counter gets incremented.

You appear to have defined potVal twice as an int , once as a global and once in the loop().

It worked!!!! Messed around with the mapping but ultimately got the results I needed.

While putting the chip in my project I accidentally bricked my tiny84 (doh!). In the process of resetting the fuse bits....