Condizione temporale con lettura analogica

Salve a tutti, questo il mio quesito:
E’ possibile creare tante condizioni con if che si devono verificare una dopo l’altra con una sequenza prestabilita? a>b per 1 secondo e dopo a<b per 1/2 secondo e dopo a>b per 1 secondo e cosi via per
un tempo di 5 secondo con 10 lettura (una ogni 1/2 secondo).

tipo questo esempio: che mi torna errore ovviamente

if (analogRead >= 5 && ((millis() - time) > 1000)) and (analogRead <= 1 && ((millis() - time) > 500)) and (analogRead >= 5 && ((millis() - time) > 1000)) and (analogRead <= 1 && ((millis() - time) > 500));
{ digitalWrite(7, HIGH);
  delay (1000);
  digitalWrite(7, LOW);
}

Posta il codice di test completo perché non capisco se analogRead specificato nella if è una variabile o nelle tue intenzioni fosse una chiamata a funzione analogRead(pin).

Comunque non mi tornano neanche i 5 secondi, cioè

a>b 1 secondo 1.0 secondi
a<b 1/2 secondo 1.5 secondi
a>b 1 secondo 2.5 secondi
a<b 1/2 secondo 3.0 secondi
a>b 1 secondo 4.0 secondi
a<b 1/2 secondo 4.5 secondi
a>b 1 secondo 5.5 secondi
a<b 1/2 secondo 6.0 secondi

Devi anche chiarire alcune condizioni che si possono verificare e cosa fare in tal caso, ma questo lo si vede in seguito.

Ciao.

Sinceramente non capisco cosa vuoi fare, vuoi comandare le uscite con una sequenza prestabilita o leggere dei valori di analogica?

Ti consiglio di riformulare il tuo quesito ponendo attenzione su come usi le proposizioni "e" ed "o", e al verbo "dovere" specificando cosa deve fare e quando.

@maurotec: 6 secodi vanno bene (era un esempio non ho fatto i calcoli precisi)

@brazoayeye: voglio leggere dei valori di analogica

ma la domanda principale è se è possibile (e come) far si che si debbano verificare una sequenza prestabilita di (10 letture valori per un tot di tempo) come nel codice postato (errori di sintassi a parte) ma che comunque sia possibile, o devo ragionare diversamente -....

@maurotec: 6 secodi vanno bene (era un esempio non ho fatto i calcoli precisi)

@brazoayeye: voglio leggere dei valori di analogica

ma la domanda principale è se è possibile (e come) far si che si debbano verificare una sequenza prestabilita di (10 letture valori per un tot di tempo) come nel codice postato (errori di sintassi a parte) ma che comunque sia possibile, o devo ragionare diversamente -....

Certo che è possibile!
Se pensi che un programma viene eseguito diverse migliaia di volte al secondo, certo che puoi fare questo tipo di verifica.
In fondo la lettura della seriale oppure la lettura del bus I2C cosa sono?

@steve-cr grazie della risposta…
e quindi in che modo dovrei ragionare?
qual’è la soluzione per dire ad arduino che (ad esempio deve accendere il led) solo quando:
a>b per millis(1000) e poi subito dopo a>b per millis(500) e poi dopo a>b per millis (1000) e cosi via…
e quindi sal e scende per una succesione di 6 eventi consecutivi?
non riesco a trovare esempio simile o funzione adatta…

Hm, si, è possibile tutto, ma intanto vedo nel tuo codice che non hai ben presente neanche cosa sia una funzione, visto che chiami "analogRead" senza passargli nessun parametro per cui temo che sia il caso di iniziare per gradi facendo qualche esperimento ad esempio far accendere alternativamente due LED.

In ogni caso quello che dici si può sicuramente fare, ma come implementare la logica che scrivi dipende molto da cosa intendi fare, e se ci posti solo uno spezzone non possiamo fare molto, temo..

Nel frattempo sappi che per leggere un valore da un pin analogico, esempio A0, devi dire "analogRead(A0)" non solo "analogRead", quindi correggi il programma e poi posta qui l'INTERO listato che stai usando per le tue prove, e vediamo.

