Domanda:
Perché a volte un LED lampeggia quando si aumenta la luminosità?
Adrian
2015-11-20 09:09:37 UTC
view on stackexchange narkive permalink

Questo è certamente un post incrociato di malfunzionamento della dissolvenza dei LED (flash casuale) ma non riesco a ottenere una risposta sul forum di Arduino.

Stavo scherzando con un codice molto semplice e ho notato che quando si tiene ripetutamente un LED a luminosità 0 per 1 secondo e poi si dissolve alla massima luminosità, occasionalmente si verificava un piccolo lampo all'inizio di ogni dissolvenza (apparentemente casuale).

  int led = 11; int luminosità = 0; void setup () {pinMode (led, OUTPUT);} void loop () {if (luminosità > = 256) // controlla se la luminosità ha superato 255, si ripristina a 0 {analogWrite (led, 255); luminosità = 0; } analogWrite (led, luminosità); se (luminosità == 0) {ritardo (1000); // LED spento per 1 secondo} luminosità + = 1; // incremento del ritardo della luminosità (20);}  

Quindi, la cosa che mi ha completamente perplesso è che posso usare un pezzo di codice diverso (sotto) e il flash scompare!

  int i = 0; int led = 11; void setup () {pinMode (led, OUTPUT);} void loop () {analogWrite (led, i); delay (6); if (i% 256 == 0) {i = 0; delay (1000);} i ++;}  

Qualcuno ha la più pallida idea del perché ciò sarebbe accaduto? Entrambi i programmi hanno fondamentalmente lo stesso codice, tranne per il fatto che i viene reimpostato a 0 nel primo programma mentre nel secondo continuo a incrementare oltre 255 in modo che analogWrite "overflow". Penso che debba essere un problema del firmware (o forse del software?).

C'è un video su YouTube che mostra ciò che accade qui, Arduino - problema del LED sbiadito.

Prova a rimuovere `analogWrite (led, 255);` poiché è abbastanza inutile, dato che due righe sotto di esso, è riportato a 0. Non riesco a vedere nulla di veramente sbagliato nel codice (a parte un ordine un po 'strano) .
Nel secondo codice, cambia `delay (6)` in `delay (20)` - appare il flash? Hai il secondo codice che scorre tre volte più velocemente del primo codice (ignorando il ritardo di 1 secondo, ovviamente), quindi il flash casuale è probabilmente non rilevabile. Per quanto riguarda * perché c'è un lampo * ... non ne ho idea.
@Gerben Questo è vero ... :) Lo farà
@CharlieHanson Ho provato ad aumentare il ritardo e non ha alcun effetto. Riesco ancora a rilevare il flash con il ritardo di 6 secondi. Ora ho una buona risposta / spiegazione sul motivo per cui accade sul forum di Arduino.
Oops, intendevo un ritardo di 6 millisecondi.
Una risposta:
brtiberio
2015-11-21 01:38:22 UTC
view on stackexchange narkive permalink

Secondo i link forniti dal forum arduino.cc la domanda ha più o meno una risposta. Se non è così importante, evita semplicemente analogWrite (led, 0) e rendilo analogWrite(led,1)

se lo desideri ancora analogWrite (led, 0) , ho testato il tuo codice con il consiglio e sembra funzionare bene quando si cambia il registro manualmente:

  #include "wiring_private.h" int led = 11; int luminosità = 0; void setup () {pinMode (led, OUTPUT);} void loop () {if (luminosità > = 256) // controlla se la luminosità ha superato 255, si ripristina a 0 {luminosità = 0; sbi (TCCR2A, COM2A1); OCR2A = 0; // imposta pwm duty} analogWrite (led, luminosità); se (luminosità == 0) {ritardo (1000); // LED spento per 1 secondo} luminosità + = 1; // incremento del ritardo della luminosità (20);}  

Modifica: per spiegare cosa sono questi "codici strani"

Non sono molto esperto in questo campo per spiegare come funziona esattamente ma fondamentalmente sbi è una funzione definita in una macro da Atmel (?), sta per " s e b it i n "e viene utilizzato per modificare i registri dei chip ATmega. Quindi in pratica quello che ho fatto è stato cambiare registro definito dalla macro TCCR2A (perché? Perché è il registro che controlla PWM nel pin 11) e passare la maschera di bit COM2A1 (questo è una modalità di confronto definita nella scheda tecnica) e OCR2A è un registro utilizzato per memorizzare il valore di confronto che definisce il ciclo di lavoro. Immagina un contatore che ogni volta che riceve un tick da un segnale clock confronta il valore del contatore con il valore memorizzato in OCR2A e imposta il pin alto o basso se quel valore è stato passato o meno (più o meno così, dipende dalla modalità memorizzata su TCCR2A).

Ma in realtà non ho fatto magie nere. Ho appena esaminato il codice di analogWrite () ed è così che usano per impostare un valore di PWM nel pin 11:

  void analogWrite (uint8_t pin, int val) {// Dobbiamo assicurarci che l'uscita PWM sia abilitata per quei pin // che lo supportano, mentre giriamo si spegne durante la lettura digitale o // la scrittura con loro. Inoltre, assicurati che il pin sia in modalità di output // per coerenza con Wiring, che non richiede una chiamata pinMode // per i pin di output analogico. pinMode (pin, OUTPUT); if (val == 0) {digitalWrite (pin, LOW); } else if (val == 255) {digitalWrite (pin, HIGH); } else {switch (digitalPinToTimer (pin)) {... #if defined (TCCR2A) && defined (COM2A1) case TIMER2A: // collega pwm al pin sul timer 2, canale A sbi (TCCR2A, COM2A1); OCR2A = val; // imposta il duty break pwm; #endif ...}  

Quindi fondamentalmente ho usato queste informazioni per impostare il registro a zero, come suggerito dal link del forum arduino.cc che hai.

Se vuoi saperne di più sul PWM in Arduino, questo sito ha molte informazioni e spiega anche molte delle modalità di registrazione.

Grazie @Personagem, lo proverò, ma potresti spiegare l'uso di ** sbi **, ** TCCR2A **, ** COM2A1 ** e ** OCR2A **. Inoltre, considerando che wiring_private.h è dei file header inclusi nella directory Arduino, è necessario includerlo?
Inoltre, come impari come utilizzare queste librerie in primo luogo?
@Adrian Ho modificato per spiegare un po 'di quei codici e l'IDE di arduino si lamenta se non l'ho fatto includere. Non sono proprio un esperto ma se vuoi approfondire, la scheda tecnica di atmega è tua amica. Questo dovrebbe essere usato in una sorta di modo avanzato. Ciò che ha fatto il team di arduino.cc (e questa è la vera bellezza che cambia un po 'il mondo di tutti) è stato creare semplici funzioni che non richiedono all'utente tipico di scavare nei fogli dati e in alcune impostazioni dei registri. Hanno reso semplice ciò che potrebbe essere difficile per le persone non così esperte. Tuttavia, se hai davvero bisogno puoi guardare tutto il codice in GitHub di arduino
Grazie mille per l'aiuto, la spiegazione e per il collegamento. Fondamentalmente posso vedere come farlo ora. Penso che tu possa trovare tutto il codice anche in \ hardware \ arduino \ avr \ cores \ arduino.
Non sarebbe "analogWrite (led, 1)" complice un effetto simile a "sbi (TCCR2A, COM2A1); OCR2A = 0;"? Cioè, impostando il ciclo di lavoro su un valore molto basso, appena prima di impostare l'uscita su BASSO. Ciò lo renderebbe molto più leggibile.
sì, l'ho suggerito nella prima frase. Ma nel caso in cui lo volesse davvero per qualsiasi motivo o solo curiosità, questa dovrebbe essere la strada. Infatti il ​​problema si basa su come la funzione analogWrite gestisce i valori di 0 e 255 senza cambiare i registri


Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...