Buon giorno ragazzi volevo chiedervi una cosa io ho l'esigenza di far blinkare dei led a due frequenze diverse "5Khz" ed "7.5Khz".Ho gia pensato al circuito praticamente comando due transistor come interruttori ai quali saranno collegamti i led ad alta luminosita da un alimentazione a parte. Cmq la mia domanda è visto che una volta acceso il tutto deve rimanere accesso per molto tempo ma molto molto volevo chiedervi la stabilità sulla frequenza. Cioè l'arduino mi butterà continuamente fuori le due frequenze esatte senza varianzioni grandi di frequenza???
p.s il segnale di output ovviamente e alto basso :-/
ciao,
una volta realizzate correttamente le due frequenze non c'è motivo di pensare che alla lunga Arduino "perda colpi".
Per caso pensavi di prendere spunto da http://arduino.cc/en/Tutorial/BlinkWithoutDelay?
Allora l'idea era praticamente generare due segnali alto-basso alle due frequenze e pilotare due transistor come interruttori attaccati ai led.
E volevo solo sapere se alla lunga il nostro piccolo ma potente arduino non perda colpi sai deve attaccare il tutto a una macchina di controllo cmq mi dite non perderà colpi vero.????
ciao, di suo Arduino non perde colpi (sempre se utilizzato entro le specifiche di funzionamento dell' ATmega328), è eventualmente l'algoritmo che genera le due frequenze che può essere strutturalmente debole (es. overflow non presi in considerazione).
No il programma che uso Multisim della national instruments. Cmq si l'algoritmo devo studiarlo molto molto bene pero devo anche dire una cosa che sono un niubbo nel mondo arduino perche questo sarebbe il mio primo progetto con l'arduino. Ovviamente ragazzi ogni aiuto è ben accetto conosco il C quindi mastico gia qualcosa. Pero non saprei nemmeno da dove partire...........
const int led1Pin = 13; // the number of the LED1 pin
const int led2Pin = 12; // the number of the LED2 pin
int led1State = LOW; // ledState used to set the LED
int led2State = LOW; // ledState used to set the LED
unsigned long previousMicrosLed1 = 0; // will store last time LED was updated
unsigned long previousMicrosLed2 = 0; // will store last time LED was updated
long intervalLed1 = 100; // interval at which to blink (microseconds)
long intervalLed2 = 68; // interval at which to blink (microseconds)
void setup() {
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
}
void loop()
{
unsigned long currentMicros = micros();
//gestione f= 5kHz
if(currentMicros < previousMicrosLed1)
{
if(0xffffffff - previousMicrosLed1 + currentMicros >= intervalLed1)
{
// save the last time you blinked the LED
previousMicrosLed1 = currentMicros;
// if the LED is off turn it on and vice-versa:
if (led1State == LOW)
led1State = HIGH;
else
led1State = LOW;
// set the LED with the ledState of the variable:
digitalWrite(led1Pin, led1State);
}
}
else
{
if(currentMicros - previousMicrosLed1 >= intervalLed1)
{
// save the last time you blinked the LED
previousMicrosLed1 = currentMicros;
// if the LED is off turn it on and vice-versa:
if (led1State == LOW)
led1State = HIGH;
else
led1State = LOW;
// set the LED with the ledState of the variable:
digitalWrite(led1Pin, led1State);
}
}
//gestione f= 7.35kHz
if(currentMicros < previousMicrosLed2)
{
if(0xffffffff - previousMicrosLed2 + currentMicros >= intervalLed2)
{
// save the last time you blinked the LED
previousMicrosLed2 = currentMicros;
// if the LED is off turn it on and vice-versa:
if (led2State == LOW)
led2State = HIGH;
else
led2State = LOW;
// set the LED with the ledState of the variable:
digitalWrite(led2Pin, led2State);
}
}
else
{
if(currentMicros - previousMicrosLed2 >= intervalLed2)
{
// save the last time you blinked the LED
previousMicrosLed2 = currentMicros;
// if the LED is off turn it on and vice-versa:
if (led2State == LOW)
led2State = HIGH;
else
led2State = LOW;
// set the LED with the ledState of the variable:
digitalWrite(led2Pin, led2State);
}
}
}
genera due onde quadre, una a 5kHz e l'altra a 7,35kHz
previousMicrosLed1 se non ho capito male questa variabile conterra lo stato precedente del led giusto....Adesso dico una castroneria oppure e perche sono stanco.....questa variabile assumera solo due stati diciamo "o che era cceso o che era spento" giusto. Cioe non e che magari andra in overflow il prog????
previousMicrosLed1 memorizza l'istante (in microsecondi) in cui c'è stata l'ultima variazione dell'uscita. è micros() che andrà in overflow dopo poco più di 70 minuti dall'accensione di Arduino .http://arduino.cc/en/Reference/Micros. Per gestire questo ho inserito il controllo
if(currentMicros < previousMicrosLed1)
questa condizione diventerà vera proprio quando micros() andarà in overflow
si ottengono due onde quadre che hanno una frequenza media di 4,9kHZ e 7,3kHz. Non sono prefettamente stabili. Quella da 4,9kHz nel tempo varia tra 4,8 e 5,2 circa metre quella da 7,3kHz varia tra 7 e 7,9. Soddisfa i tuoi requisiti?
Ho tenuto acceso Arduino per più di 72 minuti in modo che ci fosse l'overflow sui valori dati da micros() e non ci sono state variazioni. Non ho però valutato l'istante dell'overflow.
Piccolo appunto: NON collegare il pin di Arduino direttamente alla base del transistor, metti in serie una resistenza. 1kOhm può andare bene
Perdonatemi l'intrusione :P, ma la soluzione al problema per mantenere l'assoluta stabilità e precisione delle frequenze emesse, per personale esperienza, è possibile solo tramite la programmazione di un timer interno al micro che generi un interrupt ad una frequenza base (in questo caso 0.5kHz).
Più alta è la priorità dell'interrupt e minore è la probabilità di errore (se non erro Arduino ha delle funzioni sotto interrupt abilitate per la programmazione e la comunicazione via seriale/usb che possono influire in una generazione di una data frequenza al pari di uno o più overflow)
lo so, io mi sono basato su Arduino - Home per provare a risolvere il problema di morphy. Se per i suoi scopi il risultato non è soddisfacente si dovrà utilizzare
Si tratta delle funzioni logiche per settare i bit dei registri del processore per attivare i timer interni (se guardi sul datasheet trovi la spiegazione di ciascuna costante presente: http://www.atmel.com/dyn/resources/prod_documents/doc2545.pdf)
Per provarlo basta che lo scarichi in Arduino e controlli le uscite indicate. Vedrai che, nonostante il loop principale sia vuoto, il processore emette le frequenze che ti servono...
Una raccomandazione: non ti limitare ad usare questo codice ignorandone il significato, perchè gli interrupt sono estremamente utili e ti consentono di far fare al processore più azioni "contemporaneamente"(*) in modo slegato tra loro. Cerca di capire come funziona la faccenda e vedrai che non potrai più farne a meno
Ciao
*) In realtà, a meno che non si tratti di far lavorare dispositivi interni alla mpu collegati direttamente a dei pin (come in questo caso), l'apparente contemporaneità è di fatto un time-sharing della cpu, con la differenza, rispetto ad un normale flusso sequenziale di programma, che l'interrupt da la garanzia di far ripetere una data funzione in modo più sicuro in base a priorità prestabilite...
---- dimenticavo:
perchè funzioni devi mettere prima l'include che ti ha indicato frog, ovvero, questo è il codice per intero:
//qui include l'header con tutte le definizioni di funzioni e costanti necessarie a trattare gli interrupt
#include < avr/interrupt.h >
//poi inizializza i due timer e li attiva
void setup()
{
TCCR2A |= (0 << COM2A1) | (1 << COM2A0) | (1 << WGM21) | (1 << WGM20) ;
TCCR2B &= ~((1 << CS22 ) | (1 << CS21 ) | (1 << CS20 ));
TCCR2B |= (1 << WGM22 ) | (0 << CS22 ) | (1 << CS21 ) | (0 << CS20 ) ;
OCR2A = 199;
DDRB |= (1 << DDB3 );
TCCR0A |= (0 << COM0A1) | (1 << COM0A0) | (1 << WGM01) | (1 << WGM00) ;
TCCR0B &= ~((1 << CS22 ) | (1 << CS21 ) | (1 << CS20 ));
TCCR0B |= (1 << WGM02 ) | (0 << CS22 ) | (1 << CS21 ) | (0 << CS20 ) ;
OCR0A = 132;
DDRD |= (1 << DDD6 );
}
//qui trovi il "solito" loop del programma che può fare azioni totalmente slegate dall'emissione delle due frequenze
void loop()
{
}
@Nyo
all'inizio non è semplice (non per niente il datasheet è di 448 pagine). secondo me uno dei punti di forza del linguaggio utilizzato da Arduino è proprio la semplificazione nell'approccio con un microcontrollore
@kokiua
anch'io mi aspettavo servisse includere l'header. la compilazione, però, va a buon fine lo stesso. hai idea del perché?
@frog:
probabilmente perchè il compilatore deve permettere al bootloader di lavorare con la seriale e quindi abilita di default gli interrupt. Direi che comunque dovremmo chiedere a Massimo Banzi... non c'è persona più indicata alla quale chiedere conferme