@docdoc grazie per la risposta…
si è vero che non sono un vero esperto, lo ammetto, ma in quanto a logica e ragionamento sono abbastanza intuitivo… questo è quello che sono riuscito a fare fin ora e cioè:
lista materiali:

  • arduino uno
  • sensore cjmcu-ms5540c (come sensore di profondità in acqua)
  • sensore giroscopio gy-521
  • modulo irf520n
  • soleinode elettromagnete 12v
  • batteria 12v
    e quindi devo leggere i valori di entrambi i sensori per far attivare il rele e quindi il soleinode…
    sono riuscito fin ora a far si che quando (sia il giroscopio che il sensore di profondità) superi
    una certa soglia (che sia -10 per giroscopio che sia 12200 per sensore profondità) per un tempo di 5 secondi
    attiva il rele/soleinode.
    ecco il codice perfettamente funzionante (accetto qualuque modifica relativa a semplificare o cos’altro.)
#include <SPI.h>
#include <Wire.h>
#define MPU 0x68  // I2C address of the MPU-6050

double AcX,AcY,AcZ;
int Roll = 0;
int clock = 9;
int valvola = 7;
unsigned long time;
unsigned long time2;
boolean flag1 = false;
boolean flag2 = false;
void resetsensor() //this function keeps the sketch a little shorter


{
SPI.setDataMode(SPI_MODE0);
SPI.transfer(0x15);
SPI.transfer(0x55);
SPI.transfer(0x40);
}
void setup() {
Serial.begin(9600);
init_MPU(); // Inizializzazione MPU6050
SPI.begin(); //see SPI library details on arduino.cc for details
SPI.setBitOrder(MSBFIRST);
SPI.setClockDivider(SPI_CLOCK_DIV32); //divide 16 MHz to communicate on 500 kHz
pinMode(clock, OUTPUT);
pinMode (7, OUTPUT);
delay(1000);
}

void init_MPU(){
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  delay(1000);
}
 
//Funzione per il calcolo degli angoli Pitch e Roll
double FunctionsPitchRoll(double A, double B, double C){
  double DatoA, DatoB, Value;
  DatoA = A;
  DatoB = (B*B) + (C*C);
  DatoB = sqrt(DatoB);
  
  Value = atan2(DatoA, DatoB);
  Value = Value * 180/3.14;
  
  return (int)Value;
}
 
//Funzione per l'acquisizione degli assi X,Y,Z del MPU6050
void FunctionsMPU(){
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU,6,true);  // request a total of 14 registers
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)     
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
}

