Vai al contenuto
PLC Forum


millis non funziona


kemosabe

Messaggi consigliati

Signori Buongiorno, proseguendo sulla comprensione della programmazione, ho un quesito da chiedervi.

Preferirei non avere soluzioni, ma indicazioni sul procedimento da adottare.

Dovrei inserire in una funzione esterna questo procedimento relativo alla temporizzazione di una porta con il suo relativo sensore magnetico

arriva il comando alla funzione

ho la porta chiusa, parte il tempo, se la porta rimane chiusa e scade il tempo, esco dalla funzione.

se apro la porta mentre il tempo non è ancora scaduto, attendo di chiudere la porta per poter uscire dalla funzione, anche se nel frattempo è scaduto il tempo

 

ci sto provando in vari modi da piu di una settimana, ma immancabilmente, sebbene abbia provato varie soluzioni, è come se il tempo di apertura non venisse mai calcolato, e quindi esce subito dalla funzione sia che la porta sia aperta o chiusa.

Vi ringrazio dei suggerimenti

 

Link al commento
Condividi su altri siti


11 minuti fa, kemosabe ha scritto:

Preferirei non avere soluzioni, ma indicazioni sul procedimento da adottare

 

Allora ti do le indicazioni.

  • Fissi una differenza di tempo massimo
  • Metti la condizione di uscita (ad esempio break) se si verifica una delle 2 condizioni: porta chiusa o differenza di tempo > del tempo massimo

In pratica di basta un if di un OR di 2 condizioni.

Link al commento
Condividi su altri siti

ci sto provando in tutte le maniere ma continua a saltare l'if del millis.

per curiosità ho provato a inserire l'esempio del blink without delay di arduino, dentro a quella funzione, e come volevasi dimostrare  😈 ...... fa sempre la stessa cosa, 

cioè salta a piè pari il millis.

 

Sto impazzendo....?????

spiegami perchè se il blink lo metto nel loop funziona, se invece è in una funzione esterna chiamata dal loop no.

cosa cambia ?????

grazie

Link al commento
Condividi su altri siti

Perchè, probabilmente, come ti ho spiegato nell'altra discussione, stai usando variabili locali della funzione. Dichiara la variabile dove memorizzi il valore di partenza del tempo come globale e, probabilmente, funziona.

Link al commento
Condividi su altri siti

ti metto questo ma è uguale a qualsiasi altro

 

 

 void open_door()
{
 // check the button
 if (digitalRead(door) == LOW) {
  // update the time when button was pushed
 buttonPushedMillis = currentMillis;
  door_state = true;
 }
  
 // make sure this code isn't checked until after button has been let go
 if (door_state) {
   //this is typical millis code here:
   if ((currentMillis - buttonPushedMillis) >= ledTurnedOnAt) {
     // okay, enough time has passed since the button was let go.
     digitalWrite(serratura, HIGH);
     // setup our next "state"
     door_time = true;
     // save when the LED turned on
     ledTurnedOnAt = currentMillis;
     // wait for next button press
     door_state = false;
   }
 }
  
 // see if we are watching for the time to turn off LED
 if (door_time) {
   // okay, led on, check for now long
   if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay) {
     door_time = false;
     digitalWrite(serratura, LOW);
   }
 }

fatto, tutte globali, ma niente di fatto

Modificato: da kemosabe
Link al commento
Condividi su altri siti

Cosa non funziona di questa funzione?

Secondo quello che leggo ogni volta che la richiami viene eseguita con i vari test e condizioni e le variabili vengono post alte o basse secondo il risultato del test.

Link al commento
Condividi su altri siti

Hai anche scritto

12 ore fa, kemosabe ha scritto:

spiegami perchè se il blink lo metto nel loop funziona, se invece è in una funzione esterna chiamata dal loop no.

cosa cambia ?????

 

Prova a mettere il codice di quello che non funziona così lo verifico

Link al commento
Condividi su altri siti

quella sopra, appena entra ne esce senza temporizzazione.

Ne metto un'altra, che non funziona:

