Mon 1er projet. Un peu brouillon. Je prévois une V2 pour mettre tout ça au propre et aussi refaire la partie en bois parce qu'elle ne me convient pas.
J'en avait marre que la nuit, les rats mangent plus de grains que mes gallinacées. J'ai donc décidé de fabriquer ce petit automate qui ouvre la mangeoire et la ferme suivant le levé et couché de soleil (avec un delta sur les heures).
Sur base de arduino nano v3, un RTC_DS1307, d'un controleur L298N en H, de 2 capteurs magnétiques et d'un moteur 12v 30rpm.
Les 25kg de grains sont a présent protégés la nuit, et mine de rien, ça me coûte moins cher!
//1er projet arduino
//Avril 2022
//Automatisation de l'ouverture/fermeture de la porte de la mangeoire pour les poules.
//Matériel: un arduino Nano, une horloge DS13077, un controleur bridge en H L298N et un moteur DC 12v 30rpm hight torque + 2 capteurs magnétiques MC38 NO (naturally open)
#include <math.h>
#include <Dusk2Dawn.h>
#include <EEPROM.h>
#include <Wire.h>
#include <RTClib.h>
//Définition moteur
int in3 = 10;
int in4 = 9;
int sensorFerme = 4;
int sensorOuvre = 5;
DateTime now;
int sunrise;
int sunset;
int currentTime;
//Définition RTC
RTC_DS1307 rtc;
//Localisation GPS et fuseau horaire pour la bibliothèque dusk2dawn
Dusk2Dawn Lieux(lat, long, +1);
//Debug? true / false permet de mettre à jour l'heure a chaque connexion pour modification du code (true a chaque nouvelle connexion et avant 1er téléversement.
//Ne pas oublier de re-téléverser en ayant remis sur false.
const bool debug = true;
void setup() {
Serial.begin(9600);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
// On s'assure que le moteur soit toujours arrêté avant le début de la loop.
porteArrete();
pinMode(sensorFerme, INPUT);
pinMode(sensorOuvre, INPUT);
rtc.begin();
// Définissons simplement la date et l'heure à chaque fois que nous téléchargeons une version de débogage, car nous savons que le module RTC est bon avec une bonne batterie.
if (debug)
{
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
Serial.println("Checking RTC is Running");
}
void loop() {
delay(2000);
now = rtc.now();
sunrise = Lieux.sunrise(now.year(), now.month(), now.day(), true);
sunset = Lieux.sunset(now.year(), now.month(), now.day(), true);
currentTime = ((now.hour()) * 60) + (now.minute());
afficheHeure(now);
afficheSunsetSunriseCurrentTime(now);
if (currentTime >= sunrise - 10 && currentTime <= sunset + 15 && digitalRead(sensorOuvre) == 0)
{
ouverturePorte();
}
else if((currentTime < sunrise - 10 || currentTime > sunset + 15) && digitalRead(sensorFerme) == 0)
{
fermeturePorte();
}
}
void porteOuvre() {
digitalWrite(in3,1);
digitalWrite(in4,0);
}
void porteFerme() {
digitalWrite(in3,0);
digitalWrite(in4,1);
}
void porteArrete() {
digitalWrite(in3,0);
digitalWrite(in4,0);
}
void afficheHeure(DateTime now){
Serial.print("Date: ");
Serial.print(now.day());
Serial.print('/');
Serial.print(now.month());
Serial.print('/');
Serial.print(now.year());
Serial.print(" | Heure: ");
Serial.print(now.hour());
Serial.print(':');
Serial.print(now.minute());
Serial.print(':');
Serial.print(now.second());
Serial.println();
}
void afficheSunsetSunriseCurrentTime(DateTime now){
Serial.print("Sunrise: ");
Serial.print(sunrise);
Serial.print(" - Sunset: ");
Serial.print(sunset);
Serial.print(" - currentTime: ");
Serial.print(currentTime);
Serial.println();
}
void ouverturePorte(){
Serial.println("La porte s'ouvre");
while (digitalRead(sensorOuvre) == 0)
{
porteOuvre();
}
Serial.println("La porte est ouverte, elle s'arrête");
porteArrete();
}
void fermeturePorte(){
Serial.println("La porte se ferme");
while (digitalRead(sensorFerme) == 0)
{
porteFerme();
}
Serial.println("La porte est fermée, elle s'arrête");
delay(2500);
porteArrete();
}
Attention, si la variable debug reste à 1, la remise à l'heure aura lieu à chaque reboot (coupure secteur par exemple).
D'autre part un DS3231 aurait été préférable.
Petit soucis hier soir pendant la fermeture. Le capot de la mangeoire s'est coincé en pleine fermeture, du coup la corde a finir par s'enrouler a l'envers et tout s'est en**lé dans le boitier... Le moteur a fini par tourner sur lui même, enroulant les fils et tirant sur les composants.
Je dois le refaire au propre!
Il faudrait implémenter un timeout d'ouverture et fermeture.
Si le contact de fin de course ne se ferme pas dans le temps imparti, arrêter le moteur.
Tu peux aussi ajouter un buzzer afin de signaler l'incident.
V2 du boitier en place !
Le DS1307 à laissé sa place à un DS3231, l'Arduino est sur un support et le câblage est un peu mieux fait. J'ai également modifié au niveau des fixations des capteurs et des aimants.
Concernant le timeOut, j'ai testé vraiment vite fait, j'avais pas trop le temps de trainer. Le soucis c'est que dès que le timeOut était arrivé a 0, certes le moteur s'arrêtait, mais la boucle recommençait. J'ai donc décidé de pas en mettre. Ça remarche comme avant et la porte ne peut, techniquement, plus se bloquer.
MàJ du code également
//1er projet arduino
//Avril 2022
//Automatisation de l'ouverture/fermeture de la porte de la mangeoire pour les poules.
//Matériel: un arduino Nano, une horloge ds3231, un controleur bridge en H L298N et un moteur DC 12v 30rpm hight torque + 2 capteurs magnétiques MC38 NO (naturally open)
//MàJ du projet Septembre 2022 après un incident matériel.
#include <math.h>
#include <Dusk2Dawn.h>
#include <EEPROM.h>
#include <Wire.h>
#include <RTClib.h>
//Définition moteur
int in3 = 10;
int in4 = 9;
int sensorFerme = 5;
int sensorOuvre = 4;
DateTime now;
int sunrise;
int sunset;
int currentTime;
//Définition RTC
RTC_DS3231 rtc;
//Locatlisation GPS et fuseau horaire pour la bibliothèque dusk2dawn
Dusk2Dawn Labastide(43.9163881, 1.357439, +1);
// MàJ du module RTC à chaque nouvelle connexion.
// à mettre sur "false" après avoir téléversé sur "true" pour éviter une maj suite à une coupure de courant.
// Déclaration d'une constante
const bool debug = true;
void setup() {
Serial.begin(9600);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
// On s'assure que le moteur soit toujours arrêté avant le début de la loop.
moteurStop();
pinMode(sensorFerme, INPUT);
pinMode(sensorOuvre, INPUT);
rtc.begin();
if (debug){
Serial.println("Mise sous tension. Ajustement du RTC");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
else if (!debug){
Serial.println("Mise sous tension. Pas d'ajustement du RTC");
}
}
void loop() {
delay(1000);
now = rtc.now();
sunrise = Labastide.sunrise(now.year(), now.month(), now.day(), true);
sunset = Labastide.sunset(now.year(), now.month(), now.day(), true);
currentTime = ((now.hour()) * 60) + (now.minute());
//afficheHeure(now);
//afficheSunsetSunriseCurrentTime(now);
//afficheSensor();
//afficheEtatPorte()
if (currentTime >= sunrise - 10 && currentTime <= sunset + 15 && digitalRead(sensorOuvre) == 0)
{
ouverturePorte();
}
else if((currentTime < sunrise - 10 || currentTime > sunset + 15) && digitalRead(sensorFerme) == 0)
{
fermeturePorte();
}
}
void porteOuvre() {
digitalWrite(in3,0);
digitalWrite(in4,1);
}
void porteFerme() {
digitalWrite(in3,1);
digitalWrite(in4,0);
}
void moteurStop() {
digitalWrite(in3,0);
digitalWrite(in4,0);
}
void afficheHeure(DateTime now){
Serial.print("Date: ");
Serial.print(now.day());
Serial.print('/');
Serial.print(now.month());
Serial.print('/');
Serial.print(now.year());
Serial.print(" | Heure: ");
Serial.print(now.hour());
Serial.print(':');
Serial.print(now.minute());
Serial.print(':');
Serial.print(now.second());
Serial.println();
delay(1000);
}
void afficheSunsetSunriseCurrentTime(DateTime now){
Serial.print("Sunrise: ");
Serial.print(sunrise);
Serial.print(" - Sunset: ");
Serial.print(sunset);
Serial.print(" - currentTime: ");
Serial.print(currentTime);
Serial.println();
delay(1000);
}
void afficheSensor(){
Serial.print("Capteur ouvert: ");
Serial.println(digitalRead(sensorOuvre));
Serial.print("Capteur fermé: ");
Serial.println(digitalRead(sensorFerme));
delay(3000);
}
void afficheEtatPorte(){
if (digitalRead(sensorOuvre) == 0){
Serial.println("La porte est fermée, elle s'ouvre");
} else {
Serial.println("La porte est ouverte");
}
if (digitalRead(sensorFerme) == 0){
Serial.println("La porte est ouverte, elle se ferme");
} else {
Serial.println("La porte est fermée");
}
delay(1000);
}
void ouverturePorte(){
while (digitalRead(sensorOuvre) == 0)
{
porteOuvre();
}
moteurStop();
}
void fermeturePorte(){
while (digitalRead(sensorFerme) == 0)
{
porteFerme();
}
delay(6000);
moteurStop();
}
Hello!
Auriez vous une solution pour traduire le timestamp en format lisible comme la 1ère ligne et l'afficher aussi sur le lcd? Je n'ai rien trouvé de pertinent sur le web...
Ca dépend ce que représente ton timestamp?
je suppose qu'il s'agit d'un temps écoulé, donc il suffit de convertir le nombre d'unité en une heure au format (HH:MM:SS,MS)
Voici mon code dans son intégralité. Il me reste a faire la boucle pour l'ouverture et la fermeture du clapet et a voir si je ne peux pas raccourcir la void displayLCD()...
// 1er projet arduino
// Avril 2022
// Automatisation de l'ouverture/fermeture de la porte de la mangeoire pour les poules.
// Matériel: un arduino Nano, une horloge ds3231, un controleur bridge en H L298N et un moteur DC 12v 30rpm hight torque + 2 capteurs magnétiques MC38 NO (naturally open)
// Màj Janvier 2023: impression en 3D du boitier + couvercle avec supports composants intégrés, nouveau moteur DC 12V 50rpm, shield XL nano v3 ajout d'un LCD 20x4 et suppression des capteurs. Mise en place d'un chrono à la place.
#include <LiquidCrystal_I2C.h>
#include <Dusk2Dawn.h>
#include <EEPROM.h>
#include <Wire.h>
#include <math.h>
#include <RTClib.h>
LiquidCrystal_I2C lcd(0x3F,20,4);
RTC_DS3231 rtc;
Dusk2Dawn Labastide(43.9163881, 1.357439, +1);
//Définition moteur
int in1 = 2;
int in2 = 3;
DateTime now;
int sunrise;
int sunset;
int timeStamp;
int h_am = sunrise/60;
int m_am = (sunrise%60) - sunrise;
int h_pm = sunset/60;
int m_pm = (sunset%60) - sunset;
int hEte = 60; //passage a l'heure d'été
int decalage = 20; // minutes de décalage de fermeture
const bool debug = false;
void setup(){
Serial.begin(9600);
rtc.begin(); // initialisation du rtc
lcd.init(); // initialisation de l'afficheur
if (debug){
Serial.println("Démarrage. Ajustement du RTC");
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
else if (!debug){
Serial.println("Démarrage. Pas d'ajustement du RTC");
}
}
void loop(){
now = rtc.now();
sunrise = Labastide.sunrise(now.year(), now.month(), now.day(), true);
sunset = Labastide.sunset(now.year(), now.month(), now.day(), true);
h_am = ((sunrise - hEte) / 60);
m_am = (sunrise % 60);
h_pm = ((sunset - hEte) /60);
m_pm = (sunset%60);
displayLCD();
// if (timeStamp > sunrise - hEte){
// ouverturePorte();
// Serial.println("Attente de 60 secondes pour sortir de la loop");
// delay(60000);
// }
// else if(timeStamp > sunset - decalage){
// fermeturePorte();
// Serial.println("Attente de 60 secondes pour sortir de la loop");
// delay(60000);
// }
}
void displayLCD(){
lcd.backlight();
lcd.setCursor(1, 0);
lcd.print("Heure: ");
lcd.setCursor(11, 0); // 11 si on veut afficher les secondes en décommentant les lignes 78 a 82, 14 si on ne veut pas
if (now.hour() < 10){
lcd.print("0");
}
lcd.print(now.hour());
lcd.print(":");
if (now.minute() < 10){
lcd.print("0");
}
lcd.print(now.minute());
lcd.print(":");
if (now.second() < 10){
lcd.print("0");
}
lcd.print(now.second());
lcd.setCursor(1, 2);
lcd.print("Ouverture: ");
lcd.setCursor(15, 2);
lcd.print(h_am);
lcd.print(":");
lcd.print(m_am);
lcd.setCursor(1, 3);
lcd.print("Fermeture: ");
lcd.setCursor(14, 3);
lcd.print(h_pm);
lcd.print(":");
lcd.print(m_pm+decalage);
}
//Fonctions "motrices":
void opening() {
digitalWrite(in1,0);
digitalWrite(in2,1);
}
void closure() {
digitalWrite(in1,1);
digitalWrite(in2,0);
}
void stop() {
digitalWrite(in1,0);
digitalWrite(in2,0);
}
void ouverturePorte(){
Serial.println("Ouverture");
opening();
delay(13000);
Serial.println("Coupure alimentation moteur après 13secs");
stop();
}
void fermeturePorte(){
Serial.println("Fermeture");
closure();
delay(13000);
Serial.println("Coupure alimentation moteur après 13secs");
stop();
}
alors ça ça me fait vachement plaisir meme si ma vanne tombe à l'eau (et je ne suis pas dev non plus ).
Je tutoie d'emblée sur le forum, peut etre à cause de l'anglais, mais j'espère ne pas m'être montré trop cavalier!
Hardware de la V3 fini a l'instant. Après plus de 12h cumulées d'impression, le voici fini.
Boitier imprimé en 3D avec les supports pour chaque composants, l'emplacement pour le moteur et un capot clipsable où est fixé l'écran 20x4.
Plus qu'a finir le code et remplacer le système actuel!
c'est très beau, bravo pour tout ton boulot et merci pour toutes ces photos!
Après l'accident du moteur qui a arraché et enroulé tous les fils, et malgré tes améliorations du soft, tu as envisagé de mettre des sécurités physiques sur les cables? presse étoupe, fixation à vis...
J'ai modélisé un support pour le moteur.
Le moteur vient s'emboiter avec quasi zéro jeu et est verrouillé par la plaque de dessus qui est tenue par 2 vis m3 de 8mm de long. Que j'ai ensuite intégré dans la boite.
Si le moteur arrive a tourner, ça veut dire qu'il a éclaté le support...
Je réfléchis en parallèle a utiliser un petit embrayage Lego:
Maintenant que j'ai l'imprimante 3d, je peux faire quasi ce que je veux, donc pour la liaison entre lui, le moteur, l'axe et la bobine, ça ne sera pas problématique.