Codice non funzionante, attachinterrupt

Salve, ho un problema con un codice, premetto che programmo in vb.net e con il c non mi ci trovo tanto, la parte logica c'è ma i codici scritti fino ad adesso non funzionano

#define DEBOUNCE_DELAY 300
#define TOGGLE_PIN 1
#define PATTERN_INDEX_MAX 2
#define LED_PIN 13

int patternIndex = 0;
bool patternToggled = true;
unsigned long lastDebounceTime;

void setup()
{
    Serial.begin(9600);
    attachInterrupt(TOGGLE_PIN, togglePattern, FALLING);
    pinMode(LED_PIN, OUTPUT);
  }

void loop()
{
  switch (patternIndex)
  {
  case 0:
    simple;
    break;
  case 1:
    simple1;
    break;
  default:
    simple;
    break;
  }
  if (patternToggled) {
    patternToggled = false;
  }
}

void togglePattern() {
  if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY)
  {                                               
    lastDebounceTime = millis();
        patternIndex++;
        Serial.print(patternIndex);
    if (patternIndex > PATTERN_INDEX_MAX)
    {
      patternIndex = 0;
      Serial.print("0");
    }
    patternToggled = true;
  }
}

void  simple()
{
  if (patternToggled)
  {
    exit;
  }
    digitalWrite(LED_PIN, HIGH);
    delay(1000);
    digitalWrite(LED_PIN, LOW);
    if (patternToggled)
    {
      exit;
    }
    delay(1000);
  Serial.print("Simple");
}

void  simple1()
{
  • In pratica il loop dovrebbe scegliere l'effetto da riprodurre
  • In base al valore lo riproduce
  • Da quello che ho capito attachinterrupt dovrebbe riuscire a leggere un cambiamento di stato (tipo multithread)
  • attachinterrupt vede il cambiamento, aumenta il contatore e imposta la variabile boolean
  • mentre viene eseguito l'effetto controllo se il la variabile boolean è cambiata
  • se è cambiata dovrebbe interrompere l'effetto e dovrebbe ripartire il loop con lo switch che cambia l'effetto

Grazie a tutti

Innanzitutto, che scheda stai usando? Se una Uno, gli interrupt sono disponibili solo sui pin 2 e 3, e corrispondono rispettivamente agli interrupt 0 e 1. Per evitare confusione, dovresti usare la funzione digitalPinToInterrupt().

Per maggiori info, vedi qua: https://www.arduino.cc/en/Reference/AttachInterrupt.

Secondo: per chiamare una funzione, devi sempre specificare gli argomenti da passarle tra parentesi, dopo il suo nome. Se la funzione è void devi comunque mettere le parentesi, ovvero: simple();.

Manca comunque parte del codice.

SukkoPera:
Innanzitutto, che scheda stai usando? Se una Uno, gli interrupt sono disponibili solo sui pin 2 e 3, e corrispondono rispettivamente agli interrupt 0 e 1. Per evitare confusione, dovresti usare la funzione digitalPinToInterrupt().

Per maggiori info, vedi qua: attachInterrupt() - Arduino Reference.

Secondo: per chiamare una funzione, devi sempre specificare gli argomenti da passarle tra parentesi, dopo il suo nome. Se la funzione è void devi comunque mettere le parentesi, ovvero: simple();.

si uso un arduino uno, il pin assegnato è il 2, per le parentesi non sono ancora abituato purtroppo

Codice

#define DEBOUNCE_DELAY 300
#define TOGGLE_PIN 2
#define PATTERN_INDEX_MAX 2
#define LED_PIN 13

int patternIndex = 0;
bool patternToggled = true;
unsigned long lastDebounceTime;

void setup()
{
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(TOGGLE_PIN) , togglePattern, FALLING);
  pinMode(LED_PIN, OUTPUT);
}

void loop()
{
  switch (patternIndex)
  {
    case 0:
      simple();
      break;
    case 1:
      simple1();
      break;
    case 2:
      simple2();
      break;
    default:
      simple();
      break;
  }
  if (patternToggled) {
    patternToggled = false;
  }
}

void togglePattern() {
  if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY)
  {
    lastDebounceTime = millis();
    patternIndex++;
    if (patternIndex > PATTERN_INDEX_MAX)
    {
      patternIndex = 0;
    }
    patternToggled = true;
  }
}

