Bonjour,
j'ai fait ce code pour connaitre la distance entre un chariot et un mur, mais j'ai quelque problème avec la mesure.
quand les deux capteurs fonctionne c'est assez prescris, mais souvent il y en a un ou les deux qui donne 0. les capteurs sont espacés de 2 mètres.
de plus tout ajout de la fonction delay() bloque le code.
j'aimerai ajouter un buzzer qui bip de plus en plus vite selon que le chariot se rapproche mais tout mes essais n'ont rien donner. ( des bip mais pas en rapport avec la distance), j'ai testé avec la fonction Tone.
#include <NewPing.h>
#include <SPI.h>
#include <Wire.h>
#include "easyRun.h"
////////////////// SSD1306 //////////////////
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
/////////////////// HC_SR05 /////////////////
unsigned long currentTime = 0;
unsigned long previousTime = 0;
#define SONAR_NUM 2 // Nombre de capteurs.
#define MAX_DISTANCE 300 // Distance maximale (en cm) jusqu'au ping. ici 3M.
#define PING_INTERVAL 33 // Millisecondes entre les pings du capteur (29 ms est à peu près le minimum pour éviter l'écho croisé des capteurs).
unsigned long pingTimer[SONAR_NUM]; // Contient le temps auxquelles le prochain ping doit se produire pour chaque capteur.
unsigned int cm[SONAR_NUM]; // Où les distances de ping sont stockées.
uint8_t currentSensor = 0; // Garde une trace du capteur actif.
int Average;
NewPing sonar[SONAR_NUM] = { // Tableau d’objets capteur.
NewPing(12, 11, MAX_DISTANCE), // La broche de déclenchement, la broche d'écho et la distance maximale jusqu'au ping de chaque capteur.
NewPing(10, 9, MAX_DISTANCE),
};
////////////////// WS 1820 ///////////////////
#include <Adafruit_NeoPixel.h>
int DataIn = 6;
Adafruit_NeoPixel pixels(9, 6, NEO_GRB + NEO_KHZ800);
uint32_t Noir = pixels.Color(0, 0, 0);
uint32_t Rouge = pixels.Color(255, 0, 0);
uint32_t Bleu = pixels.Color(0, 0, 255);
uint32_t Vert = pixels.Color(0, 255, 0);
uint32_t couleur;
asyncTask lanceur; //lanceur est un objet de type "tâche asynchrone"
void setup() {
Serial.begin(115200);
pixels.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.clearDisplay();
///////////////////////////////////////////////
pingTimer[0] = millis() + 75; // Le premier ping démarre à 75 ms, laisse le temps à l'Arduino de se refroidir avant de démarrer.
for (uint8_t i = 1; i < SONAR_NUM; i++) // Définit l'heure de démarrage de chaque capteur.
pingTimer[i] = pingTimer[i - 1] + PING_INTERVAL;
////////////////////////////////////////////////
lanceur.set(LedOn, 0); //Pour appeler la fonction LedOn dès que possible, et ainsi amorcer le cycle
}
void loop() {
easyRun(); //actualisation des objets easyRun, dont lanceur.
for (uint8_t i = 0; i < SONAR_NUM; i++) { // Parcour tous les capteurs.
if (millis() >= pingTimer[i]) { // Est-ce le moment pour ce capteur d'envoyer un ping ?
pingTimer[i] += PING_INTERVAL * SONAR_NUM; // Réglez la prochaine fois que ce capteur recevra un ping.
// if (i == 0 && currentSensor == SONAR_NUM - 1) oneSensorCycle(); // Cycle de ping du capteur terminé, faites quelque chose avec les résultats.
sonar[currentSensor].timer_stop(); // Assurez-vous que le minuteur précédent est annulé avant de démarrer un nouveau ping.
currentSensor = i; // Capteur en cours d'accès.
cm[currentSensor] = 0; // Réglez la distance à zéro au cas où il n'y aurait pas d'écho ping pour ce capteur.
sonar[currentSensor].ping_timer(echoCheck); // Faire le ping (le traitement continue, l'interruption appellera echoCheck pour rechercher l'écho).
}
}
currentTime = millis();
if ((currentTime - previousTime) > 100) { // affichage toutes les 100ms
previousTime = currentTime;
Average = (cm[0] + cm[1]) / 2;
display.clearDisplay();
display.setTextSize(5);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, -1);
display.print(Average); //
display.display();
}
if (Average >= 200) { // test de distance pour changer la couleur
couleur = Bleu;
} else if (Average < 200 && Average >= 100) {
couleur = Vert;
} else if (Average < 100 && Average >= 0) {
couleur = Rouge;
}
}
void echoCheck() { // Si un ping est reçu, défini la distance du capteur sur le réseau.
if (sonar[currentSensor].check_timer())
cm[currentSensor] = sonar[currentSensor].ping_result / US_ROUNDTRIP_CM;
}
void LedOn() {
pixels.clear();
for (int i = 0; i <= 8; i++) {
pixels.setPixelColor(i, couleur);
pixels.show();
}
lanceur.set(LedOff, Average ); //lanceur devra appeler la fonction LedOff dans le délai d'Average (distance capteur)
}
void LedOff () {
for (int i = 0; i <= 8; i++) {
pixels.setPixelColor(i, Noir);
lanceur.set(LedOn, Average );
pixels.show();
}
}
void oneSensorCycle() {
// affichage des valeurs pour débug
}
En faisant ça, le premier capteur va tirer toutes les 33ms et le second toutes les 66ms. Le terme * SONAR_NUM est inutile puisque tu ajoutes PING_INTERVAL au temps précédent et qu'à l'origine tu avais introduit un décalage dans le timing des 2 capteurs.
ca ne marche pas mieux.
je test un autre code, qui fonctionne un peut mieux avec moins de pertes de mesures mais pas facile de rajouter les led et le buzzer sans mètre la pagaille dans les mesures.
ca ne supporte pas la fonction delay()
#include <SPI.h>
#include <Wire.h>
////////////////// SSD1306 //////////////////
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
/////////////////// HC_SR05 /////////////////
const int trigPin1 = A0; // 12
const int echoPin1 = A1; // 11
const int trigPin2 = A2; // 10
const int echoPin2 = A3; // 9
unsigned long duration1, distance1, duration2, distance2;
float distanceAvg;
int sampleCount = 5;
////////////////// WS 1820 ///////////////////
#include <Adafruit_NeoPixel.h>
int DataIn = 6;
Adafruit_NeoPixel pixels(9, 6, NEO_GRB + NEO_KHZ800);
uint32_t Noir = pixels.Color(0, 0, 0);
uint32_t Rouge = pixels.Color(255, 0, 0);
uint32_t Bleu = pixels.Color(0, 0, 255);
uint32_t Vert = pixels.Color(0, 255, 0);
uint32_t couleur;
const int buzzerPin = 11;
void setup() {
Serial.begin(9600);
pixels.begin();
pinMode(trigPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
pinMode(buzzerPin, OUTPUT);
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.clearDisplay();
}
void loop() {
distance1 = getAverageDistance(trigPin1, echoPin1);
distance2 = getAverageDistance(trigPin2, echoPin2);
distanceAvg = (distance1 + distance2) / 2.0;
display.clearDisplay();
display.setTextSize(5);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, -1);
display.print( distanceAvg / 100);
display.display();
// tone(9, 2000, 100);
pixels.clear();
for (int i = 0; i <= 8; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
pixels.show();
}
delay(distanceAvg*2); // pour faire varier la vitesse de clignotement en fonction de la distance
for (int i = 0; i <= 8; i++) {
pixels.setPixelColor(i, pixels.Color(255, 0, 0));
pixels.show();
}
}
unsigned long getAverageDistance(int trigPin, int echoPin) {
unsigned long totalDuration = 0;
for (int i = 0; i < sampleCount; i++) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration1 = pulseIn(echoPin, HIGH);
distance1 = duration1 * 0.034 / 2;
totalDuration += distance1;
}
return totalDuration / sampleCount;
}
Si tu changes l'état de toutes les LEDs ce n'est pas utile d'appeler clear() cela fait 2 fois la même chose.
Tu n'as pas besoin d'appeler show() après chaque setPixelColor(). Tu peux mettre show() à la sortie de la boucle for. Cela raccourcira la durée de la boucle.
La librairie Neopixel masque les interruptions pendant un certain temps lors du rafraîchissement.
Tu veux ajouter un buzzer. Attention, tone() utilise une interruption.
Si tu veux te débarrasser de delay(), il faudrait tout faire avec millis() mais cela va t'obliger à réorganiser ton code différemment.
Des tâches relancées à intervalles réguliers rythmées par millis().
a oui un oubli. j'ai laisser pixels.show car au début je voulais faire un chenillard.
il faut que je compte le temps chaque processus des capteurs et que je cale tout ca avec le temps de l’allumage des led et du buzzer c'est ça?
j'ai refait un code qui marche plutôt bien, j'ai été obligé de rajouter un contrôle de la valeur du capteur car il y a toujours des bizarreries qui donnent de temps en temps des valeurs a 0 ou trop élevées.
Je ne trouve pas pourquoi il y a ces écarts de mesures.
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
///////////////////////////////// HC-SR05 /////////////////////////////////
#include <NHCSR04.h>
int maxCentimeters = 500; //Default is 100cm.
int triggerPin = 10;
int echoPin = 9;
double cm;
SR04 sensor(triggerPin, echoPin, maxCentimeters);
///////////////////////////////// BUZZER /////////////////////////////////
int ancienneValeur = 0;
int nouvelleValeur = 0;
const int seuil = 30; // Seuil pour la variation d'érreurs
const int buzzerPin = 7;
unsigned long previousMillis = 0;
unsigned long currentMillis;
const long interval = 200; // Interval entre les mesures en millisecondes
const int maxDetectionDuration = 30; // Durée de détection maximale en millisecondes
unsigned long detectionStartTime = 0; // Temps de début de la détection
///////////////////////////////// SSD1306 /////////////////////////////////
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
///////////////////////////////// WS 1820 /////////////////////////////////
int DataIn = 8;
Adafruit_NeoPixel pixels(9, 8, NEO_GRB + NEO_KHZ800);
uint32_t Noir = pixels.Color(0, 0, 0);
uint32_t Rouge = pixels.Color(255, 0, 0);
uint32_t Bleu = pixels.Color(0, 0, 255);
uint32_t Vert = pixels.Color(0, 255, 0);
uint32_t Orange = pixels.Color(255, 100, 40);
uint32_t Jaune = pixels.Color(255, 155, 0);
uint32_t Pourpre = pixels.Color(127, 0, 255);
uint32_t couleur;
void setup()
{
Serial.begin(9600);
pinMode(buzzerPin, OUTPUT);
///////////////////////////////// SSD1306 /////////////////////////////////
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.clearDisplay();
///////////////////////////////// WS 1820 /////////////////////////////////
pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
}
void loop()
{
currentMillis = millis();
cm = sensor.centimeters();
if (abs(cm - ancienneValeur) > seuil) {
cm = ancienneValeur;
} else {
ancienneValeur = cm;
}
Serial.print("cm: ");
Serial.println(cm);
if (cm >= 120) { // test de distance pour changer la couleur
couleur = Bleu;
} else if (cm < 120 && cm >= 100) {
couleur = Vert;
} else if (cm < 100 && cm >= 70) {
couleur = Jaune;
} else if (cm < 70 && cm >= 40) {
couleur = Orange;
} else if (cm < 40 && cm >= 10) {
couleur = Rouge;
}
LedBuzzer();
Affichage();
}
void Affichage() {
display.clearDisplay();
display.setTextSize(5);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, -1);
int CM = cm;
display.print(cm / 100);
display.display();
}
void LedBuzzer() {
if (cm <= 15) { // Buzzer et led en continu selon la distance minimum choisie
for (int t=0; t <= 8; t++) {
pixels.setPixelColor(t, Rouge);
pixels.show();
}
digitalWrite(buzzerPin, HIGH);
} else {
for (int t=0; t<=8; t++){
// pixels.clear();
pixels.setPixelColor(t, couleur);
pixels.show();
delay(cm/4 );
}
digitalWrite(buzzerPin, HIGH);
delay(cm );
for (int t=0; t<=8; t++) {
pixels.setPixelColor(t, Noir);
pixels.show();
delay(cm/4 );
}
digitalWrite(buzzerPin, LOW);
delay(cm );
}
}