Attiny85 generare tono continuo a 71,9 Hz

...torna indietro nel tempo!
Ah, no, quello era il film di stasera! :laughing:

No, legge 74 Hz sul frequenzimetro impostando 72 Hz.
Serve se possibile piu' precisione.. circa 0,25Hz
Grazie

Usi un quarzo per il clock?
L'oscillatore interno è un semplice RC!
Che frequenzimetro usi?

uso un app per telefono...con arduino nano leggo la frequenza corretta usando un altro sketch, ma sfortunatamente e' troppo grande per lo spazio dove devo inserirlo in un apparato
Vorrei fare quello che vedete qui, ma senza tutta la roba che ha messo , solo il 71,9hz continuo
Hp cppmprao la versione con programmazione usb in montaggio smd e ci sto giusto giusto..

"Tutta la roba"?...
Ci sono un regolatore a 5V, un LED RGB, un filtro per il PWM (sì, è in PWM con andamento sinusoidale) e un trimmer per regolare il livello... Perché non usi quel programma?

Comunque, come fa notare nel sito, se non usi un quarzo la frequenza va aggiustata.

perche' come dicevo sopra il pcb non entra nello spazio disponibile..
Ma non e' ritagliabile lo sketch per avere solo il tono che voglio ?

Come posso cambiare i settaggi per scender di frequenza?

Grazie

Devi aumentare i due 6954, che sono i microsecondi in un semiperiodo.

Sì: devi lasciare solo la tabella sinusoidale e l'interrupt.

Questo è il programma completo di quel sito:

/*
    25.11.2019 - memoria su ultimo tono selezionato
    miglioramenti sul setup dei tre toni

    Compilare con Arduino 1.6.4 verificando :
    millis() : enabled
    Timer1 clock : CPU
    Clock : 8 MHz (internal)
    EEPROM : retained
    LTO : disabled
    B.O.D. : disabled
*/

#include <EEPROM.h>

const int in_ptt = 3;       // pin nr.2
const int tone_output = 4;  // pin nr.3
const int led_ctcss1 = 0;   // pin nr.5
const int led_ctcss2 = 1;   // pin nr.6
const int led_ctcss3 = 2;   // pin nr.7

byte Cnt = 0;
unsigned int PreCounter = 0;
unsigned int GlobalCounter = 0;
boolean State;
boolean LastState;
byte Tone;
float Ctcss ;

/*
  float Ctcss1 = 862.00;
  float Ctcss2 = 1159.00;
  float Ctcss3 = 1331.00;

  float Ctcss1 = 871.00;
  float Ctcss2 = 1168.90;
  float Ctcss3 = 1341.70;
*/

float Ctcss1 = 879.25; // 82.5
float Ctcss2 = 1179.45; // 110.9
float Ctcss3 = 1355.35; // 127.3

/*
  float Ctcss1 = 887.50; // 82.5
  float Ctcss2 = 1190.00; // 110.9
  float Ctcss3 = 1369.00; // 127.3
*/

