Go Down

Topic: Uscita impulsiva per 3 secondi (Read 1 time) previous topic - next topic

pietro78

Mi trovo a smanettare con arduino1 e shield I/O con 6 ingressi e 6 uscite a relè...

Volevo integrare allo sketch seguente una funzione che pi pemette di attivare una uscita pin per secondi in maniera impulsiva se il carattere ricevuto dalla seriale IDE è per esempio "J1"...

Mi spiego meglio :

Carattere ricevuto  "O1"   ------  attivo uscita 1 equivalente a Pin7
Carattere ricevuto  "O1"   ------  disattivo uscita 1 equivalente a Pin7  modalità PASSO-PASSO

Carattere ricevuto  "J1"   ------  attivo uscita 1 equivalente a Pin7 per 3 secondi e poi si spegne

Carattere ricevuto  "I1"   ------  leggo stato-ingresso 1 equivalente a Pin2

Lo sketch è il seguente :

Code: [Select]


// Variables will change:
int in=0;             
int out=0;
int an=0;
int inByte=0;

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
 
    // start serial port at 9600 bps:
  Serial.begin(9600);


  // set the digital pin as output:
  for (int out=8; out<=13; out++){
    pinMode(out, OUTPUT);     
  }
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.

  if (Serial.available() > 0) {
    protocollo();
  }
 
     
}


void protocollo()
{
  inByte = Serial.read();
    switch (inByte)
    {
        case 79: //O  out
         
         
          Serial.println("Out number? (1 to 6)");   // send an initial string
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            out = Serial.read()-48;
            Serial.println("ricevuto ");
            Serial.print(out);
            if (out>=1&&out<=6)
            {
              out=out+7;
              if (!digitalRead(out))
                digitalWrite(out, HIGH);
              else
                digitalWrite(out, LOW);
               
              Serial.print("Out ");
              Serial.print(out-7);
              Serial.print(" = ");
              Serial.println(digitalRead(out));
            }
         
          break;
         
        case 73: //I
          //input
         
          Serial.println("In number? (1 to 6)");   // send an initial string
       
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            in = Serial.read()-48;
            if (in>=1&&in<=6){
            in=in+1;
           
            Serial.print("In ");
            Serial.print(in-1);
            Serial.print(" = ");
            Serial.println(digitalRead(in));
            }
          break;
         
          case 65: //A
          //analog
         
          Serial.println("Analog number? (1 to 6)");   // send an initial string
       
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            an = Serial.read()-48;
            if (an>=1&&an<=6){
            an=an-1;
           

            Serial.print("Analog ");
            Serial.print(an+1);
            Serial.print(" = ");
            Serial.println(analogRead(an));
            }
          break;

         
        //default:
          // if nothing else matches, do the default
          // default is optional
     
    }

   
}



Ora allego la modifica chiaramente con il blocco di codice mancante legato alla funzione dell'uscita impulsiva che ho realizzato con i Delay ma non mi soddisfa in quanto mi blocca il codice e ho provato con millis ma senza nessun risultato valido...un aiuto di cuore a chi volesse aiutarmi....grazie...

Code: [Select]


// Variables will change:
int in=0;             
int out=0;
int an=0;
int inByte=0;

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
 
    // start serial port at 9600 bps:
  Serial.begin(9600);


  // set the digital pin as output:
  for (int out=8; out<=13; out++){
    pinMode(out, OUTPUT);     
  }
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.

  if (Serial.available() > 0) {
    protocollo();
  }
 
     
}


void protocollo()
{
  inByte = Serial.read();
    switch (inByte)
    {
        case 79: //O  out
         
         
          Serial.println("Out number? (1 to 6)");   // send an initial string
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            out = Serial.read()-48;
            Serial.println("ricevuto ");
            Serial.print(out);
            if (out>=1&&out<=6)
            {
              out=out+7;
              if (!digitalRead(out))
                digitalWrite(out, HIGH);
              else
                digitalWrite(out, LOW);
               
              Serial.print("Out ");
              Serial.print(out-7);
              Serial.print(" = ");
              Serial.println(digitalRead(out));
            }
         
          break;
         
        case 73: //I
          //input
         
          Serial.println("In number? (1 to 6)");   // send an initial string
       
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            in = Serial.read()-48;
            if (in>=1&&in<=6){
            in=in+1;
           
            Serial.print("In ");
            Serial.print(in-1);
            Serial.print(" = ");
            Serial.println(digitalRead(in));
            }
          break;

         
           case 74: //J  out IMPULSIVA
         
         
          Serial.println("Out number? (1 to 6)");   // send an initial string
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            out = Serial.read()-48;
            Serial.println("ricevuto ");
            Serial.print(out);
            if (out>=1&&out<=6)
            {
              out=out+7;
              if (!digitalRead(out))
                digitalWrite(out, HIGH);
           
                 delay(3000);        // uscita impulsiva a 3 secondi ma non multitasking...vorrei realizzarla col     
                                          // millis ma non sono riuscito...

                digitalWrite(out, LOW);
               
              Serial.print("Out ");
              Serial.print(out-7);
              Serial.print(" = ");
              Serial.println(digitalRead(out));
            }
         
          break;
         

         
          case 65: //A
          //analog
         
          Serial.println("Analog number? (1 to 6)");   // send an initial string
       
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            an = Serial.read()-48;
            if (an>=1&&an<=6){
            an=an-1;
           

            Serial.print("Analog ");
            Serial.print(an+1);
            Serial.print(" = ");
            Serial.println(analogRead(an));
            }
          break;

         
        //default:
          // if nothing else matches, do the default
          // default is optional
     
    }

   
}



