HELP SETTING UP ATtiny85 TIMER 0 for 150khz & 150hz squarewave on 2 ics

I’m struggling with the ATtiny85 datasheet and was able to get a waveform but I seem to be
setting it up as PWM and I actually just want a squarewave.
This is what I have so far and I’m sure it’s all wrong but it’s a start.

void setup()
{
  DDRB |= (1<<PB0); //Set pin PB0 as output
 TCCR0A |=(1<<CTC1); //Start timer 1 in CTC mode Table 12.3.1
 TCCR0A|=(1<<COM1A0); //Timer1 in toggle mode Table 12.4
 TCNT0  |= (1 << CS00) |  (1 << CS02);  // Prescaler @ 1024 Table 12.5
 TCCR0A |= ((1 << CS13) |  (1 << CS11)| (1 << CS10)); // Prescaler @ 1024 Table 12.5
  OCR0A=5500; //CTC Compare value
 }
 
 void loop()
 {
 
 
 }

This gives me about 1560 Hz (using an old oscope).

I want to use two ATtiny85s, one generating 150khz and the other 150 hz to be used to generate the two
frequencies needed for the Electro-Luminescent Backlight Power Supply circuit in attached schematic.
I breadboarded it and had no trouble using a Pro Mini with the following code (ino file attached)

  // backlight.c
// for NerdKits with ATmega168
// mrobbins@mit.edu
#define F_CPU 16000000
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
const int PB1=9; //OC1A  Pin-9
const int PB2=10; //OC1B Pin-10
const int PB3=11; //OC2A Pin-11


// PIN DEFINITIONS:
//
// D9 -- OC1A -- backlight high-speed switchy thing (nFET gate)
//		used to generate the high voltage supply
// D11 -- OC2A -- backlight low-speed switchy thing (nFET gate)
//		used to pulse the AC to the electroluminescent

 
 
void setup()
{
       pinMode(PB1,OUTPUT);
       pinMode(PB2,OUTPUT);
       pinMode(PB3,OUTPUT);
 }      
       
void loop()
{
  // D9,D10, D11 as output
  DDRB |= (1<<PB1) | (1<<PB2) | (1<<PB3);
  
  // Timer1: Toggle CTC, 10-bit, non-inverting, clocked from CLK/1
  TCCR1A = (1<<COM1A0);
  TCCR1B = (1<<WGM12) | (1<<CS10);
  OCR1A = 164; // =>150 kHz
  
  // Timer2: Toggle CTC, clocked from CLK/1024
  TCCR2A = (1<<COM2A0) | (1<<WGM21);
  TCCR2B = (1<<CS22) | (1<<CS21) | (1<<CS20);
  OCR2A = 12; // 175 Hz
  
}

I got the code from Nerdkits.com page here:
NerdKits - LCD Backlight - Electroluminescent Inverter

I breadboarded it and got 212Vac , about 100V short of the claimed 300V. I think I can increase the voltage
by changing the inductor value but I am not sure what value to use.
Since I read that the Timer 1 of the ATtiny85 is used for millis , micro etc. on this post:
http://forum.arduino.cc/index.php?topic=118586.0
I thought it better just to use two ics, both using Timer 0, which was recommend to avoid messing
with the one used for millis.
I have tried reading the datasheet but without much success. I was able to figure out the register names
but I don’t think I’m setting them correctly.
When tuning the Pro-Mini program I used a potentiometer to set the frequency using an analog input:

Declarations:

int analogPin = A3;   // potentiometer connected to analog pin 3
int freq=0;

mapped to the desired OCR1A value range and then using the scope I obtained the corresponding
frequency range generated by that range of OCRIA values and remapped those values to that frequency
range and then used serial.print commands to print the frequency like this:

 int  freqAdj = analogRead(analogPin);   // read the input pin
        freqAdj = map(freqAdj, 0, 1023, 144, 184);
 
  int freq  = map(freqAdj, 144, 186, 142 ,166);
  OCR1A=freqAdj;
  Serial.print("freq= ");
  Serial.println(freq);

which worked.
I was planning to use the same method to adjust the ATtiny85 frequency.

Can anyone help me ?

EL_Backlight_PS_H_150_kHz_L_175_Hz.ino (1.05 KB)

raschemmel:
I’m struggling with the ATtiny85 datasheet and was able to get a waveform but I seem to be
setting it up as PWM and I actually just want a squarewave.

What do you mean? PWM is a square wave. If you mean a “square” wave (as opposed to rectangular one) just make the duty cycle 50%.

Sorry, yes, that's what I meant. What I meant to say is I don't know how to set up for 50%
or how to set it up for the two frequencies that I need. That's what I need help with.
I use the term "square wave" to mean any wave form with a 50% duty cycle. Otherwise I call it a PWM,
which is probably not correct nomenclature. Thank you for correcting me.

  OCR0A=5500; //CTC Compare value

Timer 0 is an 8 bit timer so it is not going to count to 5500. That would be more like 124.

Not that I see where 1560 Hz comes from that.

CTC with toggling will give you a square wave, yes.

