PulseIn() non funziona con impulsi lunghi 1000mS ?

Salve a tutti,
ho provato questo semplice codice:

int pin = 3;
unsigned long duration;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
}
void loop()
{
  duration=pulseIn(pin,HIGH);
  Serial.println(duration);
}

Entrando con un impulso di circa 860mS (proveniente da un circuito esterno), ottengo come valore di durata sempre pari a 0.
Ho controllato l'impulso di ingresso ed è perfettamente squadrato, con livello HIGH di 5V e pulito (senza impulsi spuri).

Ho provato sia su ArduinoUNO, sia su Arduino 10000 con lo stesso risultato.
L'IDE utilizzata è la 0022.

Dov'è il problema?

Grazie a tutti.

La pulsin ha un timeout di circa 1s, valore di default, se l'impulso non arriva entro tale tempo ritorna 0.

Se vuoi modificare il timeout devi usare il formato esteso della pulsein :

pulseIn(pin, value, timeout)

Timeout è un unsigned long e rappresenta i microsecondi attesi prima del timeout.

Ciao fagio
Questo Timeout serve per non far bloccare l'Arduino in eterno se non vengono impulsi.

PulseIn() blocca l' arduino nello stesso modo di delay()Lui aspetta e non fa nient altro.

Ciao Uwe

Ciao A tutti,
grazie per la celere risposta. Ho provato aggiungendo 2 secondi di timeout

int pin = 3;
unsigned long duration;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
}
void loop()
{
  duration=pulseIn(pin,HIGH,2000000); //Timeout in uS corrispondenti a 2000mS
  Serial.println(duration);
}

Non cambia assolutamente niente. Anzi, addirittura gli "0" in uscita sul serial out vanno ancora più veloci...

Ho provato semplicemente a toccare con un filo tra il +5V e il PIN 3, e ottengo in uscita valori casuali diversi da "0" (come è normale). Se però tengo il filo collegato per circa un secondo, ottengo sempre "0".

Anche simulando l'impulso con un filo non riesco ad ottenere valore di ritorno di più di "205000" circa (che corrispondono a 205mS).

Ho provato alla fine con altri esempi presi qua e la nella rete ma nessuno funziona come dovrebbe in nessuna delle mie schede ARDUINO. (i valori che ottengo in uscita nelle solite condizioni,sono completamente diversi da quelli che hanno gli utenti da dove ho prelevato i listati)

Non è che c'è qualche problema con l'IDE 0022? (volevo provare con un IDE + vecchio).

Grazie ancora.

fagio:
Non è che c'è qualche problema con l'IDE 0022? (volevo provare con un IDE + vecchio).

Sarebbe un bug troppo macroscopico per non essere già stato reso noto, comunque usare un filo per simulare l'impulso non va bene per i noti problemi dovuti ai rimbalzi dei contatti meccanici, al massimo ottieni impulsi random compresi tra qualche ms e qualche decina di ms.
Adesso non posso fare nessuna verifica pratica della cosa, più tardi provo ad usare un Arduino come generatore di impulsi da 1.5 secondi, un secondo Arduino per misurarli e vediamo di capire dove sta esattamente il problema.

Ciao a tutti,

Ho provato lo stesso codice (l’ultimo post che ho scritto) con la IDE 0020. Funziona perfettamente con la mia applicazione (timeout 2 secondi, ecc…) dando,i in uscita valori di circa “864000” (corrispondenti appunto a 864mS, come misurati con oscilloscopio)

A questo punto, confermo che secondo me è un BUG della IDE 0022.

Fate pure le vostre prove.

Ciao.

Ho fatto una prova al volo, effettivamente la pulsein sembra non accettare il parametro timeout se questo vale più di 1 secondo e ha reali problemi con i tempi lunghi.
Tocca dare un'occhiata al sorgente della funzione per capire dove sta il problema.

Ho scoperto dove sta il problema.
La differenza tra la versione 020 e la 022, per quanto riguarda la pulseIn(), è solo nel fatto nella 022 il timeout vale solo per la fase di attesa impulso mente nella 022 viene conteggiato anche durante l'impulso.
Dal punto di vista del codice nella 022 abbiamo :

// wait for the pulse to stop
	while ((*portInputRegister(port) & bit) == stateMask) {
		if (numloops++ == maxloops)
			return 0;
		width++;
[code]
#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )

Mentre nella 020 abbiamo:

// wait for the pulse to stop
	while ((*portInputRegister(port) & bit) == stateMask) width++;

In pratica nella 020 se l'impulso non arriva mai alla fine del suo ciclo Arduino rimane bloccato in eterno, nella 022 se il ciclo impulso + attesa è superiore al timeout l'operazione viene terminata e la funzione ritorna 0.
Quanto sopra spiega perché con le condizioni imposte in questo thread con la 020 funziona e con la 022 no, però il vero problema non è questo perché la modifica nella 022 è solo una condizione di sicurezza in più per evitare di bloccare Arduino.
L'errore è nel calcolo del timeout, anche quello di default non è un secondo, è molto meno, il tutto parte da come viene definito il conteggio dei cicli di clock nella 022.
La riga di codice, nella pulsein, che determina la durata del timeout è:

unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;

Viene invoca la macrodefinizione microsecondsToClockCycles, che ritorna il numero di cicli macchina, in funzione di F_CPU, per un microsecondo di tempo reale e viene divisa per il valore 16 che incidentalmente corrisponde al numero di cicli macchina per ogni microsecondo con il quarzo da 16 MHz.
In realtà 16 è il numero di cicli macchina necessari per ogni iterazione delle varie while per il controllo del loop di attesa, è solo un caso che i due valori coincidano.
La define di microsecondsToClockCycles si trova in wiring.h ed è la seguente:

#define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )

Apparentemente è perfetta, ma in realtà c'è un problema che viene fuori solo con valori maggiori di 268435 come valore per il computo, nel nostro caso il timeout, questo perché per come sono organizzate le precedenze del calcolo prima si computa F_CPU/1000, che da 16000, e poi si moltiplica per "a" che è il valore passato per il timeout.
Facendo un paio di conti è facile verificare che 160000x268435 fa 4294960000 mente 16000x268436 fa 4294976000 che è un valore maggiore del limite imposto dalla matematica a 32 bit che è 4294967295.
Quanto sopra comporta che pure il valore di default per il timeout, 1000000 come impostato nel prototipo della funzione, genera un valore reale sbagliato nettamente inferiore al secondo.
Per risolvere, in attesa di una patch nella 0023, basta editare a mano il file wiring.h modificandolo in questo modo:

// #define microsecondsToClockCycles(a) ( ((a) * (F_CPU / 1000L)) / 1000L )
#define microsecondsToClockCycles(a) ( (a) * (F_CPU / 1000000L))

[/code]

hai aperto una bug request (o controllato se esiste di già?)?

la issue 675 segnalata su google code sembra affrontare proprio questo problema.

C'è già stato il bugfix fatto da D. Mellis, risale solo a poco più di 1 mese fa quindi, per ora bisogna fare la modifica proposta nella segnalazione oppure quella proposta da Astrobeed (che poi sono la stessa cosa) a mano, qualsiasi versione dell'IDE stiate usando oppure, aspettare la prossima release dell'IDE.