volatile unsigned int Incr;
const unsigned char sine[256] =
{
  131, 132, 135, 137, 140, 143, 146, 149, 152, 155, 157, 160, 163, 166, 168, 171,
  174, 176, 179, 181, 184, 186, 189, 191, 194, 196, 198, 200, 202, 205, 207, 209,
  211, 212, 214, 216, 218, 219, 221, 223, 224, 226, 227, 228, 229, 231, 232, 233,
  234, 234, 235, 236, 237, 237, 238, 238, 239, 239, 239, 239, 240, 240, 240, 239,
  239, 239, 239, 238, 238, 237, 237, 236, 236, 235, 234, 233, 232, 231, 230, 229,
  227, 226, 225, 223, 222, 220, 219, 217, 216, 214, 212, 210, 208, 206, 204, 202,
  200, 198, 196, 194, 192, 189, 187, 185, 182, 180, 177, 175, 173, 170, 167, 165,
  162, 160, 157, 154, 152, 149, 146, 144, 141, 138, 135, 133, 130, 127, 124, 122,
  119, 116, 113, 111, 108, 105, 103, 100, 97, 95, 92, 89, 87, 84, 82, 79,
  77, 74, 72, 69, 67, 64, 62, 60, 58, 55, 53, 51, 49, 47, 45, 43,
  41, 39, 37, 36, 34, 32, 31, 29, 28, 26, 25, 24, 22, 21, 20, 19,
  18, 17, 16, 15, 15, 14, 13, 13, 12, 12, 12, 11, 11, 11, 11, 11,
  11, 11, 11, 12, 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 19, 21,
  22, 23, 24, 26, 27, 29, 30, 32, 33, 35, 37, 39, 41, 43, 45, 47,
  49, 51, 53, 56, 58, 60, 63, 65, 68, 70, 73, 75, 78, 81, 83, 86,
  89, 92, 94, 97, 100, 103, 106, 108, 111, 114, 117, 120, 123, 126, 129, 130
};

void setup()
{
  pinMode(led_ctcss1, OUTPUT);
  pinMode(led_ctcss2, OUTPUT);
  pinMode(led_ctcss3, OUTPUT);
  pinMode(in_ptt, INPUT);
  digitalWrite(in_ptt,  HIGH);    // abilita resistenza interna di pull-up
  pinMode(tone_output, OUTPUT);   // Enable PWM output pin

  // Enable 64 MHz PLL and use as source for Timer1
  PLLCSR = 1<<PCKE | 1<<PLLE;
  // Set up Timer/Counter1 for PWM output
  TIMSK = 0;                     // Timer interrupts OFF
  TCCR1 = 1<<CS10;             // 1:1 prescale
  GTCCR = 1<<PWM1B | 2<<COM1B0; // PWM B, clear on match

  // Set up Timer/Counter0 for 20kHz interrupt to output samples.
  TCCR0A = 3<<WGM00;           // Fast PWM
  TCCR0B = 1<<WGM02 | 2<<CS00; // 1/8 prescale
  TIMSK  = 1<<OCIE0A;           // Enable compare match, disable overflow

//  byte of the EEPROM can only hold a
//  value from 0 to 255.

  digitalWrite(led_ctcss1, HIGH);   // spegni tutti i led
  digitalWrite(led_ctcss2, HIGH);   // spegni tutti i led
  digitalWrite(led_ctcss3, HIGH);   // spegni tutti i led

  Tone = (EEPROM.read(0)) ;
  if (Tone>2) Tone = 0; // imposta il 1^ tono

  // parametri per forzare sin da subito una impostazione del tono
  PreCounter = 0;
  GlobalCounter = 0;
  Cnt = 7;
  State = LOW;
  LastState = HIGH;

}
//#######################################################

void loop()
{
  PreCounter++;
  if(PreCounter>3000)
    {
    GlobalCounter++;
    State = digitalRead(in_ptt);
    PreCounter = 0;
    }
  if(GlobalCounter>75)
    {
    GlobalCounter = 0;
    Cnt = 0;
    }
  if(State!=LastState)
    {
    Cnt++;
    LastState = State;

    if(Cnt == 8)      //  hai contato 8 pressioni compulsive del PTT entro il tempo di reset del conta pressioni compulsive
      {
      Cnt = 0;                          // azzera sin da subito il contatore di compulsioni sul PTT
      digitalWrite(led_ctcss1, HIGH);   // spegni tutti i led
      digitalWrite(led_ctcss2, HIGH);   // spegni tutti i led
      digitalWrite(led_ctcss3, HIGH);   // spegni tutti i led
      switch(Tone)
        {
        case 0:  // 82,5 Hz
          {
          digitalWrite(led_ctcss1, LOW);
          Ctcss = Ctcss1;
          break;
          }
        case 1:
          {
          digitalWrite(led_ctcss2, LOW);
          Ctcss = Ctcss2;
          break;
          }
        case 2:
          {
          digitalWrite(led_ctcss3, LOW);
          Ctcss = Ctcss3;
          break;
          }
        }
      EEPROM.write(0, Tone);            // salva il valore corrente del tono nella EEPROM
      Incr = 20000*(Ctcss/65536.0); // imposta l'emissione del tono
      Tone = Tone+1;                  // predisponiti per il prossimo giro
      if(Tone>2) Tone = 0;           // predisponiti per il prossimo giro
      }
    }
}
//############################################################################

