Montage et codage 4 microswitch

Bonjour et merci pour vos infos ! Bonne fête de Pâques à tous !

Perso je suis un peu perdu ! Ce matin après avoir mangé quelques œufs de Pâques avec Tom :slightly_smiling_face:, j'ai simplement effectué le montage et codage du 31.03.24 par @jpbbricole sur wokwi suivant:

/*
Name:       ARDFR_papadetom4microswitches.ino
Created:	28.03.2024 15:56:26
Author:     jpbbricole/papadetom
*/

// Déclaration des broches
const byte delPin[] = {10, 11, 12, 13};
const byte bpPin[] = {2, 3, 4, 5};
const byte bpNombre = sizeof(bpPin) / sizeof(bpPin[0]);     // Calcul du nombre de boutons
const byte delEtatOn = HIGH;     // Etat pour allumer la LED
const byte bpEtatOn = LOW;     // Etat de bp quand actif

const unsigned long delOnTempo[] = {2000, 2000, 2000, 2000};     // Durées d'allumage
unsigned long delOnMillis[] = {0, 0, 0, 0};     // Durées d'allumage, chrono

void setup( )
{
	Serial.begin(115200);

	for (int b = 0; b < bpNombre; b ++) // programmation des broches
	{
		pinMode(delPin[b], OUTPUT);
		digitalWrite(delPin[b], !delEtatOn); // extinction de la LED
		pinMode(bpPin[b], INPUT_PULLUP);
	}
}

void loop()
{
	for (int b = 0; b < bpNombre; b ++) // Lecture des boutons
	{
		if (digitalRead(bpPin[b]) == bpEtatOn && digitalRead(delPin[b]) != delEtatOn) // poussoir enfoncé et DEL pas allumée
		{
			digitalWrite(delPin[b], delEtatOn); // Allumer la LED
			delOnMillis[b] = millis(); // Démarrage du chrono
			Serial.println(String(b) + " Start " + String(delOnTempo[b]) + " millisecondes");
		}
	}

	for (int b = 0; b < bpNombre; b ++) // Lecture des chrono
	{
		if (digitalRead(delPin[b]) == delEtatOn  && millis() - delOnMillis[b] >= delOnTempo[b]) // Si led allumée et chrono à échéance
		{
			Serial.println(String(b) + " END");
			digitalWrite(delPin[b], !delEtatOn); // Etreindre la LED
		}
	}
}

Celui me convient parfaitement. Je ne souhaite pas forcément comprendre le codage comme déjà expliqué auparavant, Tom fera certainement d'autre essai de codage et d'autre montage avec celui-pour s'améliorer, après tout il n'a que 10 ans ! Je souhaite à présent ajouter le buzzer qui doit produire 1 son (de 1 ou plusieurs notes) uniquement lorsque l'une des leds s'allume. Puis (comme si cela n'était pas déjà assez compliqué pour moi ! ) aussi faire fonctionné le moteur pas à pas pendant x secondes quand l'une des leds s'allume (ou fonctionne le temps d'allumage de la led peut-être aussi une solution).

Je demande beaucoup mais je suis dans l'impossibilité de faire cela seul pour le moment ! Auriez vous un bon livre à me conseiller pour apprendre le c++ pour arduino avec des exemples et surtout ludique pour Tom ? Poiur info, j'ai commandé un abonnement chez https://www.robobox.fr/

Merci !
papadetom
jc

Non, et ça me conforte dans mon avis que ce n’est pas possible d’ignorer l’apprentissage du C++.

Pas possible pour quoi?

En tout cas pas indispensable pour proposer une solution à Tom.

Bonjour le_viking

Oui, on peut faire de l'Arduino sans apprendre le C++. perso je ne l'ai pas étudié, je suis directement parti sur le langage de l'environnement Arduino et tout ces outils qui facilitent grandement la tâche.

As tu fait le montage "en vrai" pour tester ton programme?
C'est ce que j'ai fait, et copié/collé ton programme du post#82 et je constate:

Je persiste à dire que Metro.c n'est pas adapté pour cet exemple, il gère des événements récurrents.

Cordialement
jpbbricole

Bonjour papadetom