void loop()
{
  FunctionsMPU(); // Acquisisco assi AcX, AcY, AcZ.
    
  Roll = FunctionsPitchRoll(AcX, AcY, AcZ);   //Calcolo angolo Roll
 
  int ValvolaRoll = map(Roll, -90, 90, 0, 179);
  
TCCR1B = (TCCR1B & 0xF8) | 1 ; //generates the MCKL signal
analogWrite (clock, 128) ;
resetsensor();//resets the sensor - caution: afterwards mode = SPI_MODE0!
//Calibration word 1
unsigned int word1 = 0;
unsigned int word11 = 0;
SPI.transfer(0x1D); //send first byte of command to get calibration word 1
SPI.transfer(0x50); //send second byte of command to get calibration word 1
SPI.setDataMode(SPI_MODE1); //change mode in order to listen
word1 = SPI.transfer(0x00); //send dummy byte to read first byte of word
word1 = word1 << 8; //shift returned byte
word11 = SPI.transfer(0x00); //send dummy byte to read second byte of word
word1 = word1 | word11; //combine first and second byte of word
resetsensor();//resets the sensor
//Calibration word 2; see comments on calibration word 1
unsigned int word2 = 0;
byte word22 = 0;
SPI.transfer(0x1D);
SPI.transfer(0x60);
SPI.setDataMode(SPI_MODE1);
word2 = SPI.transfer(0x00);
word2 = word2 <<8;
word22 = SPI.transfer(0x00);
word2 = word2 | word22;
resetsensor();//resets the sensor
//Calibration word 3; see comments on calibration word 1
unsigned int word3 = 0;
byte word33 = 0;
SPI.transfer(0x1D);
SPI.transfer(0x90);
SPI.setDataMode(SPI_MODE1);
word3 = SPI.transfer(0x00);
word3 = word3 <<8;
word33 = SPI.transfer(0x00);
word3 = word3 | word33;
resetsensor();//resets the sensor
//Calibration word 4; see comments on calibration word 1
unsigned int word4 = 0;
byte word44 = 0;
SPI.transfer(0x1D);
SPI.transfer(0xA0);
SPI.setDataMode(SPI_MODE1);
word4 = SPI.transfer(0x00);
word4 = word4 <<8;
word44 = SPI.transfer(0x00);
word4 = word4 | word44;
long c1 = word1 << 1;
long c2 = ((word3 & 0x3F) >> 6) | ((word4 & 0x3F));
long c3 = (word4 << 6) ;
long c4 = (word3 << 6);
long c5 = (word2 << 6) | ((word1 & 0x1) >> 10);
long c6 = word2 & 0x3F;
resetsensor();//resets the sensor
//Temperature:
unsigned int tempMSB = 0; //first byte of value
unsigned int tempLSB = 0; //last byte of value
unsigned int D2 = 0;
SPI.transfer(0x0F); //send first byte of command to get temperature value
SPI.transfer(0x20); //send second byte of command to get temperature value
delay(35); //wait for conversion end
SPI.setDataMode(SPI_MODE1); //change mode in order to listen
tempMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
tempMSB = tempMSB << 8; //shift first byte
tempLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
D2 = tempMSB | tempLSB; //combine first and second byte of value
resetsensor();//resets the sensor
//Pressure:
unsigned int presMSB = 0; //first byte of value
unsigned int presLSB =0; //last byte of value
unsigned int D1 = 0;
SPI.transfer(0x0F); //send first byte of command to get pressure value
SPI.transfer(0x40); //send second byte of command to get pressure value
delay(35); //wait for conversion end
SPI.setDataMode(SPI_MODE1); //change mode in order to listen
presMSB = SPI.transfer(0x00); //send dummy byte to read first byte of value
presMSB = presMSB << 8; //shift first byte
presLSB = SPI.transfer(0x00); //send dummy byte to read second byte of value
D1 = presMSB | presLSB;
const long UT1 = (c5 * 8) + 20224;
const long dT =(D2 - UT1);
const long TEMP = 200 + ((dT * (c6 + 50))/1024);
const long OFF = (c2*4) + (((c4 - 512) * dT)/4096);
const long SENS = c1 + ((c3 * dT)/1024) + 24576;
long PCOMP = ((((SENS * (D1 - 7168))/16384)- OFF)/32)+250;
float TEMPREAL = TEMP/10;
Serial.print("pressure = ");
Serial.print(PCOMP);
Serial.println(" mbar");
const long dT2 = dT - ((dT >> 7 * dT >> 7) >> 3);
const float TEMPCOMP = (200 + (dT2*(c6+100) >>11))/10;
Serial.print("Roll: "); Serial.print(Roll);
Serial.print("\n");
delay(1000);


if (Roll > -10)
 {flag2 = false;}
if (flag2==false)
{flag2=true;
time2 = millis();
}
if (flag2==true && ((millis() - time2) > 5000))
{ digitalWrite (7, HIGH);
delay (1000);
digitalWrite (7, LOW);
}

if (PCOMP < 12000)
 {flag1 = false;}
if (flag1==false)
{flag1=true;
time = millis();
}
if (flag1==true && ((millis() - time) > 5000))
{ digitalWrite(7, HIGH);
  delay (1000);
  digitalWrite(7, LOW);
}
}

ora devo modificare la parte finale.
per il sensore di profondità, oltre a superare la soglia x del valore per 5 secondi
voglio aggiungere come ho descritto nel post precedente:

a>b per millis(1000) e poi subito dopo a>b per millis(500) e poi dopo a>b per millis (1000) e cosi via…
e quindi sale e scende per una succesione di 6 eventi consecutivi?
accende rele/soleinode

in attesa vs commeti e/o soluzioni
grazie

Ok qui di seguito una macchina a stati che può aiutarti anche a rivedere il tuo sketch al fine di rimuovere i delay(n).

boolean oneShotSwitch;
uint32_t elapsedTime;
uint32_t mainTimer;
uint32_t sec5Timer;