void open_door() 
{
    door_state= digitalRead(door); 
  if ( door_state== HIGH) 
  {  
     leds[1]=CRGB(0,255,0);  //led porta   verde  on  aperta  
       FastLED.show();
        door_state = HIGH; 
  }  else   {    
             leds[0]=CRGB(255,0,0);       // led porta   rosso on chiusa  
               FastLED.show();
                door_state = LOW; 
 }
// unsigned long currentMillis = millis();
      
   if (door_state == LOW || door_time==true)
   {      
    if (stop_time_door - start_time_door >= tempo_door )
    {    start_time_door = stop_time_door;
    
         door_time=false;
         
     } 
 }

  if (door_state == LOW  && door_time == true)
    {   digitalWrite ( serratura, HIGH);               // serratura on 
         tone (buzzer,3000);              // buzzer medio
        
      Serial.println ("door close    time   serratura on 2 sec  suono medio");
          Serial.println ("          ");
          
    } else if (door_state == LOW && door_time==false)
      {         digitalWrite ( serratura, LOW);               // serratura on 
                 noTone (buzzer);              // buzzer medio
                   Serial.println ("door close   no time    no serratura  suono stop");
                  Serial.println ("          ");
                  delay(100);
                 
      } 
}

anche questa si comporta nello stesso modo

per chiarezza ti metto anche il pezzo di codice della chiamata;

 char customKey = myKeypad.getKey();
   if  (customKey)
     {
      // Serial.println(customKey);
      keys[count] = customKey;
      count++;
   if  (count == 4) 
     {
      //Serial.println(keys);
      if (strcmp(keys, password[n]) == 0) 
        {
         open_door();
      
         
         
         state = INIT_LCD;
        }
         count = 0;
     }
     }
  if  (millis() - time > 10000)     // exceed 10 seconds ?
    {  
     state = INIT_LCD;
    }

 

Link al commento
Condividi su altri siti

  if  (millis() - time > 10000)     // exceed 10 seconds ?
    {  
     state = INIT_LCD;
    }

Prova a riscriverla così

 

  if  ((millis() - time) > 10000)     // exceed 10 seconds ?
    {  
     state = INIT_LCD;
    }

 

A parte questo, tu avevi scritto

 

16 ore fa, kemosabe ha scritto:

spiegami perchè se il blink lo metto nel loop funziona, se invece è in una funzione esterna chiamata dal loop no.

cosa cambia ?????

 

Metti il codice di programmino che non va, compreso il codice che lo richiama, che vediamo il perchè non funziona.

Link al commento
Condividi su altri siti

il problema, credo non è il quel ritardo che mi hai chiesto di modificare, quello aspetta solo 10 secondi per l'inserimento del codice e poi esce.

adesso, per semplificare, ho temporaneamente disinserito la parte del codice, facendo l'accesso solo con l' RFID.

ti mando il tutto, con un'altra prova, ma anche questa non funge

 

grazie

//enum {INIT_LCD, SCAN_TAG, KEY_IN_PASSWORD} state = INIT_LCD;
enum {INIT_LCD, SCAN_TAG} state = INIT_LCD;
// define for keypad
#include <Keypad.h>
#include <Keypad_I2C.h>
#define I2CADDR 0x20  
#include <Wire.h>   
//FASTLED
#include <FastLED.h>
#define DATA_PIN  3
#define NUM_LEDS  6
#define CLOCK_PIN 13
CRGB leds[NUM_LEDS];

// define for nfc
#include <SPI.h>
#include <MFRC522.h>

#define NOT_FOUND -1

#define RST_PIN 9  
#define SS_PIN  10 

MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance

#define NR_KNOWN_CARDS  2
#define CARD_SIZE       4

// init paralle arrays
byte knownCards[NR_KNOWN_CARDS][CARD_SIZE] = {
  {0x04, 0x49, 0x81, 0x40},
  {0xe5, 0xa2, 0x9c, 0x2c}
};

char name[NR_KNOWN_CARDS][10] = 
{
  "Usul",
  "Richard"
};

char password[NR_KNOWN_CARDS][5] = 
{
  "1111", 
  "8888"
};

int n;  // current tag index