:+1:, veinards :wink:

Compris!
Je te prépare pour le moteur et pour le buzzer.

A+"
Cordialement
jpbbricole

1 Like

:woozy_face:T'as pas dû recevoir la bonne formation!

Bonsoir papadetom

J'adore ça :wink:

Je te donne la version avec moteur pas à pas, il faut installer la bibliothèque
AccelStepper:
image

Pour les connexions du moteur, c'est ainsi:
image
AccelStepper moteur(AccelStepper::FULL4WIRE, 6, 8, 7, 9); // Fils sur lesquels est branché le module du moteur

Pour l'alimentation:
image
regardes la documentation de ton kit.

Dans le programme, la variable motDelCommande fixe quel DEL fait démarrer le moteur et la variable motMarcheTempo fixe son temps de fonctionnement.

Tu peux aussi ajuster cette valeur:
moteur.setMaxSpeed(600);
qui fixe la vitesse du moteur.

Le programme:

/*
Name:       ARDFR_papadetom4microswitches.ino
Created:	28.03.2024 15:56:26
Author:     jpbbricole/papadetom
*/

#include <AccelStepper.h>  // https://www.arduino.cc/reference/en/libraries/accelstepper/

// Déclaration des broches
const byte delPin[] = {10, 11, 12, 13};
const byte bpPin[] = {2, 3, 4, 5};
const byte bpNombre = sizeof(bpPin) / sizeof(bpPin[0]);     // Calcul du nombre de boutons
const byte delEtatOn = HIGH;     // Etat pour allumer la LED
const byte bpEtatOn = LOW;     // Etat de bp quand actif

const unsigned long delOnTempo[] = {2000, 1500, 6000, 3000};     // Durées d'allumage
unsigned long delOnMillis[] = {0, 0, 0, 0};     // Durées d'allumage, chrono

//------------------------------------- Partie moteur^(mot)
const int motDelCommande = 2;     // DEL qui commande le moteur

AccelStepper moteur(AccelStepper::FULL4WIRE, 6, 8, 7, 9); // Fils sur lesquels est branché le module du moteur
const unsigned long motMarcheTempo = 3000;     // Temps de marche du moteur
unsigned long motMarcheMillis = 0;     // Temps de marche du moteur, chrono
boolean moteurEstEnFonction = false;     // Si moteur fonctionne

void setup( )
{
	Serial.begin(115200);

	for (int b = 0; b < bpNombre; b ++) // programmation des broches
	{
		pinMode(delPin[b], OUTPUT);
		digitalWrite(delPin[b], !delEtatOn); // extinction de la LED
		pinMode(bpPin[b], INPUT_PULLUP);
	}

	moteur.setMaxSpeed(600);
	moteur.setSpeed(moteur.maxSpeed());
}

void loop()
{
	for (int b = 0; b < bpNombre; b ++) // Lecture des boutons
	{
		if (digitalRead(bpPin[b]) == bpEtatOn && digitalRead(delPin[b]) != delEtatOn) // poussoir enfoncé et DEL pas allumée
		{
			digitalWrite(delPin[b], delEtatOn); // Allumer la LED
			delOnMillis[b] = millis(); // Démarrage du chrono
			Serial.println(String(b) + " Start " + String(delOnTempo[b]) + " millisecondes");
			
			if (b == motDelCommande) // Si la DEL commande le démarrage du moteur
			{
				moteurEstEnFonction = true;  // Moteur déclaré en fonction
				motMarcheMillis = millis();  // Démarrage du chrono

				Serial.println("\tMoteur demarre " + String(motMarcheTempo) + " millisecondes");
			}
		}
	}

	for (int b = 0; b < bpNombre; b ++) // Lecture des chrono des DEL
	{
		if (digitalRead(delPin[b]) == delEtatOn  && millis() - delOnMillis[b] >= delOnTempo[b]) // Si led allumée et chrono à échéance
		{
			Serial.println(String(b) + " END");
			digitalWrite(delPin[b], !delEtatOn); // Etreindre la LED
		}
	}

	if (moteurEstEnFonction && millis() - motMarcheMillis >= motMarcheTempo)  // Si temps de fonction terminé
	{
		moteurEstEnFonction = false;  // Moteur déclaré en fonction
		Serial.println("\tMoteur ARRET");
	}

   if (moteurEstEnFonction)
   {
		moteur.runSpeed();
   }
}