void  simple()
{
  if (patternToggled)
  {
    exit;
  }
  digitalWrite(LED_PIN, HIGH);
  delay(1000);
  digitalWrite(LED_PIN, LOW);
  if (patternToggled)
  {
    exit;
  }
  delay(1000);
}

void  simple1()
{
  if (patternToggled)
  {
    exit;
  }
  digitalWrite(LED_PIN, HIGH);
  delay(500);
  if (patternToggled)
  {
    exit;
  }
  digitalWrite(LED_PIN, LOW);
  delay(500);
}

void  simple2()
{
  if (patternToggled)
  {
    exit;
  }
  digitalWrite(LED_PIN, HIGH);
  delay(100);
  if (patternToggled)
  {
    exit;
  }
  digitalWrite(LED_PIN, LOW);
  delay(100);
}

As_Needed:
Manca comunque parte del codice.

Il codice che ho scritto è tutto qui, che parte dovrebbe mancare?

Grazie a tutti e due per l'aiuto che mi state dando

Edit: ho testato il tutto con il codice che ho inserito sopra e funziona perfettamente, se avete dei consigli magari per "pulire" un po' il codice ed eliminare o rendere più leggibile in qualche modo:

if (patternToggled)
  {
    exit;
  }

miky94x:
Il codice che ho scritto è tutto qui, che parte dovrebbe mancare?

Adesso è tutto :wink: Rivedi il primo post e noterai che non è completo. Comunque tutta quella roba nell'ISR non è tanto consigliata, meglio usare una flag. Almeno io comunque non ho capito benissimo cosa è che adesso non ti funziona.

Cosa vorrebbe fare quella exit?

As_Needed:
Adesso è tutto :wink: Rivedi il primo post e noterai che non è completo. Comunque tutta quella roba nell'ISR non è tanto consigliata, meglio usare una flag. Almeno io comunque non ho capito benissimo cosa è che adesso non ti funziona.

Si scusami non avevo visto :smiley:
Adesso mi funziona tutto benissimo, chiedevo semplicemente se c'erano altri modi più "eleganti" per uscire da una funzione

SukkoPera:
Cosa vorrebbe fare quella exit?

Non serve?
in vb.net se si vuole uscire da tipo un FOR bisogna scrivere exit for, usando visual studio come IDE mi dava exit e inserendolo non mi dava problemi, come si esce da una funzione in modo giusto?

Quello che cerchi in C è il break, lo stesso che hai usato nel case, dove svolge esattamente quella funzione ;).

Però break esce da un ciclo, non da una funzione. Per quello ci vuole return, ma credo che questo tu lo sappia e abbia solo sbagliato termine.

SukkoPera:
Quello che cerchi in C è il break, lo stesso che hai usato nel case, dove svolge esattamente quella funzione ;).

Però break esce da un ciclo, non da una funzione. Per quello ci vuole return, ma credo che questo tu lo sappia è abbia solo sbagliato termine.

si scusami ma sono fuso xD
Devo ancora farmi gli occhi con il C e alcune cose faccio fatica a leggerle non sapendo la sintassi corretta :smiley:
Grazie davvero a tutti per l'aiuto e scusate per il disturbo, spero possa servire anche ad altri :slight_smile:

:wink: Beh comunque riguardo alla flag, è semplicemente mettere una variabile che cambia stato da 0 a 1 nell'interrupt e poi nel loop con un if, controlli se quella variabile ad esempio è diventata 1 e se lo è, fai tutto quello che adesso fai nell'interrupt in quell'if e riporti la variabile allo stato precedente di prima che avvenisse l'interrupt. :wink: In questo modo fai perdere il meno tempo possibile al micro, anche se comunque non utilizzi digitalWrite, è più pulito fare così.
Ciao!

EDIT:

Esempio:

dichiari:

byte flag = 0;

Questo è il tuo interrupt:

void togglePattern() {
flag=1;
}

e nel loop metti un if

if (flag==1){
flag=0;
  if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY)
  {
    lastDebounceTime = millis();
    patternIndex++;
    if (patternIndex > PATTERN_INDEX_MAX)
    {
      patternIndex = 0;
    }
    patternToggled = true;
  }
}

le variabili globali usate all'interno dell'interrupt e all'estero di esso vanno dichiarate cone volatile

Dichiaro flag volatile

volatile byte flag = 0;

e metto a posto il codice come mi avete detto

Grazie a tutti

vbextreme:
le variabili globali usate all'interno dell'interrupt e all'estero di esso vanno dichiarate cone volatile

Si è vero!! Scusate, distrazione notturna.