const byte numRows = 4; //number of rows on the keypad
const byte numCols = 4; //number of columns on the keypad
//define the cymbols on the buttons of the keypads
char keymap[numRows][numCols] =
{
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[numRows] = {0, 1, 2, 3}; //Rows 0 to 3
byte colPins[numCols] = {4, 5, 6, 7}; //Columns 0 to 3

int count = 0;
char keys[5];
unsigned long time;

Keypad_I2C myKeypad( makeKeymap(keymap), rowPins, colPins, numRows, numCols, I2CADDR);
// define for lcd

#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // Set the LCD I2C address

int buzzer = 8;
int door = 4;
int serratura =7;
//millis door

unsigned long buttonPushedMillis; // when button was released
unsigned long ledTurnedOnAt; // when led was turned on
unsigned long turnOnDelay = 2500; // wait to turn on LED
unsigned long turnOffDelay = 5000; // turn off LED after this time
unsigned long previousMillis = 0;
unsigned long start_time_door;
unsigned long stop_time_door;
const unsigned long tempo_door = 5000;
bool door_time= false;
bool door_state = false;
bool consenso=false;
int serratura_state = LOW;
void setup() {
 
  
    myKeypad.begin( );
       // setup nfc
       Serial.begin(9600); 
       while (!Serial);  
       SPI.begin();      
    mfrc522.PCD_Init(); 

     FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
      FastLED.setBrightness(50);
       FastLED.clear ();
        FastLED.show();

  // setup keypad (assumed serial began)
     keys[4] = 0;
  // setup lcd
     lcd.begin(16,2);
  // setup PIN
     pinMode(buzzer, OUTPUT);
     pinMode(door, INPUT);
     pinMode (serratura, OUTPUT);
}

void loop() 
{ door_state=digitalRead(door);
   if (digitalRead(door)==HIGH)
     {   //Serial.println(fc_door, DEC);
      leds[0]=CRGB(0,255,0);   //porta
      FastLED.show();  
      door_state= true;       
     }else {  
            leds[0]=CRGB(255,0,0);
             FastLED.show();  
            door_state=false;
           }
            
  init_lcd();
  scan_new_card();
  //key_in_password();
}

void scan_new_card() 
{
  if  (state != SCAN_TAG) 
    {
     return;  
    }
  if  ( ! mfrc522.PICC_IsNewCardPresent()) 
    {
     return;
    }
  if  ( ! mfrc522.PICC_ReadCardSerial()) 
    {
     return;
    }
  mfrc522.PICC_HaltA();
 tone(buzzer, 1500, 100);
  delay(50);
  tone(buzzer, 3000, 60);  
  dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
 // Serial.print(F(" ("));
 // Serial.print(mfrc522.uid.size, DEC);
 // Serial.println(F(")"));

  n = indexOf(mfrc522.uid.uidByte, mfrc522.uid.size);
  
  if  ( n != NOT_FOUND) 
    {
     Serial.print(" Ciao  ");
     Serial.println(name[n]);
      //show_user(name[n]);
       time = millis();
    //Serial.println(time);
     //state = KEY_IN_PASSWORD;
     open_door();
     //state = INIT_LCD;
    } else {
            user_not_found();
            state = INIT_LCD;
           }
}

void dump_byte_array(byte *buffer, byte bufferSize) 
{
 for  (byte i = 0; i < bufferSize; i++) 
    {
      //Serial.print(buffer[i] < 0x10 ? " 0" : " ");
      // Serial.print(buffer[i], HEX);
  }
}

int indexOf(byte *buffer, byte bufferSize) 
{
 if  (CARD_SIZE == bufferSize) 
   {
    for (byte i = 0; i < NR_KNOWN_CARDS; i++) 
       {
        byte j;
        for (j = 0; j < CARD_SIZE; j++) 
           {
            if (buffer[j] != knownCards[i][j]) break;
           }
        if (j == CARD_SIZE) return i;
       }
  }
   return NOT_FOUND;
}

/*void key_in_password() 
{
 if  (state != KEY_IN_PASSWORD) 
   {
    return;  
   }
 char customKey = myKeypad.getKey();
   if  (customKey)
     {
      // Serial.println(customKey);
      keys[count] = customKey;
      count++;
   if  (count == 4) 
     {
      //Serial.println(keys);
      if (strcmp(keys, password[n]) == 0) 
        {
         open_door();
      
         
         
         state = INIT_LCD;
        }
         count = 0;
     }
     }
  if  (millis() - time > 10000)     // exceed 10 seconds ?
    {  
     state = INIT_LCD;
    }
}*/

void init_lcd() 
{
  if  (state != INIT_LCD) 
    {
     return;
    }
     lcd.clear();
 for (int i = 0; i< 3; i++)
    {
     lcd.backlight();
     delay(250);
     lcd.noBacklight();
     delay(250);
    }
     lcd.backlight();
     lcd.setCursor(0,0);
     lcd.print("Hallo World!");
     Serial.println("Hallo World!   ");
     lcd.setCursor(0,1);
     lcd.print("Tag a NFC card"); 
     Serial.print("Ready....  ");
     Serial.println("Cod or Card?  ");
     state = SCAN_TAG;
}

void user_not_found() 
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("User not found!");
  Serial.print("Utente non presente  ");
  Serial.println("Error  ");
  toggle_led();
  //delay(3000);
}