Demain, je t'ajoute le buzzer.

Salutations à Tom!
Cordialement
jpbbricole

1 Like

J'ai commencé à préparé ma version didactique(en fin je crois) du bouton et LED pendant 2s, mais comme cela n'est pas ce que tu recherche, je laisse @jpbbricole te faire ton petit programme.

Du coup, obligatoirement tu as appris le C++, certes pas avec des cours et surement moins rapidement. mais tu t'es formé au C++, je ne dirais même pas en autodidacte, puisque tu as utiliser un support.
On le vois bien d'ailleurs dans tes programmes, ton niveau en C++ et loin d'être bas.

Bonsoir terwal

D'accord avec toi, mais je regarde ça par l'autre bout de lorgnette, sans l'Arduino, je n'aurais pas fait de C, je trouvais ça ésotérique, j'étais tout pour le Basic.

Bonne soirée
jpbbricole

Bonjour @jpbbricole, le C/C++ en soit n'a pas vraiment d'intérêt, du moins il n'est pas supérieur à d'autre.
Si un langage permet de faire ce que tu veux et tu n'y trouve pas d'inconvénient qui pourrait palier par d'autre langage, ce langage est le meilleur.
Le Basic à permit à beaucoup de personne de faire ses gammes et de passer sur d'autre langage, lorsque cela a était nécessaire.

J'ai horreur du pyhton, mais de la même façon beaucoup de personne peuvent grâce à lui, faire leur projet.

1 Like

Et bien voyez vous, j'ai eu 2 jours de formation au python, j'ai presque rien retenu car les stagiaires, soient disant débutant, étaient loin de l'être, et du coup, je n'était pas dans le coup.

Le formateur n'arrêtez pas de nous dire que le python est le language du siécle...

Depuis, à titre perso, j'ai fais du python pour faire 1 interface Homme Machine avec d'un côté mon Raspberry et son écran tactile (en python + tkinter) de l'autre Arduino, au milieu une liaison série filaire, ça ça marche (j'essaye de passer en Bluetooth).

Mon plaisir perso, c'est de trouver les solutions, pas forcément tout seul, mais sans aucun cours au sens stricte du terme car je n'arrive pas à me concentrer sur 1 formateur qui me parle, je préfère avancer à mon rythme en allant chercher l'info dont j'ai besoin sur le moment.

Moi je fais du code en mode loisir.

1 Like

@papadetom
Il y a quelques livres pour débuter.
Le cours C de open classroom qui bien que critiqué est extrêmement abordable même pour un enfant. zeste de savoir https://zestedesavoir.com/tutoriels/pdf/822/la-programmation-en-c-moderne.pdf (c'est c++ malgré le titre )qui est également très accessible et imprimable. et Le site de https://www.developpez.com/. Ce ne sont que les plus connus.

Je vais expliquer pourquoi j'ai répondu non à cette affirmation
cette ligne

Metro ledOn = Metro(10000);

en réalité pourrait être déclaré sur deux lignes comme ceci

//En global
Metro ledOn;
//En void setup()
ledOn. interval(10000);

Dans la première ligne on construit un objet ledOn de type Metro qui appelle le constructeur par défaut et interval vaut alors 1000
Dans la seconde ligne on appelle la fonction interval en mettant 10000 en paramètre. Cette fonction n'a pour objet que de changer la valeur d'une variable membre.
Aucune fonction active n'est appelée donc rien n'a déclenché quoi que ce soit

Dans la première déclaration on construit directement l'objet ledOn de type Metro avec un constructeur qui prend en paramètre interval mais là aussi aucune fonction active n'est appelée donc rien n'a déclenché quoi que ce soit.

Maintenant si on m'explique que je me trompe, autrement qu'en annonçant metro ca peut pas marcher ou en essayant de tourner en dérision je suis preneur

Merci !

OK, merci le_viking

