Interrupt e detachInterrupt

Buona giornata ragazzi
sono ancora qui per chiedervi gentilmente un aiuto,
sto provando gli interrupt e mi sembrano OK, poi però voglio che alcune parti del progetto non siano interessate dagli interrupt,
questo e il programma che sto testando

#include <Arduino.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

#define led_v 4
#define led_g 6
#define buton 3
#define buton_1 5
#define buton_2 7
#define sens 2 //interrupt

unsigned long ledTemp;
bool led_1;
int cunter = 0;

byte Stato = 0;
byte StatoLedVerde = 0;
byte UnLamp = 0;

int A = 0;
int B;
int C;

void Led_Verde();
void Led_Gialo();
void mate();
void SENS(); //Funzione per interrupt

LiquidCrystal_I2C lcd(0x3F, 20, 4); //0x27

void setup() {
	Serial.begin(9600);
	lcd.init();
	lcd.backlight(); //per attivare la retro inluminazione
	lcd.home();

	pinMode(led_v, OUTPUT);
	digitalWrite(led_v, 0);
	lcd.setCursor(0, 1);
	lcd.print("Led Spento");

	pinMode(led_g, OUTPUT);
	digitalWrite(led_g, 0);

	pinMode(buton, INPUT_PULLUP);
	pinMode(sens, INPUT_PULLUP);
	pinMode(buton_1, INPUT_PULLUP);
	pinMode(buton_2, INPUT_PULLUP);

	attachInterrupt(digitalPinToInterrupt(2), SENS, FALLING); //interrupt verso massa
	led_1 = false;

	delay(100);
}

void loop() {
	if (digitalRead(buton) == 0) {
		cunter++;
		while (digitalRead(buton) == 0)
			;
	}
	if (cunter > 4) {
		cunter = 0;
	}

//	lcd.setCursor(10, 0);
//	lcd.print("Case0");

	switch (cunter) {
	case 0:
		lcd.setCursor(10, 0);
		lcd.print("Case0");
		lcd.setCursor(0, 2);
		lcd.print("     ");
		lcd.setCursor(0, 3);
		lcd.print("         ");
		break;
	case 1:
		Led_Verde();
		lcd.setCursor(10, 0);
		lcd.print("Case1");
		break;
	case 2:
		Led_Gialo();
//		lcd.setCursor(10, 0);
//		lcd.print("Case2");
		break;
	case 3:
		if (led_1) {
			digitalWrite(led_g, 0);
			lcd.setCursor(0, 1);
			lcd.print("           ");
			lcd.setCursor(0, 0);
			lcd.print("Led Aceso");

			if (millis() - ledTemp > 3000) {
				digitalWrite(led_v, 0);
				led_1 = false;

				lcd.setCursor(0, 0);
				lcd.print("         ");
				lcd.setCursor(0, 1);
				lcd.print("Led Spento ");
			}
		}
		lcd.setCursor(10, 0);
		lcd.print("Case3");
		break;
	case 4:
		mate();
		break;
	}

	delay(100);
} //loop

void Led_Verde() {
	lcd.setCursor(10, 0);
	lcd.print("Case1");

	if (digitalRead(buton_1) == 0 && Stato == 0) {
		digitalWrite(led_g, 0);
		digitalWrite(led_v, 1);
		lcd.setCursor(0, 1);
		lcd.print("           ");
		lcd.setCursor(0, 0);
		lcd.print("Led Aceso");
		while (digitalRead(buton_1) == 0)
			;
		Stato = 1;
	}

	if (digitalRead(buton_1) == 0 && Stato == 1) {
		digitalWrite(led_v, 0);
		lcd.setCursor(0, 0);
		lcd.print("         ");
		lcd.setCursor(0, 1);
		lcd.print("Led Spento ");
		while (digitalRead(buton_1) == 0)
			;
		Stato = 0;
	}
}

void Led_Gialo() {

	lcd.setCursor(10, 0);
	lcd.print("Case2");

	if (UnLamp == 0) {
		digitalWrite(led_v, 1);
		StatoLedVerde++;
		delay(100);
		digitalWrite(led_v, 0);

		if (StatoLedVerde == 5) {
			digitalWrite(led_v, 0);
			digitalWrite(led_g, 1);
			cunter = 3;
		}
	}
	if (StatoLedVerde > 5) {
		StatoLedVerde = 0;

	}
}

void mate() {

	lcd.setCursor(10, 0);
	lcd.print("Case4");
//	digitalWrite(led_v, 0);

	if (digitalRead(buton_2) == 0) {
		A++;
		while (digitalRead(buton_2) == 0)
			;
	}
	if (A > 20) {
		A = 0;
	}
	B = A >> 1; //B assegnto ad A / 2
	C = A << 1; //C assegnato ad A x 2

	lcd.setCursor(0, 2);
	lcd.print("A ");
	lcd.print(A);
	if (A < 10) {
		lcd.setCursor(3, 2);
		lcd.print(" ");
	}

	lcd.setCursor(0, 3);
	lcd.print("B ");
	lcd.print(B);
	if (B < 10) {
		lcd.setCursor(3, 3);
		lcd.print(" ");
	}

	lcd.setCursor(5, 3);
	lcd.print("C ");
	lcd.print(C);
	if (C < 10) {
		lcd.setCursor(8, 3);
		lcd.print(" ");
	}

}

void SENS() {

	digitalWrite(led_v, 1);
	ledTemp = millis();
	led_1 = true;
}

ora io vorrei che la funzione mate() non sia soggetta ad interrupt,