Grazie...

Hai provato con le librerie di classi create da leo72?

C'è il leOS, SecTimer o simile, cerca un suo post e trovi i link alle librerie, puoi anche cercare nel playground.

Oggi di leggere codice proprio non ci riesco, mi girano gli occhi.

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

pietro78

Per rispondere a Maurotec non ho provato le librerie esterne perchè volevo realizzare il tutto con un semplice millis() ma quello che sembra strano è proprio che realizzare una uscita impulsiva sembra facile ma non lo è per niente....
Ad esempio ho provato un semplice sketch dove premo un pulsante e piloto un led pin on-off per 3 secondi ma ripeto senza il delay vado in tilt...

Se qualcuno mi può aiutare con un esempio di uscita impulsiva realizzato con millis ne sarei veramente riconoscente...poi capito il concetto provo anche a buttarmi con le librerie secTimer e LeOs...
Grazie...

leo72


Ad esempio ho provato un semplice sketch dove premo un pulsante e piloto un led pin on-off per 3 secondi ma ripeto senza il delay vado in tilt...

Che intendi per impulsivo? Cioè tenere un'uscita alta per 3 secondi da quando premi un pulsante?

Senza una variabile di stato non lo puoi fare.
Code: [Select]
byte stato = false;
byte pulsante = 2;
byte led = 13;
unsigned long myMillis;

void setup() {
    pinMode(led, OUTPUT);
    pinMode(pulsante, INPUT_PULLUP);
}

void loop() {
  if (!digitalRead(pulsante)) {
    delay(30); //debounce
    if (!digitalRead(pulsante)) {
      digitalWrite(led, HIGH);
      stato = true;
      myMillis = millis();
    }
  }
  if (stato) {
    if (millis() - myMillis > 3000) {
      digitalWrite(led, LOW);
      stato = false;
    }
  }
}


Come funziona il codice?
Ogni volta che premi il pulsante (uso la logica del LOW come premuto, il pulsante è tenuto alto con la pull-up interna) viene messo a TRUE il flag che controlla lo stato del led, questo viene acceso e poi viene salvato il valore attuale di millis.
Si controlla poi se lo stato del flag. Se è TRUE, si guarda se è trascorso l'intervallo voluto, 3 secondi. Se sì, si spenge il led e si rimette a FALSE lo stato.

pietro78

Grazie Leo per il codice...non ancora ho modo di provare il codice ma penso che hai trovato la souzione...

Una sola domanda a scopo didattico se mi permetti ...cosa significa il punto esclamativo ??

Code: [Select]
if (!digitalRead(pulsante))

Penso che debba significare "se leggi la pressione del pulsante" ma non conoscevo l'espressione con il "!"...

gpb01

#5
Mar 28, 2013, 02:22 pm Last Edit: Mar 28, 2013, 02:25 pm by gpb01 Reason: 1

...
Una sola domanda a scopo didattico se mi permetti ...cosa significa il punto esclamativo ??
...


E' l'operatore booleano di NEGAZIONE : http://arduino.cc/en/Reference/Boolean

In pratica, se la digitalRead ritorna "vero" il "!" lo inverte in "falso" e viceversa ;)

Guglielmo

P.S. : Leo ti ha specificato che usa la logica del LOW per indicare pulsante premuto, quindi tu, nell'IF, devi rilevare la condizione di LOW
Search is Your friend ... or I am Your enemy !

pietro78

Ne approfitto per un'altra domanda didattica...siccome non ho avuto ancora modo di verificare il codice mi pare strana l'espressione:

Code: [Select]
if (stato)
{  }


In pratica con la condizione "if(stato)"  cosa si esprime ??!!