void show_user(char name[10]) 
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Hi ");
 // Serial.print("Ciao  ");
 // Serial.println("name  ");
  lcd.print(name);
  lcd.setCursor(0,1);
  lcd.print("Key in your PIN");
  Serial.println("Il tuo pin prego...  ");
}

void toggle_led() 
{ 
   lcd.clear ();
                 lcd.setCursor ( 0, 0 );
                 lcd.print ( "ID NON VALIDO"  );
                     Serial.println ( "ID NON VALIDO" );
   
   unsigned long previousMillis = millis();
    while(millis() - previousMillis < 5000)
    {
     leds[4].setRGB(0,0,0);  //white
     leds[3].setRGB(255,64,0); //orange
          FastLED.show();
            delay(50);
     leds[4].setRGB(255,255,255);  //white
     leds[3].setRGB(0,0,0); //red
          FastLED.show();
          delay(50);
    leds[4].setRGB(0,0,0);  //white
     FastLED.show();
    }   
}
void open_door() 
{     
  Serial.print( " dentro");

 unsigned long currentMillis = millis();

  if ( currentMillis - previousMillis >= tempo_door) {
    // save the last time you blinked the LED
   // 

    // if the LED is off turn it on and vice-versa:
    if (serratura_state == LOW) {
      serratura_state = HIGH;
    } else {
     serratura_state = LOW;
    
     previousMillis = currentMillis;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(serratura, serratura_state);
    state = INIT_LCD;
  }
}

 

Modificato: da kemosabe
Link al commento
Condividi su altri siti

Cosa non ti funziona?

 

Come ti ha già detto, il problema si deve spezzare in tanti piccoli problemi. Si mettono a punto e poi, uno alla volta si integrano nell'applicazione generale.

 

Contino a ripeterti.

1 ora fa, Livio Orsini ha scritto:

A parte questo, tu avevi scritto

 

18 ore fa, kemosabe ha scritto:

spiegami perchè se il blink lo metto nel loop funziona, se invece è in una funzione esterna chiamata dal loop no.

cosa cambia ?????

 

Metti il codice di programmino che non va, compreso il codice che lo richiama, che vediamo il perchè non funziona.

 

Cominciamo a risolvere il problema elementare.

Link al commento
Condividi su altri siti

Scusa, ma te l'ho scritto 3 0 4 volte quale è il problema!!!!!

Evidentemente scrivo in un'altra lingua.

non ti preoccupare, prima o poi lo risolverò.

Grazie Ciao

Link al commento
Condividi su altri siti

  • 3 weeks later...
Il 21/2/2020 alle 23:24 , kemosabe ha scritto:

 

spiegami perchè se il blink lo metto nel loop funziona, se invece è in una funzione esterna chiamata dal loop no.

cosa cambia ?????

 

Ciao kemosabe, probabilmente visto il tempo passato hai già risolto il tuo problema.  Se così non fosse vorrei farti un esempio di BlinkWithoutDelay funzionante col codice inserito in una funzione chiamata dal loop:

 

const int ledPin =  LED_BUILTIN;    // the number of the LED pin
int ledState = LOW;                 // ledState used to set the LED
unsigned long previousMillis = 0;   // will store last time LED was updated
const long interval = 1000;         // interval at which to blink (milliseconds)

void setup() {
  pinMode(ledPin, OUTPUT);
}

 

void Controllo(){
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  } 
}

 

void loop() {
  Controllo();
}

 

 

Questo codice funziona perché il loop continua a chiamare la funzione e quindi il codice inserito in questa viene continuamente eseguito come se fosse stato inserito direttamente nel loop.

Per quanto riguarda il tuo codice, da quanto ho capito nella tua descrizione del problema, tu pensi che chiamando la funzione open_door() il codice all'interno di questa venga continuamente eseguito fino al verificarsi della condizione :

currentMillis - previousMillis >= tempo_door

Non è così.  Il codice all'interno della funzione, non essendoci cicli, viene eseguito una sola volta quando la funzione viene chiamata e se in quella occasione il codice:

 

if ( currentMillis - previousMillis >= tempo_door) 

non è verificato le istruzioni che seguino l'"if" non vengono eseguite.

Dovresti quindi modificare il tuo programma in modo che la funzione open_door() venga chiamata più spesso oppure trasformare l'"if" in un "while" e il >= in <. Questa seconda soluzione vanificherebbe però l'utilizzo di millis() in quanto durante l'attesa della fine del ciclo il micro non potrebbe far altro.

Link al commento
Condividi su altri siti

Ospite
Questa discussione è chiusa alle risposte.
×
×
  • Crea nuovo/a...