De rien
Il y a aussi un livre De Claude Delannoy, C++ pour les programmeurs C. C'est pas pour les débutants mais on peut le télécharger gratuitement en ce moment même si c'est pour lire plus tard...
http://bibliotheque.pssfp.net/livres/C%2B%2B%20pour%20les%20programmeurs%20C.pdf

1 Like

Bonsoir le_viking

Toute ton explication n'explique pas ce que je constate "en vrai", fais l'essai toi même, ça demande quasiment pas de matériel, et tu reviens m'expliquer pourquoi je me suis trompé, mais je doute, j'ai simplement copié/collé ton programme.

metro ne peut pas marcher dans le cas qui nous intéresse, parce que, pour moi, tu te trompe sur ce quoi fait cette bibliothèque.
Le mieux, fais en l'essai pour de bon, la théorie ne fait pas tout.

Cordialement
jpbbricole

J'avais testé quand j'ai donné le code, j'ai testé le temps quand tu m'as signalé le défaut, je ne constate aucune erreur même en faisant pleins de tests ou en changeant le temps. Cette librairie est faite pour mesurer un intervalle de temps, c'est sur que pour une seule mesure ca ne vaut guère le coup sauf pour éviter d'apprendre à utiliser millis. Elle ne devient intéressante qu'avec plusieurs LED clignotantes avec un temps différent éclairage/extinction, là ca fait gagner des lignes de code

J'ai réussi à constater le problème en ajoutant des fonctions pour contrôler l'exactitude du délai, dans ce cas il suffit d'appeler la fonction reset

ledOn.reset();

avant la fonction check pour remettre le temps de début conforme

Bonsoir papadetom

Voila la version avec moteur et son.
Moteur :
La variable motDelCommande fixe quel DEL fait démarrer le moteur et la variable motMarcheTempo fixe son temps de fonctionnement.
Le temps de fonctionnement du moteur est indépendant de celui de la DEL qui le commande.
Tu peux aussi ajuster cette valeur pour faire varier la vitesse du moteur:
moteur.setMaxSpeed(600);
Pour inverser le sens de rotation, mettre un moins ici :
moteur.setSpeed(-moteur.maxSpeed());
Pour brancher le moteur, voir post#107.

Sons :
La variable sonDelCommande fixe quel DEL fait démarrer le son.
Les notes sont dans le tableau sonNotes] et la durée des notes dans le tableau sonNotesDuree.

const int sonNotes[] = {493, 440}; // Pompiers notes
const int sonNotesDuree[] = {1000, 1000}; // Pompiers tempo

Pour ajouter ou supprimer des notes, il faut agir dans les 2 tableaux.
Attention, la génération des sons est la seule fonction dite bloquante dans ce programme, c’est-à-dire que, pendant les sons, rien d’autre ne se passe dans le programme, ça arrête même le moteur s’il est en marche.
Le buzzer passif se connecte entre la pin sonBuzzerPin (A0) et +5V.

Le programme:

/*
Name:       ARDFR_papadetom4microswitches.ino
Created:	28.03.2024 15:56:26
Author:     jpbbricole/papadetom

31.03.2024	Première version #98
31.03.2024	Ajout moteurpas à pas #107
01.04.2024	Ajout sons #120
*/

#include <AccelStepper.h>  // https://www.arduino.cc/reference/en/libraries/accelstepper/

// Déclaration des broches
const byte delPin[] = {10, 11, 12, 13};
const byte bpPin[] = {2, 3, 4, 5};
const byte bpNombre = sizeof(bpPin) / sizeof(bpPin[0]);     // Calcul du nombre de boutons
const byte delEtatOn = HIGH;     // Etat pour allumer la LED
const byte bpEtatOn = LOW;     // Etat de bp quand actif

const unsigned long delOnTempo[] = {2000, 1500, 6000, 3000};     // Durées d'allumage
unsigned long delOnMillis[] = {0, 0, 0, 0};     // Durées d'allumage, chrono

//------------------------------------- Partie moteur^(mot)
const int motDelCommande = 2;     // DEL qui commande le moteur