ho provato ad inserire all'inizio della funzione
detachInterrupt(digitalPinToInterrupt(2));

ed attivare gli intrrupt alla fine della funzione
attachInterrupt(digitalPinToInterrupt(2), SENS, FALLING);

(nel programma postato non ci sono gli o tolti perché non vanno)

ma non mi funziona,
cortesemente qualcuno mi può dire dove sbaglio?

Quello che hai dichiarato per disattivare e riattivare gli interrupt dovrebbe fare ciò che desideri, per cui, cosa non ti funziona esattamente?
Ci sono alcune cose che non vanno nell'ISR dell'interrupt, la prima è che la funzione millis non funziona all'interno delle ISR poiché quando sei dentro l'ISR gli interrupt vengono disattivati e quindi millis non può restituirti il valore corretto, la seconda è de tutte le variabili che usi e modifichi sia dentro che fuori le ISR devi dichiararle con la parola chiave volatile

Oltre agli ottimi consigli di fabpolli, mi chedevo anche perché tu stia usando detachInterrupt() per disassociare la ISR e poi attachInterrupt() per rimetterla, invece di usare noInterrupts() che disabilita tutti gli interrupt (non solo quello ma tutti), e quindi interrupts() che li riabilita.

PS poi mettici una "o" alla variabile "cunter" ossia "counter" perché senza la "o" è praticamente uno che ha a che vedere con "cunt", l'organo sessuale femminile... :wink:

Ciao fabpolli grazie di avermi risposto,
chiedo scusa per le poche indicazioni,
ho sistemato la variabile l'ho dichiarata volatile,

forse l'hai intuito però mi spiego meglio,

sul pin D2 (interrupt 0) ho collegato un sensore infrarosso,
nella ISR cera (perché l'ho tolto) un digitalWrite(led_v, 1);
questo mi faceva accendere il led anche quando ero nei case 0, 1, 2, 4,
dove io non volevo che il led si accendesse,

ho risolto spostando il digitalWrite(led_v, 1); dentro l'if del case 3,

ora fa quello che mi aspettavo,

docdoc
sto imparando ad usare gli interrupt,
e volevo disattivare solo quello che mi interessava,

con "cunt", l'organo sessuale femminile

bella questa, sarà fatto

dimenticavo,
per quanto riguarda ledTemp = millis();
all'interno del ISR questa mi sta funzionando,
anche se non sarà precisissima
non saprei dove andare a prendere il tempo,

approfitto della vostra gentilezza per chiedervi alcune info,
io ho questo sensore

https://www.amazon.it/ostacolo-infrarosso-riflessione-fotoelettrico-TE174/dp/B00XXEJD58?ref_=fsclp_pl_dp_12

il quale ha un raggio di azione di circa 10 cm,
mi servirebbe uno che arrivasse almeno 50 cm,

ho cercato ma non riesco a trovare niente,
avete conoscenza di qualcosa che arrivi a 50 cm

mille grazie per il tempo che mi dedichi

milefori:
sto imparando ad usare gli interrupt,
e volevo disattivare solo quello che mi interessava

Ok, comunque se ne hai uno solo (o se vuoi disattivarli tutti, o se non hai bisogno di cambiare ISR associata ad un certo interrupt) in genere io uso noInterrupt()+interrupts() perché più semplice e dovrebbe essere anche più rapida del detach+attach perché si limita a disabilitarli non a rimuoverli e poi ricollegare la ISR.

per quanto riguarda ledTemp = millis();
all'interno del ISR questa mi sta funzionando,
anche se non sarà precisissima
non saprei dove andare a prendere il tempo,

Beh ma non è che non funziona, semplicemente non avanza di valore, quindi non puoi fare due letture anche a distanza di tempo (a parte il fatto che le ISR non dovrebbero mai impiegare molto tempo) perché comunque restituiscono lo stesso numero.

io ho questo sensore
il quale ha un raggio di azione di circa 10 cm,
mi servirebbe uno che arrivasse almeno 50 cm,

Hm, ma esattamente quale range di distanze ti occorrono e con quale precisione, e quali altre caratteristiche (es. l'oggetto da misurare cos'è, come si muove)?

Per dire, per distanze da 4 cm a 4 metri funzionano abbastanza bene pure i sensori ad ultrasuoni.

docdoc

Beh ma non è che non funziona, semplicemente non avanza di valore

a me basta che poi entri nel if per il conteggio dello spegnimento,

per il sensore
mi deve rilevare il passaggio di una persona alla distanza massima 1 m,
non e importante una grande precisione, per il fatto che questo mi serve per poi attivare un relè a stato solido,

milefori:
docdoca me basta che poi entri nel if per il conteggio dello spegnimento

Se la variabile è globale e dichiarata "volatile" come ti hanno suggerito, allora la cosa deve funzionare. Se non funziona c'è altro :wink:

per il sensore mi deve rilevare il passaggio di una persona alla distanza massima 1 m,
non e importante una grande precisione, per il fatto che questo mi serve per poi attivare un relè a stato solido,

Allora direi che gli ultrasuoni vanno più che bene.
Prenditi un HY-SRF05 (non prendere gli HC-SR04, sono molto spesso fallati...) e fai qualche prova. Pensa che io lo uso per determinare il livello di acqua nel serbatoio della macchina espresso (quindi distanze tra 4 e 25 cm...).

Se la variabile è globale e dichiarata "volatile"

OK funziona

mille grazie anche per le info sul sensore,
ora vedo di acquistarne uno e fare delle prove