Je voudrais avoir un bouton et lorsque j'appuie dessus une première fois mon programme se dirige vers un autre void mais lorsque je rappuie dessus alors que je suis dans ce meme void alors mon programme se redirige vers le void principal (loop). Je voudrais faire comme ca:
(les led sont la pour me signifier ou je suis je sais que j'aurais pu faire plus simplement )
Mais je rencontre un problème et je ne sais pas d'ou: lorsque j'essaie j'arrive a passer a jusqu'au void joystick mais j'ai deja une erreur, au lieu de m'afficher:
bouton
state: 0
Il m'affiche uniquement bo et je ne comprends vraiment pas pourquoi.
Puis après si je rappuie sur mon bouton il ne fait plus rien il est stuck dans mon void joystick(), je viens de penser que peut être qu'on ne peut pas utiliser la fonction interruption dans un autre void que le loop? Ou juste j'ai fais une erreur?
Quelqu'un aurait une réponse ou même une solution?
Le traitement dans l'interruption doit être le plus réduit posssible. En particulier tu ne peux pas appeler de Serial.print() ou a fortiori la loop.
Si tu tiens vraiment à utiliser une interruption, il faut positionner un flag dans l'interruption et le tester dans tes fonctions (et non dans tes void car void veut dire vide/invalide)
Les routines d'interruption devraient être minimalistes (elles monopolisent l'UC, au detriment ... d'autres routines d'inetrruption telles que le timer (sans lequel millis(), voire delay() seraient inopérants) et la jonction série...(même en emission: vous emettez beaucoup de caractères dans cette routine...)
Votre routine d'interruption peut très bien avoir une seule fonction, (c'est simple si votre bouton est sans rebonds..):
commuter une variable globale et volatile (state peut très bien être un booleen) (elle fera très peu, mais bien et très vite)
le loop n'aurait alors qu'à appeler, suivant les cas, deux fonctions ....
De plus, souhaitez vous que l'interruption soit déclenchée sur un changement, un passage de bas à haut ou un passage de haut à bas?
Merci, je crois comprendre un peu mais je ne comprends pas le fait qu'il ne faut pas qu'il y est trop d'appel de fonction dans mon void interrupt() car pour moi l'interruption ne fait qu'envoyer le "déroulement du programme" vers ce void non?
J'ai bien compris après que une interruption c'est pas super... Mais je pense que j'en ai besoin car mon code est bien plus long et il met environs 30sec a s'exécuter, c'est pour ça que je pense avoir besoin d'une interruption, elle me servirait a stopper mon programme (dit automatique) pour passer au mode manuel (void joystick).
Et j'ai bien un bouton avec un rebond (un bouton poussoir). Je voudrais que l'interruption soit déclenchée lorsque j'appuie dessus donc sa peut être les trois je pense vu que c'est un bouton poussoir il passe de bas a haut et de haut a bas en soit(?)
LEs rebonds, qui affectent certains boutons poussoirs, ne sont malheureusement pas ce que vous croyez voir: quand on appuie sur ces BP de mauvaise qualité, ils se mettent à rebondir plusieurs centaines de fois par seconde... générant un beau désordre dans les logiciels.
Une interruption bloque dès le départ toutes les interruptions suivantes (et l'envoi de caractères par Serial.print arme une interruption qui fait effectivement la tâche d'impression. Que se passe-t-il si les interruptions sont inhibées?)
Vous auriez interet à décomposer les tâches chronophages en petites étapes assez rapides pour être appelées en séquence (le comportement serait le même qu'avant) , puis une étape après l'autre dans le loop: vous auriez alors un automate assez rapide pour réagir aux sollicitations imprévues du monde externe.
Oui mais je ne peux pas faire ça car mon programme est long et j'ai besoin de pouvoir le passer en mode manuel a n'importe quel moment et de plus mon loop de base fait appel a d'autre void...
Il manque encore des parties que je n'ai pas encore incrémenté.
#include <SharpIR.h>
#include <WiFi.h>
SharpIR sensor( SharpIR::GP2Y0A21YK0F, A0 ) ;
int n = 0 ;
const int ledvert = 4 ;
const int ledorange = 5 ;
const char* ssid = "L'etre parfait" ; // Nom WiFi
const char* password = "oouuaaiiss" ; // Mdp WiFi
// Valeurs pour le serveur Web
const char* host = "api.openweathermap.org" ;
const char* apikey = "1a702a15a2f46e405e61804cf67c0d30" ;
const char* town = "Pamiers,fr" ;
String keyword = String("\"icon\":\"") ; // Chaîne que l'on recherche dans le JSON
const int httpPort = 80 ; // Serveur web attend sur le port 80
bool inBody = false ; // Indique si on est dans l'en-tête HTTP (false) ou dans le contenu de la ressource
// On se place dans le rôle du client en utilisant WifiClient
WiFiClient client ;
void setup() {
// Initialisation du port série
Serial.begin(9600) ;
pinMode(ledvert, OUTPUT) ;
pinMode(ledorange, OUTPUT) ;
// On affiche le wifi sur lequel on veut se connecter
Serial.print("Connexion au WiFi ") ;
Serial.println(ssid) ;
WiFi.begin(ssid, password) ; // On se connecte
while (WiFi.status() != WL_CONNECTED) { // On attend d'être connecté
delay(500) ;
Serial.print(".") ;
}
Serial.println("") ; // On affiche les paramètres
Serial.println("WiFi connecte") ;
Serial.print("Adresse IP du module ESP: ") ;
Serial.println(WiFi.localIP()) ;
Serial.print("Adresse IP ddu point d'accès : ") ;
Serial.println(WiFi.gatewayIP()) ;
// On vérifie que la connexion est ok, sinon on passe en mode erreur
if (!client.connect(host, httpPort)) {
Serial.println("La connexion avec le serveur a échouée.") ;
}
}
void loop() {
digitalWrite(ledvert, LOW) ;
digitalWrite(ledorange, LOW) ;
if(int distance = sensor.getDistance() < 20) {
Serial.print("distance: ") ;
Serial.println(distance) ;
IR() ;
}
digitalWrite(ledvert, HIGH) ;
digitalWrite(ledorange, LOW) ;
Serial.print("connexion au serveur : ") ;
Serial.println(host) ;
// On vérifie que la connexion est ok, sinon on passe en mode erreur
if (!client.connect(host, httpPort)) {
Serial.println("La connexion avec le serveur a échouée.") ;
}
/* La connexion a réussi on forme le chemin
URL complexe composée du chemin et de deux
questions contenant le nom de ville et l'API key */
String url = String("/data/2.5/weather?q=") + town + "&appid=" + apikey ;
Serial.print("demande URL: ") ;
Serial.println(url) ;
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n") ;
// On attend 1 seconde
delay(750) ;
if(int distance = sensor.getDistance() < 20) {
Serial.print("distance: ") ;
Serial.println(distance) ;
IR() ;
}
digitalWrite(ledvert, HIGH) ;
digitalWrite(ledorange, LOW) ;
inBody = false ; // On est dans l'en-tête
// On se préparer à recevoir la chaîne de caractères correspondant à l'icone
String iconString = "" ;
// Réception de message
while(client.available()) {
String line = client.readStringUntil('\r') ;
if (line.length() == 1) inBody = true ; // Passer l'en-tête jusqu'à une ligne vide
if (inBody) {
// Ligne du corps du message, on cherche le mot clé
int pos = line.indexOf(keyword) ;
if (pos > 0) {
// indexOf donne la position du début du mot-clé, en ajoutant sa longueur
// On se place à la fin.
pos += keyword.length() ;
// On ne souhaite garder que les 3 caractères correspondant à l'icône
line[pos+3] = '\0' ;
// On stocke le résultat dans iconString
iconString = &line[pos] ;
}
}
}
Serial.print("Icone : ") ;
Serial.println(iconString) ; // On affiche la valeur de l'icône
if(iconstring == "valeur d'inondation") {
flood() ; // Il n'y a pas de double vérification mais on pourrait très bien vérifier sur d'autres site si les informations se coordonnes
}
if(int distance = sensor.getDistance() < 20) {
Serial.print("distance: ") ;
Serial.println(distance) ;
IR() ;
}
digitalWrite(ledvert, HIGH) ;
digitalWrite(ledorange, LOW) ;
delay(10000) ; // On attend 10 secondes avant la prochaine requête
// Il va falloir que je trouve a quoi correspond l'icone qui m'interesse pour l'exploiter
}
// Fonction 'IR', vérifie que l'eau est bien trop haute et que ce soit pas juste une erreur
void IR() {
digitalWrite(ledvert, LOW) ; // Eteint la led verte qui signale que le niveau d'eau est bon
digitalWrite(ledorange, HIGH) ; // Allume la led orange qui signale la vérification du niveau d'eau
// Vérifie à 4 reprises que le niveau d'eau est trop haut pour annuler les erreurs
while(sensor.getDistance() < 20 || n != 4) {
n = n++ ;
delay(500) ;
}
// Réinitialise n pour les prochaines vérifications du niveau d'eau
// et renvoie a la fonction 'flood' si le niveau de l'eau et bien trop haut après la seconde vérification
if(n == 4) {
n = 0 ; // Réinitialise n pour les prochaines vérification de niveau d'eau
flood() ; // Déclanche la fonction 'flood' ci-dessous
}
delay(500) ; // on attend 0.5s avant la reprise de la fonction 'loop' pour reposer la petite carte
}
// Fonction 'flood', elle déclanche le système de levage
void flood() {
digitalWrite(ledorange, millis() / 500 % 2) ; // Fait clignoter la led orange pour signaler aux utilisateurs que le système va protéger la maison d'une inondation via le système de levage
digitalWrite ;
digitalWrite ;
digitalWrite ;
digitalWrite ;
delay() ;
digitalWrite ;
digitalWrite ;
digitalWrite ;
digitalWrite ;
delay() ;
if(sensor.getDistance() < 20) {
IR() ;
}
}
if( !avoidBurstRead ) while( millis() <= lastTime + 20 ) {} //wait for sensor's sampling time
si getDistance est appelé sans mode burst depuis une interruption (quand on est dans une interruption, toutes les autres interruptions sont inhibées: en particulier les interruptions du timer, qui gère le comptage des millisecondes....) vous pouvez générer des délais infinis.... Ce n'est pas une structure viable...
Edité: j'ai fait 2 hypothèses, a) que ma mémoire ne flanche pas, b) que vous avez un avr (sinon, je ne sais pas: même sur PC, ils recommandent des interruptions très courtes...)
Edité encore:
vous faites appel à delay() à tour de bras (un millis() bloquant). Comme millis() a de forte chances, une fois rentré dans une interruption, de ne pas évoluer, vous allez générer des délais .... infinis..
Si j'ai bien compris c'est si getDistance est appelé par une interruption hors dans mon cas je n'ai pas ce problème car si interruption il y a alors cette fonction ne sera pas appelé (mode burst?)
D'accord donc les delay il faut en utiliser très peu c'est bien ça? Le problème c'est que j'en ai pas mal besoin surtout dans le loop car c'est une connexion a un wifi et il faut que j'attende les réponses et elles se font parfois... longues.
Si j'ai bien compris une interruption commence lorsqu'elle est appelé (logique) et se finis lorsque le programme appelé est finis, hors dans mon cas jamais car elle fait appel a une autre qui ne se finis jamais a moins que je re fasse appel a une interruption qui est impossible car vous m'avez dit que lorsqu'on est dans une interruption les autres sont inhibées. Voila ce que je crois avoir compris.
Edité: Merci de m'avoir dit que les interruptions sont recommandé d'être courte je ne le savais pas et également le fait qu'ils ne faut pas abuser des delay