byte currentState = 0;
byte oldState = ~currentState;
uint16_t adcValue = 0;
const byte adcChannel = 0;
byte counter = 0;
byte letture = 10;


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}
// a>b 1 secondo    1.0 secondi
// a<b 1/2 secondo  1.5 secondi
// a>b 1 secondo    2.5 secondi
// a<b 1/2 secondo  3.0 secondi
// a>b 1 secondo    4.0 secondi
// a<b 1/2 secondo  4.5 secondi
// a>b 1 secondo    5.5 secondi
// a>b 1/2 secondo  6.0 secondi
void loop() {
  // put your main code here, to run repeatedly:
  oneShotSwitch = false;
  if (currentState != oldState) {
    oneShotSwitch = true;
    mainTimer = millis();
    counter = 0;
  }
  oldState = currentState;
  elapsedTime = millis() - mainTimer;
  adcValue = analogRead(adcChannel);

  switch (currentState) {
    case 0:
      if (oneShotSwitch) {
        // se oneShotSwitch == true stampa "case 1"
        Serial.println("case 0");
      }
      if (letture == 10)
        sec5Timer = millis();
      if (elapsedTime >= 10) {
        adcValue = 6;               // occhio, usato solo per il test 
        if (adcValue >= 5) {
          counter++;
          if (counter >= 100) {
            currentState = 1;
            letture--;
          }
        }
      }
      break;
    case 1:
      if (oneShotSwitch) {
        // se oneShotSwitch == true stampa "case 1"
        Serial.println("case 1");
      }
      if (elapsedTime >= 10) {
        adcValue = 0;            // occhio, usato solo per il test 
        if (adcValue <= 1) {
          counter++;
          if (counter >= 50) {
            currentState = 0;
            letture--;

          }
        }
      }
      break;

  }
  if (letture == 0 && sec5Timer >= 5000) {
    Serial.println("ok");
    currentState = 2;
    letture = 10;
  }
}

Ogni 10 millesimi di secondo fa il test:

 if (elapsedTime >= 10) {

Sulla implementazione della macchina a stati puoi leggere questo topic:https://forum.arduino.cc/index.php?topic=642978.0

Ciao.

Io dopo 10 post non ho ancora capito come deve essere questa sequenza, si parla di 6 eventi, di 10 letture, di letture ogni mezzo secondo....

Prima di continuare con qualsiasi ipotesi è meglio chiarire una volta per tutte come è fatta questa sequenza, ma non a parole che ciascuno capisce qualcosa di diverso...

La sequenza è questa (tre impulsi alti)?[ ]si  [ ]no

       1s      1s      1s
a>b    .----.  .----.  .----.
       |    |  |    |  |    |
-------'    '--'    '--'    '-----------
            0.5s    0.5s    0.5s

La durata delle parti alte e basse e`fissa o ha un margine di variazione?

[ ] fissa  [ ] alto varia da/a ....   [ ] basso varia da/a .....

@maurotec grazie mi studio il tuo codice e ti aggiorno, per ora grazie…
una sola domanda stabilisci 10 letture
però se si verifica la sequenza dopo 5 secondi
e quindi tutte le 8 letture vere
la condizione si è verificata? giusto
il ragionamento è questo?

@Claudio_FF la sequenza è giusta nel senso che il periodo di tempo di lettura lo decido in seguito
ed anche il numero di letture è irrilevante…
a me serviva la tipologia di codice per cui si verificasse una sequenza di condizioni una dietro l’altra
per un determinato tempo di lettura, che potrà essere 5 10 o 20 secondi

SABATINOCC:
a me serviva la tipologia di codice per cui si verificasse una sequenza di condizioni una dietro l’altra

Quindi astrattamente: a ogni condizione verificata modifichi il valore di una variabile di fase (diciamo avanti di uno). A ogni condizione non verificata la riporti all’inizio. Il riconoscimento della sequenza avviene quando la variabile di fase ha raggiunto il valore opportuno.

Chiaro che il riconoscimento di uno step intermedio dipende dal fatto di aver già riconosciuto quelli prima, ma questo è semplice perché la variabile di fase ci serve appunto per sapere a che punto siamo arrivati.

ora vorrei capire se posso usare i valori letti direttamente dal serial monitor oppure no

La condizioni si verifica qui:

if (letture == 0 && sec5Timer >= 5000) {
   // Per smettere di eseguire i due case devo per forza impostare 
   // currentState ad un valore diverso da 0 e 1.
   // ricarico il contatore di letture a 10.
   // qui il tuo digitalWrite(pin, HIGH) al posto di questo ci ho messo 
   // Serial.println("ok");
}

Quindi la logica è che se i due case 0 e 1 portano lettura == 0 entro 5 secondi si verifica la condizione.

Probabilmente ti serve un altro case in funzione di trigger, come dire adcValue == 0 per 3 secondi poi passa è sta in attesa che adcValue >=5 per la prima volta, salva il timer ecc.

ora vorrei capire se posso usare i valori letti direttamente dal serial monitor oppure no

Non ti seguo, letti direttamente.. ma chi li invia? Booh, se hai possibilità di creare un programma sul pc che invia 5 ogni 10ms per 1 secondi, poi 0 per 1/2 ecc, puoi testare il codice che ti postato semplicemente, basta salvare il valore ricevuto da seriale nella variabile adcValue e commentare adcValue = 0 e = 6.

Ciao.