gpb01


...
In pratica con la condizione "if(stato)"  cosa si esprime ??!!


L'operatore IF è utilizzato per verificare se una certa condizione è vera e, in tal caso, eseguire quello che è specificato ... qui il riferimento : http://arduino.cc/en/Reference/If

In pratica tu hai

Code: [Select]
if (condizione_da_verificare) {

  cosa_fare_se_la_condizione_è_vera
}
else {
  cosa_fare_se_la_condizione_è_falsa
}


la parte dell' else è opzionale.

Credo comunque che sarebbe bene se dedicassi un po' di tempo alla lettura almeno di un semplice manuale di "C" e del "reference" http://arduino.cc/en/Reference/HomePage ;)

Guglielmo
Search is Your friend ... or I am Your enemy !

gpb01

Scusa, forse ho frainteso io la domanda ... forse non avevi capito proprio cosa intendesse Leo con quell' IF ?

In tal caso ...
... "stato" come vedi è una variabile di tipo "byte" che Leo dichiara inizialmente "false" e che, se si verificano certe condizioni, mette invece a "true".

Nel successivo IF (stato) non fa altro che controllare se quella variabile è ancora a "false" (e quindi le condizioni non si sono verificate) o a "true" .... in tal caso esegue quello che c'è nell'IF ...

Altri dubbi ? :)

Guglielmo
Search is Your friend ... or I am Your enemy !

leo72

Guglielmo ti ha spiegato la logica che ho adoperato.
Sono tutte delle contrazioni per ridurre il quantitativo di codice da scrivere.

Bisogna conoscere Arduino e cosa fa per poi poterlo usare, ma è anche utile conoscere il suo codice per poterlo usare.
false e true sono 2 costanti predefinite che valgono rispettivamente 0 e 1.
Avrei potuto utilizzare un tipo bool (booleano) per memorizzare false e true ma posso lo stesso usare un tipo byte che contiene un valore numerico, tanto devo metterci dentro solo 0 o 1, anche se sotto mentite spoglie (false e true, appunto).

Nei confronti, come gli if, una condizione è vera quando ha un valore diverso da 0, altrimenti è falsa. Quindi
fare
Code: [Select]
if (stato == true)
if (stato == 1)
if (stato)

è perfettamente equivalente. L'ultima, anzi, è una forma contratta dato che avendo stato appunto un valore di 0 o 1, può solo essere o falso o vero.

Anche per la lettura del pin ho usato le stesse abbreviazioni.
Ho precisato che uso la logica del LOW per premuto, per cui se l'utente preme un pulsante, significa che viene letto LOW.
Il test "lungo" sarebbe quindi:

Code: [Select]
if (digitalWrite(pin) == LOW)
Ora, in Arduino LOW vale 0 e HIGH vale 1.
Quindi il precedente test è equivalente a:
Code: [Select]
if (digitalWrite(pin) == 0)

Ma riprendendo quanto detto prima, lo 0 vale sempre false nei test.
Se però io inverto il risultato di un false ottengo che il test è vero quando è falso, giusto?
Quindi
Code: [Select]
if (!digitalRead(pin))
significa appunto
Code: [Select]
se (inverti(digitalRead(pin))
digitalRead(pin) è falso quando il pin restituisce LOW, cioè 0.
Invertendo 0 ottengo 1, per cui l'if esterno diventa vero quando il pin è inverti(0).

pietro78

Quote
Scusa, forse ho frainteso io la domanda ... forse non avevi capito proprio cosa intendesse Leo con quell' IF ?


Non ti preoccupare infatti io non avevo capito proprio l'espressione usata da Leo in questo caso...

Quote
if (stato == true)
if (stato == 1)
if (stato)
è perfettamente equivalente.


Grazie Leo per le apprezzabili delucidazioni...e anche a "gpb01 " ...ora è tutto chiaro ...voi siete i maestri e noi piano piano cerchiamo d'imparare...
E' evidente che chi sa masticare il C come voi usate delle scorciatoie per scrivere il codice...io purtroppo mi attengo alle formule più note e quelle che vedo già un pò diverse dalle altre per me sono "errori di forma" e invece sono chicche di saggezza...grazie a tutti...ora provo a concludere lo sketch che avevo postato all'inizio in modo tale da poterlo condividere con chi ne può avere bisogno...

leo72

Sicuramente Guglielmo sa masticare il C visto quel che ha fatto in tutti questi anni, io di sicuro no perché programmo in C da 2 anni e mezzo.  :smiley-sweat:
Solitamente non uso queste contrazioni quando scrivo codice per principianti proprio per evitare di incasinare ulteriormente l'utente che già di problemi ne ha di suo  ;)
Però stamani andavo di fretta ed ho scritto contratto per far prima. Manca anche la definizione di costante "const" messa davanti alla variabile del pin, così come ho usato un "byte" al posto di un "bool" perché avevo in mente una cosa e poi ne ho fatta un'altra  :smiley-yell:

gpb01


Sicuramente Guglielmo sa masticare il C visto quel che ha fatto in tutti questi anni, io di sicuro no perché programmo in C da 2 anni e mezzo.  :smiley-sweat:
...


Leo non fare il modesto ... che sappiamo bene di cosa sei capace ... :) :) :)