Not that I see where 1560 Hz comes from that.

That’s the problem. I am trying to get a 150khz 50% duty cycle waveform.
I am able to do it using a 16Mhz Pro-Mini with the following code in
void loop()

  void loop()
{
  // D9,D10, D11 as output
  DDRB |= (1<<PB1) | (1<<PB2)| (1<<PB3) ;
  
  // Timer1: Toggle CTC, 10-bit, non-inverting, clocked from CLK/1
  TCCR1A = (1<<COM1A0);
  TCCR1B = (1<<WGM12) | (1<<CS10);
  OCR1A = 164; // =>150 kHz
  
  // Timer2: Toggle CTC, clocked from CLK/1024
  TCCR2A = (1<<COM2A0) | (1<<WGM21);
  TCCR2B = (1<<CS22) | (1<<CS21) | (1<<CS20);
  OCR2A = 12; // 175 Hz
}

but I discovered that if I put my ATtiny85 TIMER 0 code in void loop() it will not run.
It will only run if the code is in void Setup().
This is the code I have for the ATtiny85 that is generating the 1560hz waveform
It is only 50% if I use an OCR0A value of 127 (255/2).
I am trying to find out if it is even possible to generate a 150khz waveform (50% duty cycle)
with an ATtiny85, even if I used an external clock source. I have a 16Mhz ATmega328 with
OPTIBOOT Bootloader breadboarded right next to the ATtiny85 that has a 16Mhz XTAL
on it. I have the ATtiny85-20PU using a board file for 16Mhz Internal PLL. Is it possible
to get a 50% duty cycle waveform from an ATtiny85 or am I wasting my time ?

forgot the ATtiny85 code.
Here it is:

void setup()
{
  pinMode(input3, INPUT);
   pinMode(output0, OUTPUT);
   pinMode(output0, OUTPUT);
  DDRB |= (1<<PB0); //Set pin PB0 as output
  TCNT0=0;
 TCCR0A |=(1<<CTC1); //Start timer 1 in CTC mode Table 12.3.1
 TCCR0A |=(1<<COM0A0); //Timer1 in toggle mode Table 12.4
 
 TCNT0  |= (1 << CS00) |  (1 << WGM01);  // Prescaler @ 1024 Table 12.5

 OCR0A=127; //CTC Compare value
 
 
 
 }

http://snippets-r-us.com/

sketch_dec20a.ino: In function 'void setup()':
sketch_dec20a:3: error: 'input3' was not declared in this scope
sketch_dec20a:4: error: 'output0' was not declared in this scope

I’m sorry Nick, I didn’t copy the entire code because I didn’t the rest was relevant. My bad.
here it is:

#include <Arduino.h>
 #include <WProgram.h>
#define F_CPU 16000000
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>


int input3=3;
int output0=0;
int output1=1;
int freq=0;
int  freqAdj=0;
#include <Arduino.h>
 #include <WProgram.h>
void setup()
{
  pinMode(input3, INPUT);
   pinMode(output0, OUTPUT);
   pinMode(output0, OUTPUT);
  DDRB |= (1<<PB0); //Set pin PB0 as output
  TCNT0=0;
 TCCR0A |=(1<<CTC1); //Start timer 1 in CTC mode Table 12.3.1
 TCCR0A |=(1<<COM0A0); //Timer1 in toggle mode Table 12.4
  TCNT0  |= (1 << CS00) |  (1 << WGM01);  // Prescaler @ 1024 Table 12.5
 OCR0A=127; //CTC Compare value
 }
  void loop()
 {
  //int  freqAdj = analogRead(analogPin);   // read the input pin
  //  freqAdj = map(freqAdj, 0, 1023, 144, 184);
//  int freq  = map(freqAdj, 144, 184, 166,142);
 
   // OCR1A=freqAdj;
// 
  }

Nick,
I know I should have copied the entire file but since it was compiling and
I was able to get the 1560 hz I thought that the problem was in the timer
related code (the part I posted, as opposed to declarations, since it was compiling previously)

#include <Arduino.h>
#include <WProgram.h>
#define F_CPU 16000000
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <inttypes.h>
...
#include <Arduino.h>
#include <WProgram.h>

That’s a lot of includes, considering it compiles without any of them. Are you really running it at 16 MHz?

  pinMode(output0, OUTPUT);
  pinMode(output0, OUTPUT);

?

Once will do. And can't you find better names than output0?

  TCNT0  |= (1 << CS00) |  (1 << WGM01);  // Prescaler @ 1024 Table 12.5

No, that is the timer counter. Not something you configure like that. You have to read the datasheet and get all these setting right. Don’t thrash around.

 TCCR0A |=(1<<CTC1); //Start timer 1 in CTC mode Table 12.3.1

CTC1 is part of TCCR1 not TCCR0A.

As I work through your code I am finding that practically every line is setting something completely contrary to the datasheet. You don’t need to post asking for advice here. You need to do what I am doing and look at each register and set the documented bits appropriately.

After correcting all that I get this:

