AtTiny85 in CTC Mode Oscillate +/- 500 Hz

Thread Starter

gioben

Joined Jul 11, 2016
6
So I have been struggling to make this chip output a 2.5 khz signal.

I think I have managed to output this, but now I need to oscillate up and down +/- 500 Hz.

So I will need the square signal to go from 2000 to 3000 kHz.

This is the code I have done to output the signal.
C:
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 (CS01); //With this setting prescaler to 8
//TCCR0B |= bit (CS00);// | bit (CS01);  // Prescaler of 1024
TCCR0B |= bit (CS00) | bit (CS01);  // Prescaler of 64
TCCR0A |= bit (WGM01);    //  Start Timer 0 in CTC mode
OCR0A = 50.05;   // CTC Compare value (count up to 128)
}

void loop()
{

}
Mod edit: added code tags

I have used a 64 prescaler, with a 50.05 value of comparison, this after trying several combinations I think this works the best. I need to keep the 50 % duty cycle I am on right now.

Do you have any ideas, suggestions ??

Thanks in advance for your time.

----------------------------------------------------------------------------------------------------------------

EDIT

I was able to output a constant 2.5 kHz, yes. But now my issue is to make it oscillate the 500 Hz. I tried to do that by changing the comparison value from 63.05 to 41.5 which are the values of 2.0 and 3.0 kHz respectively. But it doesn't do that, the duty cycle changes and my actual range of values are from 1.2 to 9 kHz.

What options do I have ?
 
Last edited by a moderator:

JohnInTX

Joined Jun 26, 2012
4,787
@gioben
Welcome to AAC!
Please do not post your question in more than one thread. Doing so causes confusion and dilutes members' efforts to help you.
This question seems best suited for this forum. I have deleted the other threads.
 

dannyf

Joined Sep 13, 2015
2,197
This is what I would try, in the loop():

Code:
  //output frequency from low to high
  for (TOP = TOP_HIGH; TOP > TOP_LOW; TOP-=TOP_STEP) delay_ms(DLY_STEP); //waste some time
  //output frequency from high to low
  for (TOP = TOP_LOW; TOP < TOP_HIGH; TOP+=TOP_STEP) delay_ms(DLY_STEP); //waste some time
It will go from low to high, and then high to low, so on and so forth.
 

Thread Starter

gioben

Joined Jul 11, 2016
6
You want to sweep the output frequency?

Just change the top of the timer periodically.

Using pwm is better. And use center aligned pwm to avoid glitches.
How would I use PWM for that ? I am using the Tiny in CTC Mode. I tried using Fast Mode, but my duty cycle changed a lot. How will you thinhk the best way of doing this would be?
 

Thread Starter

gioben

Joined Jul 11, 2016
6
  • //output frequency from low to high
  • for (TOP = TOP_HIGH; TOP > TOP_LOW; TOP-=TOP_STEP) delay_ms(DLY_STEP); //waste some time
  • //output frequency from high to low
  • for (TOP = TOP_LOW; TOP < TOP_HIGH; TOP+=TOP_STEP) delay_ms(DLY_STEP); //waste some time

So, TOP will me the address of my top value, TOP high and low respectively are the values of my actual desired max and min ? DLY_STEP is the delay in millisecond in between the toggling ?? So is that my period?
 

Thread Starter

gioben

Joined Jul 11, 2016
6
Hi I have also tried this code without being able to make it work, this is using PWM.

Code:
#include <TinySoftPwm.h>
//#include <DigiUSB.h>
#define HW_PWM_PIN               0 /* Used to check HW PWM with analogWrite() */
#define SW_PWM_BUILT_IN_LED_PIN  1 /* Digispark Model A (Rev2) built-in LED pin number (Change it to 2 for Model B) */
//#define TIME_TEST_PIN            5 /* Used to check with oscilloscope micros(), millis() are still OK */
void setup()
{
   TinySoftPwm_begin(5.5556, 0); /* 128 x TinySoftPwm_process() calls before overlap (Frequency tuning), 0 = PWM init for all declared pins */
//   pinMode(TIME_TEST_PIN, OUTPUT);
//   DigiUSB.begin();
}
void loop()
{
static uint32_t PwmStartUs=micros();
static uint32_t PwmStartMs=millis();
static uint8_t  Pwm=0;
static int8_t   Dir=1;
static boolean  State=LOW;
//static uint32_t BlinkStartMs=millis();
  /***********************************************************/
  /* Call TinySoftPwm_process() with a period of 60 us       */
  /* The PWM frequency = 128 x 60 # 7.7 ms -> F # 130Hz      */
  /* 128 is the first argument passed to TinySoftPwm_begin() */
  /***********************************************************/
  if((micros() - PwmStartUs) >= 60)
  {
    /* We arrive here every 60 microseconds */
    PwmStartUs=micros();
    TinySoftPwm_process(); /* This function shall be called periodically (like here, based on micros(), or in a timer ISR) */
  }
/*************************************************************/
  /* Increment/decrement PWM on LED Pin with a period of 10 ms */
  /*************************************************************/
  if((millis()-PwmStartMs) >= 1)
  {
    /* We arrived here every 10 milliseconds */
    PwmStartMs=millis();
    Pwm+=Dir; /* increment or decrement PWM depending of sign of Dir */
    TinySoftPwm_analogWrite(SW_PWM_BUILT_IN_LED_PIN, Pwm); /* Software PWM: Update built-in LED for Digispark */
    analogWrite(HW_PWM_PIN, Pwm); /* Copy Pwm duty cycle to Hardware PWM */
    if(Pwm==200) Dir=-1; /* if PWM reaches the maximum: change direction */
    if(Pwm==15)   Dir=+1; /* if PWM reaches the minimum: change direction */
  }
}
If you have any input, that will be amazing. Thanks everyone
 

Thread Starter

gioben

Joined Jul 11, 2016
6
Just in case it helps anyone in the future, here is what I needed.

Code:
byte divisor = 150;
int delay_value = 10;

void setup()
{
pinMode(1, OUTPUT);
TCCR1 = 0b10010101;
OCR1C = divisor;         // set the OCR

}

void loop()
{

for (int i=0; i < 100; i++){
  divisor++;
  OCR1C = divisor;
  delay(delay_value);
}

for (int j=0; j < 100; j++){
  divisor--;
  OCR1C = divisor;
  delay(delay_value);
}

}
 

dannyf

Joined Sep 13, 2015
2,197
No need to be that complicated.

Code:
#define TOP            OCR0A
#define TOP_LOW        (F_CPU / 64 / F_TOP / 2) //64:1 prescaler, CTC mode
#define TOP_HIGH    (F_CPU / 64 / F_BTM / 2)  //64:1 prescaler, CTC mode
#define TOP_STEP    10
#define STEP_DLY    100            //in ms
#define F_TOP        2500        //high frequency, in Hz
#define F_BTM        1500        //low frequency, in Hz

void loop(void) {
    //frequency sweep, from F_BTM to F_TOP and then F_BTM
    for (TOP=TOP_HIGH; TOP>TOP_LOW; TOP--) _delay_ms(STEP_DLY);
    for (TOP=TOP_LOW; TOP<TOP_HIGH; TOP++) _delay_ms(STEP_DLY);
}
 
Top