Guglielmo
Search is Your friend ... or I am Your enemy !

pietro78

Come promesso carico il codice e spiego il funzionamento...

Chiaramente lo sketch inizialmente è stato preso dagli esempi di futura elettronica da dove ho acquistato la simpatica shield 6IN/6OUT/6Analog e l'ho manipolato:

La scheda è in continuo ascolto sulla seriale e in base ai caratteri ricevuti compie delle azioni,ad esempio:

se digito sulla serile monitor dell'IDE arduino 1.03  :

"O1"  arduino accende il relè n.1 sulla scheda ma bensì relativo al pin7
"O2"  arduino accende il relè n.2 sulla scheda ma bensì relativo al pin8 ...etc..etc fino al relè n.6

"I1"   arduino controlla lo stato dell'ingresso fisico n.1 sulla scheda ma bensì relativo al pin 2 digitale
"I2"   arduino controlla lo stato dell'ingresso fisico n.2 sulla scheda ma bensì relativo al pin 3 digitale

Io ho cercato di implementare grazie all'aiuto di Leo e gpb01 un'altra funzione ovvero :

"J1"  arduino accende il rele n.1 sulla scheda per 2 secondi e poi la spegne
"J2"  arduino accende il rele n.2 sulla scheda per 2 secondi e poi la spegne   etc..etc..

Ora ho incontrato un problema...ovvero se invio due comandi consecutivi tipo "J1 J2" il sistema non risponde in multitasking bensì accende prima il Relè 1,dopo due secondi spegne il Relè 1,
poi accende il relè 2,dopo due secondi spegne il Relè 2...

Io volevo usare millis() proprio per evitare i ritardi nel codice...come posso fare ???
Il problema potrebbe essere legato ai Switch-Case creati ??

Grazie se avete ancora la pazienza di seguirmi...vi ringrazio già in anticipo...


pietro78

Mi ero dimenticato di caricare il codice...eccolo

Code: [Select]


// Variables will change:
int in=0;             
int out=0;
int an=0;
int inByte=0;

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
 
    // start serial port at 9600 bps:
  Serial.begin(9600);


  // set the digital pin as output:
  for (int out=8; out<=13; out++){
    pinMode(out, OUTPUT);     
  }
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.

  if (Serial.available() > 0) {
    protocollo();
  }
 
     
}


void protocollo()
{
  inByte = Serial.read();
    switch (inByte)
    {
        case 79: //O  out
         
         
          Serial.println("Out number? (1 to 6)");   // send an initial string
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            out = Serial.read()-48;
            Serial.println("ricevuto ");
            Serial.print(out);
            if (out>=1&&out<=6)
            {
              out=out+7;
              if (!digitalRead(out))
                digitalWrite(out, HIGH);
              else
                digitalWrite(out, LOW);
               
              Serial.print("Out ");
              Serial.print(out-7);
              Serial.print(" = ");
              Serial.println(digitalRead(out));
            }
         
          break;
         
        case 73: //I
          //input
         
          Serial.println("In number? (1 to 6)");   // send an initial string
       
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            in = Serial.read()-48;
            if (in>=1&&in<=6){
            in=in+1;
           
            Serial.print("In ");
            Serial.print(in-1);
            Serial.print(" = ");
            Serial.println(digitalRead(in));
            }
          break;
         
          case 65: //A
          //analog
         
          Serial.println("Analog number? (1 to 6)");   // send an initial string
       
            while (Serial.available() <= 0)
            {
              delay(300);
            }
           
            an = Serial.read()-48;
            if (an>=1&&an<=6){
            an=an-1;
           

            Serial.print("Analog ");
            Serial.print(an+1);
            Serial.print(" = ");
            Serial.println(analogRead(an));
            }
          break;

         
        //default:
          // if nothing else matches, do the default
          // default is optional
     
    }

   
}



Forse l'errore stà che dovrei specificare un millis per ogni uscita,quindi unsigned long myMillis1,unsigned long myMillis2...etc..etc  spero di averci azzeccato...

Go Up