AccelStepper moteur(AccelStepper::FULL4WIRE, 6, 8, 7, 9); // Fils sur lesquels est branché le module du moteur
const unsigned long motMarcheTempo = 3000;     // Temps de marche du moteur
unsigned long motMarcheMillis = 0;     // Temps de marche du moteur, chrono
boolean moteurEstEnFonction = false;     // Si moteur fonctionne

//------------------------------------- Son
const int sonDelCommande = 1;     // DEL qui commande le son

const int sonBuzzerPin = A0; // Connexion buzzer
const int sonNotes[] = {493, 440};     // Pompiers notes
const int sonNotesDuree[] = {1000, 1000};     // Pompiers tempo
const int sonNotesNombre = sizeof(sonNotes) / sizeof(sonNotes[0]); // Nombre de notes dans la mélodie
const int sonRepetitions = 3;     // Nombre de fois que les notes sont jouées
int sonRepetcpt = 0;     // Compteur des répétitions

void setup( )
{
	Serial.begin(115200);

	for (int b = 0; b < bpNombre; b ++) // programmation des broches
	{
		pinMode(delPin[b], OUTPUT);
		digitalWrite(delPin[b], !delEtatOn); // extinction de la LED
		pinMode(bpPin[b], INPUT_PULLUP);
	}

	moteur.setMaxSpeed(600);
	moteur.setSpeed(moteur.maxSpeed());
}

void loop()
{
	for (int b = 0; b < bpNombre; b ++) // Lecture des boutons
	{
		if (digitalRead(bpPin[b]) == bpEtatOn && digitalRead(delPin[b]) != delEtatOn) // poussoir enfoncé et DEL pas allumée
		{
			digitalWrite(delPin[b], delEtatOn); // Allumer la LED
			delOnMillis[b] = millis(); // Démarrage du chrono
			Serial.println(String(b) + " Start " + String(delOnTempo[b]) + " millisecondes");
			
			if (b == sonDelCommande) // Si la DEL commande le son
			{
				Serial.println("\tSon joue");
				sonRepetcpt = sonRepetitions; // Chatrger compteur
			}
			
			if (b == motDelCommande) // Si la DEL commande le démarrage du moteur
			{
				moteurEstEnFonction = true;  // Moteur déclaré en fonction
				motMarcheMillis = millis();  // Démarrage du chrono

				Serial.println("\tMoteur demarre " + String(motMarcheTempo) + " millisecondes");
			}
		}
	}

	for (int b = 0; b < bpNombre; b ++) // Lecture des chrono des DEL
	{
		if (digitalRead(delPin[b]) == delEtatOn  && millis() - delOnMillis[b] >= delOnTempo[b]) // Si led allumée et chrono à échéance
		{
			Serial.println(String(b) + " END");
			digitalWrite(delPin[b], !delEtatOn); // Etreindre la LED
		}
	}

	if (moteurEstEnFonction && millis() - motMarcheMillis >= motMarcheTempo)  // Si temps de fonction terminé
	{
		moteurEstEnFonction = false;  // Moteur déclaré en fonction
		Serial.println("\tMoteur ARRET");
	}

	if (moteurEstEnFonction) // Commande moteur
	{
		moteur.runSpeed();
	}

	if (sonRepetcpt > 0) // S'il y a des sons à jouer
	{
		sonJouer();
		sonRepetcpt --; // Décrémenter le compteur de répétitions
		if (sonRepetcpt < 1) // Si tout est joué
		{
			Serial.println("\tSon fin");
		}
	}

}

void sonJouer()
{
	for (int n = 0; n < sonNotesNombre; n ++)
	{
		tone(sonBuzzerPin, sonNotes[n]);
		delay(sonNotesDuree[n]);
		noTone(sonBuzzerPin);
		Serial.print("\tnote ");
		Serial.println(sonNotes[n]);

	}
}

Amusez vous bien :wink:
Bonne soirée
jpbbricole

1 Like

Merci pour le code jpbbricole! Merci à tous pour votre aide.

Je vais faire le montage cette semaine.
Je me demande s'il serai possible d'actionner le moteur uniquement au bout de x pulsion des switch ? (Toujours des nouvelles idées :bulb:)

Bonne semaine !

Papadetom