//--- genera ctcss in base a ctcss valido ricevuto
ISR(TIMER0_COMPA_vect)
{
  static unsigned int Acc;
  Acc += Incr;
  OCR1B = sine[Acc >> 8];
}

con 7200 sono a 72 hz..
Cominvcio le prove con sul dispositivo, poi mi aggiusto eventualmente..

Grazie mille a tutti !!!

Roberto

Prego
Ciao

Se vuoi fare queste belle cose, però, ti serve un buon frequenzimetro/periodimetro, possibimente con frequenzimetro a conteggio reciproco come il Racal-Dana 1991... Con un po' di pazienza, il 1991 potresti trovarlo su ebay a meno di 200€.
...oppure questo, nella versione senza i 5,8GHz a circa 80€:

...oppure un oscilloscopio! (che per iniziare è la scelta migliore), come il classico Rigol DS1054Z, che si espande a 100MHz a costo zero e trovi attualmente intorno ai 400€.

ho un frequnzimetro cinese 6 cifre da 100khz a 50 mhz e un oscilloscopio hp crt fino a 100mhz.
Una domanda : nel tuo scketch come ottieni dalla frequenza il valore da inserire ,cioe' il semperiodo ?
A me per 71,9 Hz risulta 6880microsec.
Non si puo' inserire la formula in modo che inserndo il valore in Hz si modifica automaticamente il valore ?
P.s. ieri ho applicato sull'uscita del ATTiny un passa basso rc con r=22kohm e c= 100nf e la forma e' quasi una sinusoide

1/71,9/2=6954us.

uint32_t t_semiper=0;
uint16_t semiperiodo = 500000/71.9 +.5; // semiperiodo in us.
                                        // Inserire al posto di 71.9 la frequenza desiderata;
                                        // +.5 è per l'arrotondamento.
void setup()
  {
  pinMode (2, OUTPUT); // Uscita su I/O 2.
  // equivalente a: DDRB=0b00000100;
  }

void loop()
  {
  if(micros()-t_semiper>=semiperiodo) // Se è trascorso un semiperiodo (semiperiodo in us):
    {
    PINB|=0b00000100; // Inverte lo stato di I/O 2.
    t_semiper+=semiperiodo; // Incrementa t_semiper di 6954us.
    }
  }

Bello!!

Questo sketch è perfetto, Con un attiny e quarzo esterno da 16 MHz, è preciso al centesimo di Hz. (94,8).

1 Like

Essendomi ricapitata questa discussione, faccio presente che il limite inferiore dei 100kHz probabilmente dipende solo dalla poca ripidità dei fronti del segnale per il contatore e si risolve aggiungendo una porta a trigger di Schmitt:

Dove va collegato il quarzo esterno sulla scheda ?

Una soluzione potrebbe essere utilizzare un prodotto simile della baite atmega48 che ho modificato per leggere frequenze da 1 a 200khz , ho tolto il prescaler che è il motivo per cui non leggeva da 1 hz

http://www.dmxpassion.altervista.org/pg025.html

C'era un tempo che cercavo tutti i prodotti che contenevano un atmega328 o simili per modificarli per altri usi, ne ho trovati molti con un MC della stm08 che costa meno dell' atmega8 (30 centesimi)e ha prestazioni analoghe, compilatore C è gratuito e funziona bene