void setup()
{
  DDRB |= bit (PB0);     //  Set pin PB0 as output
  
  // stop Timer 0
  TCCR0A = 0;
  TCCR0B = 0;
  TCNT0 = 0;
  
  // set up Timer 0
  TCCR0A |= bit (COM0A0);   //  Toggle OC0A/OC0B on Compare Match
  TCCR0B |= bit (CS00) | bit (CS02);  // Prescaler of 1024
  TCCR0A |= bit (WGM01);    //  Start Timer 0 in CTC mode
  OCR0A = 127;   // CTC Compare value (count up to 128)
}

void loop()
{
// nothing yet 
}

I measured 30.8 Hz which is correct for an 8 MHz clock.

8000000 / 1024 / 128 / 2  = 30.5

1024 is the prescaler.
128 is what we are counting to.
Divide by 2 because it takes two toggles to make one cycle (one on, one off).

Now to fiddle with the figures to get 150 kHz. :slight_smile:

This output 150 kHz on my 8 MHz Attiny85:

void setup()
{
  DDRB |= bit (PB0);     //  Set pin PB0 as output
  
  // stop Timer 0
  TCCR0A = 0;
  TCCR0B = 0;
  TCNT0 = 0;
  
  // set up Timer 0
  TCCR0A |= bit (COM0A0);   // Toggle OC0A/OC0B on Compare Match
  TCCR0B |= bit (CS00);     // No prescaler
  TCCR0A |= bit (WGM01);    // Start Timer 0 in CTC mode
  OCR0A = 26;   // CTC Compare value (count up to 27)
}

void loop()
{
// nothing yet 
}

Calculation:

8000000 / 27 / 2 = 148148

Well, that's pretty close.

Thank you so much. I really mucked it up.
I REALLY appreciate your patience in straightening out my messed up code.
I am reading the datasheet and I made notations in your code referencing where it came from (for the sake of
others of course)

void setup()
{
  DDRB |= bit (PB0);     //  Set pin PB0 as output
  
  // stop Timer 0
  TCCR0A = 0;
  TCCR0B = 0;
  TCNT0 = 0;
  
  // set up Timer 0
  TCCR0A |= bit (COM0A0);   // Toggle OC0A/OC0B on Compare Match ([b]Table 11-2[/b])
                            // ([b]Table 11-2[/b]. Compare Output Mode, non-PWM Mode ,ie: 50% duty cycle)
  TCCR0B |= bit (CS00);     // No prescaler ([b]Table 11-6:[/b] )
  TCCR0A |= bit (WGM01);    // Start Timer 0 in CTC mode ([b]Table 11-5[/b])
  [b]OCR0A[/b] = [b]52[/b];   // [b]CTC Compare value[/b] (count up to 53) // [b]16000000 / 53 / 2[/b] =[b] 150943[/b]
}

void loop()
{

Also, I have a question about the frequency.
Since I am currently using 16000000 (Internal PLL) , I recalculated your setting to above value for 16Mhz which results
in 150943 but while reading the datasheet I came across the following on page 72:

For generating a waveform output in CTC mode, the OC0A output can be set to toggle its logical level on each
Compare Match by setting the Compare Output mode bits to toggle mode (COM0A[1:0] = 1). The OC0A value will
not be visible on the port pin unless the data direction for the pin is set to output. The waveform generated will have
a maximum frequency of fOC0 = fclk_I/O/2 when OCR0A is set to zero (0x00). The waveform frequency is defined by
the following equation:
fclk_I/O
FocnX= -------------------------
2N(1+ OCRnX)

[The N variable represents the prescale factor (1, 8, 64, 256, or 1024).]

16000000 16000000 16000000
Using this formula I obtained FocnX => -------------------- = ------------------= ------------------ =150943.39
21(1+52) (2+104) 106

which appears to be where you got your calculation. Correct ?
Note that by using a 16Mhz clock I am able to get within almost 1khz of the target freq of 150khz , whereas
with 8Mhz the count of 27 (your original) yields 1843 hz below target and the value 26 is 3.846khz above 150khz.

Am I correct about this ?
Also, the part about the waveform not being visible on the port pin unless it is set to output ,
That's why the following is necessary , correct ?

DDRB |= bit (PB0);     //  Set pin PB0 as output

Thanks again , Nick , you really pulled me out of a hole !
Robert

Yes, substituting your numbers gives what you said:

 16000000 / 53 / 2  = 150943.4

(Where OCR0A is 52).

I agree the output pin needs to be output.

Thanks Nick !
Hopefully this post will help others in finding the relevant sections of the datasheet and
understanding how to setup the ATtiny85 TIMER 0 to generate 50% duty cycle waveforms.
Robert

Nick,
I got both ATtiny85s working at the two frequencies that I found to be optimum for the EL backlight PS
using my method of analogread of the pot setting and mapping it to the timer count value for both
chips. I don't know why but I didn't get the frequencies I expected from the calculation so I had to
adjust the values accordingly. The backlight power supply is generating between 165vac to 218vac
depending on which Mosfets I use. I have photos of the LCD with the backlight lit. Should I post it
as a project or is the forum reserved for people who are seeking help ?
Robert