le plan du cablage :
pour l'avoir en grand c'est
ICI
comme vous pouvez le voir il y a 2 arduino Nano pour gérer, un dans chaque compartiment
l'arduino du compartiment arrière envoi a l'arduino avant des codes toues les 5 secondes,si rien ne bouge ou immédiatement si le numéro d'alarm change , style alarm = 1 ou 2 jusqu'a 10
cela me gère
_le périscope en fonction de la profondeur avec une sécurité si le soum n'est pas dans l'eau + un temps maxi de fonctionnement de la pompe si un ILS de fin de course venait a déconner
_ la pesé du soum, avec un accéléromètre, a partir du moment ou mes périscopes sont sorties, en actionnant un interrupteur sur ma télécommande, les 2 servo en rotation en continue déplacent les 2 lests mobiles qui sont sur les tiges filetées dans chaque compartiment et devraient me remettre le soum a niveau 0
_ la sécurité de profondeur qui est déterminée par un potar de la télécommande de 0 à 3 mètres si je dépasse la profondeur demandée au potar ,le servo de la pompe et du presse durite, relâche doucement la pression de la bille, si dans délai de 5 secondes,le soum n'est pas repassé au dessus du niveau demandé,le servo relâche complétement la bille (le soum remonte doucement a la profondeur demandée)
_1 détection d'eau dans chaque compartiment, si eau détectée, le servo ballast relache la pression de la bille et me bloque toute action sur la pompe (le soum remonte et ne peut plus replonger)
_1 capteur de pression de l'air dans le ballast, si ma pompe restait en position remplissage,car j'ai réussi a faire péter le joint siclaflex un la laissant tourner pour remplir au maximum le ballast, cela réglage la bille pour faire descendre la pression dans le ballast (le soum remonte)
_1 capteur de température dans le compartiment moteur propulsion qui réduit la puissance moteur a 25% si la température venait a être trop importante a l’intérieur
_1 capteur de tension de la batterie qui réduit la puissance moteur a 25% pour avoir assés de pêche pour ramener le soum,en bloquant la plongée,et le ramène a la surface
_ un lecteur de carte SD, qui me permet d'enregistrer toues les données pour pouvoir les mettre dans EXCEL en forme de tableau
voila en gros ce que je gère avec mes 2 arduino UNO
Programme de l'arduino UNO arriere
Code : Tout sélectionner
/* --- Programme Arduino version 1.0.5--- 04/06/2014
carte Arduino Nano ARRIERE (Nano_Arriere.ino)
**************************
Pour reprogrammer l'arduino directement sur son support:
debrancher les fils RX & TX (Bleu et gris)
debrancher les fils d alim 12volt (prise 3 fils (jaune ,rouge & noir a cote du BMP085))
****************************
MMA7361 (A7)--> Arduino Nano--< 2 servos(D11,D12) , recepteur voie 8 = (A0 sur NANO1)
permet l'equilibrage automatique du soum si la voie 8 du recepteur est activee
alimentation du MMA7361 ainsi que les 2 servos en 3.3 volts via l'arduino niveau 0 = 330
alimentation du MMA7361 ainsi que les 2 servos en 5 volts via l'arduino niveau 0 = 565
BMP085 (A4 & A5)(--> NANO1--< servo ballast(D10 sur NANO_AVANT) et periscope , recepteur voie 6 = (A0 sur NANO_ARRIERE)
Permet de mettre le servo ballast en position vidange si profondeur maxi depassee, prend la main sur la voie6 (A0 sur NANO_ARRIERE)
Permet de faire monter ou descendre le periscope en fonction de la profondeur
Permet de mettre le servo barre de plongee en position remontee si entree d eau detectee ou profondeur excesive, prend la main sur la voie3 (A1 sur NANO_ARRIERE & A1 sur NANO_AVANT)
Detecteur d eau (x2) (D5)--> NANO_ARRIERE--< servo ballast(D10 sur NANO_AVANT )
Permet de mettre le servo ballast en position vidange si entree d eau detectee, prend la main sur la voie 6 = (A0 sur NANO_ARRIERE)
Permet de mettre le servo barre de plongee en position remontee si entree d eau detectee ou profondeur excesive, prend la main sur la voie3 (A1 sur NANO_ARRIERE & A1 sur NANO_AVANT)
Relais et ILS--> NANO_ARRIERE--< moteur pompe periscope
2 Relais, (D8 & D9 sur NANO_ARRIERE) pour commande et inversion du moteur pompe
2 ILS, (D6 & D7 sur NANO_ARRIERE) Fin de course du periscope, coupe le moteur pompe periscope en fin de course
Alimentation autre que par l'arduino nano,avec un Ubec par exemple
Batterie (A6)--> NANO_ARRIERE--< Mesure tension
permet de lire la tension de la batterie et d enclencher une action
+ batterie ---> 1 resistance 3k3 -|
---> Pin A6 sur NANO_ARRIERE
- batterie ---> 1 resistance 1K1 -|
******
Donnees envoyees sur NANO_AVANT : <1;-3;16;2294;531;2000>
******
------Branchement NANO_ARRIERE---------------
recepteur voie 8 --> (A0)
recepteur voie 3 --> (A1)
recepteur voie 5 --> (A2)
BMP085 --> (A4,A5,5V)
MMA7361 --> (A7,5V)
tension Batterie --> (A6)
ILS --> (D6,D7)
Fuite --> (D5)
RX/TX <--> (RX/TX)
Relais <-- (D8,D9)
servo barre AR <-- (D10)
servo pese avant <-- (D11)
servo pese arriere <-- (D12)
LED RGB <-- (D2,D3,D4)
------Branchement NANO_AVANT---------------
recepteur voie 6 --> (A0)
recepteur voie 3 --> (A1)
recepteur voie 2 --> (A2)
CARD SD <--> (D10,D11,D12,D13,3v3)
RTC <--> (A4,A5,5V)
LCD <--> (A4,A5,5V)
RX/TX <--> (RX/TX)
Variateur <-- (D7)
servo ballast <-- (D8)
servo barre AV <-- (D9)
*/
#include <SoftwareSerial.h>
#include <Wire.h>
#include <SoftwareServo.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
SoftwareServo Servo_AV; // Declare le servo (D11 sur NANO_ARRIERE) accelerometre a l Avant
SoftwareServo Servo_AR; // Declare le servo (D12 sur NANO_ARRIERE) accelerometre a l Arriere
SoftwareServo Servo_Barre; // Declare le servo (D10 sur NANO_ARRIERE) barres de plongee
SoftwareSerial serial(0, 1); // RX, TX pour sur NANO_ARRIERE
//----------
int Alarm = 0;
int Alarm_old = 0;
long Tps_Data = 0; // Tps entre 2 envois serial
int neutre=1500; // Position manche au neutre
int Echelle= 0.013; // Echelle rapport profondeur/capteur de pression
//----------MMA7361----
int SR8 = A0; // Declare la variable (Signal_Recepteur voie 8) (Pin A0 sur NANO_ARRIERE)
int Val_SR8 = 0; // valeur du signal recepteur voie 8
const int MMA7361_X = A7; // declaration constante X de broche A7 accelerometre 3 axes MMA7361 (sorties analogiques) pour ARDUINO Nano
int Val_X = 0; // variable pour angle X accelerometre 3 axes MMA7361 (sorties analogiques)
/*alimentation du MMA7361 ainsi que les 2 servos en 3.3 volts via l'arduino niveau = 330
alimentation du MMA7361 ainsi que les 2 servos en 5 volts via l'arduino niveau = 580*/
int Val_MMA7361 = 0; // Valeur lu par le capteur
int Ang_Milieu = 595; // Valeur accelerometre1 quand niveau = 0
int Val_Servo_AV = 90; // valeur position servo Avant quand niveau = 0, 90 par defaut
int Val_Servo_AR = 90; // valeur position servo Arriere quand niveau = 0
int Vitesse_Servo_AV = 0; // Vitesse et sens du servo Avant(D11)
int Vitesse_Servo_AR = 0; // Vitesse et sens du servo Arriere(D12)
int Ang_AV = Ang_Milieu + 5; // Valeur denclenchement vers l'Avant du capteur
int Ang_AR = Ang_Milieu - 5; // Valeur denclenchement vers l Arriere du capteur
int CompteurA = 0; // Compteur
//----------BMP085----
int Temperature_Lu; // Temperature Lut par le capteur
int Pression_Surface; // Pression lut a la Surface par le capteur
int Pression_Lu; // Pression lut par le capteur
int Pression_Relative; // Difference de Pression entre la Surface et la Pression lut
long Pression_Max = 0; // Variable pour stocker la valeur Maxi lut sur le capteur de Pression pour faire la moyenne
long Pression_Min = 0; // Variable pour stocker la valeur Mini par sur le capteur de Pression pour faire la moyenne
int Profondeur_Max = 1916; // Declare la variable (Profondeur_Max) 479=6.25cm, 958=12.5cm, 1916=25cm, 3833=50cm , 7666= 1metre , 15352= 2metres
//----------Pour mesure tension batterie 12V
float Tension_Mini= 10; // Definir la tension mini de la batterie V=11.4
int NbrValeurs = 10; // Nombre de valeurs pour faire la moyenne
float Tensions[10]; // definir un tableau pour stoker valeurs tension
const float coeff_division = 4.37; // Coefficient diviseur du pont de resistance 4.37
float Tension = 14; // definir tension (batterie chargee)
int Compteur = 1; // Compteur du Tableau
long Tps_1 = 0; // Tps entre 2 mesures de tension
//----------Barre de plongee
int SR3 = A1; // Declare la variable (Signal_Recepteur voie 3) (Pin A1 sur NANO_ARRIERE)
int Val_SR3 = 0; // valeur du signal recepteur voie 3
int Ang_Servo_Barre = 90; // Declare la variable (Ang_Servo barre de plongee)
int Ang_Servo_Remonte = 135; // position servo barre pour remonter
int Alarm_Tps1 = 0; // Declencheur Tps barre de plongee
unsigned long tpsActuel1 = 0; // lira l'heure a chaque boucle
//----------2 x Relais Pompe a eau periscope----
int tpsPompe = 2000; // definir le temps maxi de fonctionnement de la pompe a 2 secondes
int Alarm_Tps2 = 0; // Temps de fonctionnement pompe a eau
unsigned long tpsActuel2 = 0; // lira l'heure a chaque boucle
int Relais_Haut = 9; // Definir pin relais pompe a eau (Pin D8 sur NANO_ARRIERE)
int Relais_Bas = 8; // Definir pin relais pompe a eau (Pin D9 sur NANO_ARRIERE)
int Periscope_Haut = 450; // Definir profondeur pour sortir le periscope 996=13cm (996/13*6=458)
int Periscope_Bas = 1916; // Definir profondeur pour rentrer le periscope 1916=25cm 1150=15cm
//----------Potar pour regler, modifier la Profondeur_Max----
int SR5 = A2; // Declare la variable (Signal_Recepteur voie 5) (Pin A2 sur NANO_ARRIERE)
int Val_SR5 = 0; // valeur du signal recepteur voie 5
int angle_potar = 0; // Declare la variable (Angle_potar emetteur voie 5) (Pin A2 sur NANO_ARRIERE)
int Profondeur_MaxR = Profondeur_Max; // Declare la variable (Profondeur_Max reglabe avec la voie 5)
//=======================================================================================================
void setup()
{
pinMode(Relais_Haut, OUTPUT); // Definir en sortie le relais_1 pompe a eau (Pin D9 sur NANO_ARRIERE)
pinMode(Relais_Bas, OUTPUT); // Definir en sortie le relais_2 pompe a eau (Pin D8 sur NANO_ARRIERE)
pinMode(6, INPUT);digitalWrite (6, HIGH); // signal periscope en bas (Pin D6 sur NANO_ARRIERE)
pinMode(7, INPUT);digitalWrite (7, HIGH); // signal periscope en haut (Pin D7 sur NANO_ARRIERE)
pinMode(SR8, INPUT); // signal entree du recepteur,broche A0 pour ARDUINO Nano1 (Voie 8, MMA7361 ON/OFF)
pinMode(2,OUTPUT); // led en sortie rouge (pin D2 sur NANO_AVANT)
pinMode(3,OUTPUT); // led en sortie verte (pin D3 sur NANO_AVANT)
pinMode(4,OUTPUT); // led en sortie bleu (pin D4 sur NANO_AVANT)
pinMode(5, INPUT);digitalWrite (5, HIGH); // signal detecteur entree eau dans compartiment,(Pin D5 sur NANO_ARRIERE)
pinMode(SR3, INPUT); // signal entree du recepteur, (Pin A1 sur NANO_ARRIERE) (Voie 3, Commande servo barre de plongee)
Servo_Barre.attach(10); // Attache le servo barre (Pin D10 sur NANO_ARRIERE)
pinMode(A3, INPUT);digitalWrite (A3, HIGH); // signal detecteur eau exter pour autoriser fonctionnement de la pompe,(Pin A3 sur NANO_ARRIERE)
Arret(); // Mettre les relais sur arret pompe
Masse_Stop(); // Servo_AV et AR Arret niveau
Remonte(); // servo barre en position remonte
//------------------- Calibration capteur de Pression pendant les 5 premieres secondes --------------------
bmp.begin();
Calibration();
Serial.begin(9600);
}
/* pour info:
Alarm = 0 : RAS -> LedVerte();
Alarm = 1 : Periscope Bas -> LedVerte();
Alarm = 2 : Periscope Haut -> LedVerte();
Alarm = 3 : Accelerometre -> LedBleu();
Alarm = 4 : Profondeur Maxi -> Vidange(); LedBleu();
Alarm = 5 : Barre de plongee -> Vidange(); LedRouge();
Alarm = 6 : Temperature -> Arret(); Vidange(); Remonte(); LedRouge();
Alarm = 7 : Batterie Faible -> Arret(); Vidange(); Remonte(); LedRouge();
Alarm = 8 : Perte de signal radio -> Arret(); Vidange(); Remonte(); LedRouge();
Alarm = 9 : Eau dans compartiment -> Arret(); Vidange(); Remonte(); LedRouge();
*/
//=========================================================================================================
void loop(){
//**************** Recuperer les donnees BMP085, Temperature, Tension 12v, detecteur d'eau ******************
Pression_Lu = bmp.readPressure(); Pression_Relative = Pression_Lu - Pression_Surface;
Val_X = analogRead(MMA7361_X); // capture de la variable mesuree en X sur accelerometre 3 axes MMA7361 (sorties analogiques)
MesureTension();
int Val_Signal_eau_1 = digitalRead(5); //-----Detection eau dans compartiments---------
int Val_Signal_eau_2 = digitalRead(A3); //-----Detection eau exter pour fonctionnement de la pompe periscope -------------
//*********Si Alarm < 4 repasse alarm = 0
if (Val_Signal_eau_1==HIGH && Tension>Tension_Mini && bmp.readTemperature()<40 && Pression_Relative < Profondeur_MaxR){Alarm = 0 ;}
//*********Si Relais descente periscope enclenche
if (Alarm < 1 && Relais_Bas == LOW) {Alarm = 1;}
//*********Si Relais montee periscope enclenche
if (Alarm < 2 && Relais_Haut == LOW) {Alarm = 2;}
//*********si accelerometre en action
if (Alarm < 3 && Val_SR8 >= 1700 && Val_SR8 <= 2100){Alarm = 3;}
//*********Si detection eau dans compartiments(pin D5 sur NANO_ARRIERE)
if (Alarm < 9 && Val_Signal_eau_1 == LOW){Alarm = 9;}
/*
//=============== Masquer les 3 lignes suivante si emetteur en PCM (FailSafe sur Emetteur)
if (Val_SR3 < 850 || Val_SR3 > 2200){Alarm = 8;}
if (Val_SR5 < 850 || Val_SR5 > 2200){Alarm = 8;}
if (Val_SR8 < 850 || Val_SR8 > 2200){Alarm = 8;}
*/
//*********Si Tension batterie Faible (pin A6 sur NANO_ARRIERE)
if (Alarm < 7 && Tension <= Tension_Mini){Alarm = 7;}
//*********Si temperature interieur compartiment arriere >39
if (Alarm < 6 && bmp.readTemperature()>= 40){Alarm = 6;}
//*********Si profondeur maxi depassee CAPTEUR DE Pression BMP085 (Pin A4 & A5 sur NANO_ARRIERE)
if (Pression_Relative < Profondeur_MaxR) {Alarm_Tps1 = 0;}
if (Alarm < 4 && Pression_Relative > Profondeur_MaxR) {Alarm = 4;}
//*********Temps pour mettre en vidange rapide & barre de plongee en remontee defini a 10 secondes
if (Alarm_Tps1 == 0) {tpsActuel1 = millis()+10000; Alarm_Tps1 = 1;}
if (Alarm < 5 && Alarm_Tps1 == 1 && tpsActuel1 < millis()){Alarm = 5; Remonte();}
//***** Definir nouvelle profondeur maxi avec la telecommande (Pin A2 sur NANO_ARRIERE)
if (Alarm >= 6){ // si probleme redefinir profondeur MaxiR a la profondeur de depart du setup
Profondeur_MaxR = Profondeur_Max;
}else{
Val_SR5 = pulseIn(SR5, HIGH, 30000); // Donne a la variable (Val_SignalReglage) la valeur du SR5 (pin A2 sur NANO_ARRIERE)
angle_potar = map(Val_SR5, neutre-500,neutre+500, 1, 30); // Calibre des valeurs du potar voie 7 de 1 a 30 (30 graduations sur le potar)
angle_potar = constrain(angle_potar, 1, 30); // Fixe les valeurs minimum et maximum du potar
Profondeur_MaxR = 479 * angle_potar; // definir la profondeur maxi demandee avec la voie 7 (1 graduation = 479 = 6.25centimetres)
}
//***** Commande BARRE DE PLONGEE (Pin A1 sur NANO_ARRIERE)--> (Pin D10 sur NANO_ARRIERE)
if (Alarm < 4){ // si profondeur OK
Val_SR3 = pulseIn(SR3, HIGH, 30000); // Donne a la variable (Val_SR3) la valeur du Signal Recepteur3 (pin A1 sur NANO_ARRIERE)
if (Val_SR3 >= 900 && Val_SR3 <= 2100){ // si impultions comprisent entre 1000 et 2000 (pin A1 sur NANO_ARRIERE)
Ang_Servo_Barre = map(Val_SR3, neutre-500,neutre+500, 45, 135); // Calibre des valeurs pour le servo barre de 45 a 135
Ang_Servo_Barre = constrain(Ang_Servo_Barre, 45, 135); // Fixe les valeurs minimum et maximum en degre du servo ballast
Servo_Barre.write(Ang_Servo_Barre); delay(10);SoftwareServo::refresh(); // Positionne le servo suivant les ordes de la radiocommande
}
}
//************************* Periscope et Relais pour pompe a eau (Relais= Pin D8 & D9 sur NANO_ARRIERE) (ILS= pin D6 & D7 sur NANO_ARRIERE)
// !!!! ne pas alimenter la platine relais avec l'arduino nano, prendre l alimentation du recepteur
if (Val_Signal_eau_2 == LOW){ //Si la pompe est sous le niveau de l eau (Pin A3 sur NANO_ARRIERE) (contact sur flasque avant)
int Val_ILS_Haut = digitalRead(6); int Val_ILS_Bas = digitalRead(7); //Lire les valeurs des 2 ILS
int Relais_Haut = digitalRead(9); int Relais_Bas = digitalRead(8); //Lire les valeurs des 2 relais
if (Alarm_Tps2 == 1 && (Val_ILS_Haut == LOW || Val_ILS_Bas == LOW)) { Alarm_Tps2 = 0;} //si 1 des 2 ILS est contacte(periscope en position haut ou bas) et alarmTps2 = 1,remettre Alarm_Tps2 a 0
if (millis() > tpsActuel2 && (Relais_Haut == LOW || Relais_Bas == LOW)) { Alarm_Tps2 = 1; Arret();} //si un des 2 relais est enclenche depuis plus de X secondes, sans contact dun ILS, couper les relais
// code pour arreter la pompe du periscope en navigation
if (Alarm < 4 ){ // code pour arreter la pompe
if (Pression_Relative > Periscope_Haut && Pression_Relative < Periscope_Bas && Val_ILS_Haut == LOW ) {Arret();} // si >450 et <1900 et Contact fin de course ILS_haut , arreter la pompe du periscope
if ((Pression_Relative > Periscope_Bas || Pression_Relative < Periscope_Haut) && Val_ILS_Bas == LOW ) {Arret();} // si >1900 ou <450 et si Contact fin de course ILS_bas , arreter la pompe le periscope
}
// code pour actionner la pompe du periscope en navigation
if (Alarm_Tps2 == 0 && Alarm < 4 && Relais_Haut == HIGH && Relais_Bas == HIGH){ //si temps de fonctionnement pas depasse et alarm <4 et si relais au repos
if (Pression_Relative > Periscope_Haut && Pression_Relative < Periscope_Bas && Val_ILS_Haut == HIGH ) {Monte();} // si >450 et <1900 et pas de Contact fin de course ILS_Haut faire monter le periscope
if ((Pression_Relative > Periscope_Bas || Pression_Relative < Periscope_Haut) && Val_ILS_Bas == HIGH) {Descent();} // si >1900 ou <450 et Contact fin de course ILS_bas faire descendre le periscope
tpsActuel2 = millis()+tpsPompe; // definir le temps maxi de fonctionnement de la pompe a 3 secondes
}
}
//************ ACCELEROMETRE MMA7361 (pesee du sous-marin, deplacement de masse) (Pin A7 sur NANO_ARRIERE)
if (Alarm < 4 && (Pression_Relative >Periscope_Haut && Pression_Relative <Periscope_Bas)){ // seulement si sous-marin est sous la surface de l eau entre 13cm et 25cm
Val_SR8 = pulseIn(SR8, HIGH, 30000); // Donne a la variable (Val_SR8) la valeur du Signal Recepteur8 (pin A0 sur NANO_ARRIERE)
if (Val_SR8 >= 1800 && Val_SR8 <= 2100){ // si impultions comprisent entre 1500 et 2000 (Pin A0)
Alarm = 3;
Val_X = analogRead(MMA7361_X); // capture de la variable mesuree en X sur accelerometre 3 axes MMA7361
if (Val_X <= Ang_AV && Val_X >= Ang_AR){ Masse_Stop();} // Stop les masses
if (Val_X > Ang_AV) { Masse_AV();} // deplace les masses vers l avant
if (Val_X < Ang_AR) { Masse_AR();} // deplace les masses vers l arriere
Servo_AV.write(Vitesse_Servo_AV); Servo_AR.write(Vitesse_Servo_AR); SoftwareServo::refresh();
}else{ // si pas de signal accelerometre moteur arret
Masse_Stop(); // Servo_AV et AR Arret
}
}else{ // si profondeur non autorise
Masse_Stop(); // Servo_AV et AR Arret
}//---FIN ACCELEROMETRE MMA7361
//*******Si la valeur de Alarm change actions a faire
if (Alarm != Alarm_old){
Alarm_old = Alarm;
Data(); // envoi donnees
switch (Alarm) {
case 0: // RAS
LedVerte();
break;
case 1: // Periscope Bas
LedVerte();
break;
case 2: // Periscope Haut
LedVerte();
break;
case 3: // Accelerometre
LedBleu();
break;
case 4: // Profondeur Maxi
LedBleu();Masse_Stop();
break;
case 5: // barre de plongee
LedRouge();
Arret(); Remonte();Masse_Stop();
break;
case 6: // Temperature
LedRouge();Arret();Remonte();Masse_Stop();
break;
case 7: // Batterie Faible
LedRouge();
Arret(); Remonte();Masse_Stop();
break;
case 8: // Perte de signal radio
LedRouge();
Arret(); Remonte();Masse_Stop();
break;
case 9: // Eau dans compartiment
LedRouge();
Arret(); Remonte();Masse_Stop();
break;
//default: // cas par defaut
}
}//---FIN Si la valeur de Alarm change
//------Envoyer valeurs sur serial toutes les 30 secondes
if (millis() > Tps_Data) {
Tps_Data = millis() + 30000; //Definir 30 secondes entre 2 envois = 30000
Data();}//---FIN d Envoye valeurs sur serial
}//*************** FIN PROGRAMME
//************************* routines
void Data(){ //pour envoi serial
Serial.print("<");
Serial.print(Alarm);Serial.print(";");
Serial.print(Val_X - Ang_Milieu);Serial.print(";");
Serial.print(Pression_Relative);Serial.print(";");
Serial.print((bmp.readTemperature()*100),0);Serial.print(";");
Serial.print((Tension*100),0);Serial.print(";");
Serial.print(Profondeur_MaxR);
Serial.print(">");
Serial.println();
}
void Monte(){ // Relais_Haut etat bas ,Relais_Bas etat haut , Pompe Sens Horaire monter du periscope
digitalWrite (Relais_Bas, HIGH); digitalWrite (Relais_Haut, LOW);
}
void Descent(){ // Relais_Haut etat Haut ,Relais_Bas etat bas , Pompe Sens anti-Horaire descente du periscope
digitalWrite (Relais_Haut, HIGH); digitalWrite (Relais_Bas, LOW);
}
void Arret(){ // Relais_Haut etat haut , Relais_Bas etat haut, Pompe Stop
digitalWrite (Relais_Haut, HIGH); digitalWrite (Relais_Bas, HIGH);
}
void Remonte(){ // Servo en position remonte
Servo_Barre.write(Ang_Servo_Remonte); SoftwareServo::refresh(); delay(0);
}
void Masse_AR(){ // deplace les masses vers l arriere
if (Servo_AV.attached()==0){ Servo_AV.attach(11);} // Attache le servo_AV continue (Pin D11 sur NANO_ARRIERE)
if (Servo_AR.attached()==0){ Servo_AR.attach(12);} // Attache le servo_AR continue (Pin D12 sur NANO_ARRIERE)
Vitesse_Servo_AV=Val_Servo_AV+30; Vitesse_Servo_AR=Val_Servo_AR-40;
}
void Masse_AV(){ // deplace les masses vers l avant
if (Servo_AR.attached()==0){ Servo_AR.attach(12);} // Attache le servo_AR continue (Pin D12 sur NANO_ARRIERE)
if (Servo_AV.attached()==0){ Servo_AV.attach(11);} // Attache le servo_AV continue (Pin D11 sur NANO_ARRIERE)
Vitesse_Servo_AV=Val_Servo_AV-30; Vitesse_Servo_AR=Val_Servo_AR+40;
}
void Masse_Stop(){ // Stop les masses
if (Servo_AV.attached()==1){Servo_AV.detach();} // Detache le servo_AV continue (Pin D11 sur NANO_ARRIERE)
if (Servo_AR.attached()==1){Servo_AR.detach();} // Detache le servo_AR continue (Pin D12 sur NANO_ARRIERE)
}
void Calibration(){ // Calibration du BMP085 pour definir le O Surface pendant les 15 premieres secondes
LedBleu();
Pression_Max = bmp.readPressure(); // valeur lut par le capteur de Pression (definir une valeur Pression Max )
Pression_Min = Pression_Max; // Definir une valeur Pression Min = Pression Max
while (millis() < 15000) { //15 secondes
Pression_Surface = bmp.readPressure(); //Stocker la valeur du CAPTEUR Pression dans la variable "Pression_Surface"
if (Pression_Surface > Pression_Max) { Pression_Max = Pression_Surface;} // Enregistre la valeur Max lut par le capteur de Pression
if (Pression_Surface < Pression_Min) { Pression_Min = Pression_Surface;} // Enregistre la valeur Min lut par le capteur de Pression
Val_MMA7361 = Val_MMA7361 + analogRead(MMA7361_X); // valeur lut par le capteur MMA7361_X
CompteurA = CompteurA + 1;
}
//-------------------- definir valeur moyenne du capteur de Pression
if (Pression_Max > Pression_Min) {Pression_Surface = Pression_Max-((Pression_Max-Pression_Min)/2);} // defini la Pression moyenne en Surface
if (Pression_Max == Pression_Min) {Pression_Surface = Pression_Max;} // prend la Pression max en Surface si pression min = pression max
//-------------------- definir valeur moyenne du capteur MMA7361
Ang_Milieu = Val_MMA7361/(CompteurA);
LedVerte();
} //---------------------fin calibration capteur de Pression et accelerometre
void MesureTension(){//------MESURE TENSION BATTERIE 12Volts (moyenne de 10 mesures) toutes les secondes
// definir un tableau pour stoker valeurs tension}
if (millis() > Tps_1) { // Enregistre la tension toutes les X secondes
unsigned int Tension_Mesure = analogRead(A6); // Mesure de la tension brute avec le pin A6 de l'arduino
Tensions[Compteur] = ((Tension_Mesure * (5.0 / 1024)) * coeff_division); // Calcul de la tension reel
if (Compteur == NbrValeurs){ // Si X valeurs dans le tableau, fait la moyenne des X valeurs
int i; for (i = 1; i < Compteur; i = i + 1) { Tension = Tension + Tensions[i];}
Tension = Tension / Compteur; Compteur = 0; // remet le compteur du tableau a 1
}
Compteur = Compteur + 1; Tps_1 = millis() + 1000;} //Definir le Tps entre 2 mesures
}//---FIN MESURE TENSION BATTERIE 12Volts
void LedRouge(){
digitalWrite(3, LOW); digitalWrite(4, LOW); digitalWrite(2, HIGH); // allume la LED rouge
}
void LedVerte(){
digitalWrite(2, LOW); digitalWrite(3, LOW); digitalWrite(4, HIGH); // allume la LED verte
}
void LedBleu(){
digitalWrite(2, LOW); digitalWrite(4, LOW); digitalWrite(3, HIGH); // allume la LED Bleu
}
Programme de l'arduino UNO avant
Code : Tout sélectionner
/* --- Programme Arduino version 1.0.5--- 04/06/2014
carte Arduino Nano AVANT (Nano_Avant.ino)
**************************
Commande le servo Ballast (Pin D8) avec delai de fonctionnement pompe,securite profondeur,Tension,temperature
Commande le servo barre Avant (Pin D9) avec securite de profondeur,tension,temperature
Commande le Variateur (Pin D7) avec securite de profondeur,tension,temperature
Ecrire les donnes sur carte SD (Pin D10,D11,D12,D13,3v3)
Ecrire les donnes sur Ecran LCD (Pin A4,A5,5V)
Gerer l'heure d'ecriture (Horloge RTC) (Pin A4,A5,5V)
Recevoir les Numeros d ALARM et valeurs capteurs de la carte Nano ARRIERE
******
Donnees recues de NANO_ARRIERE : <1;-3;16;2294;1194;2000;> <alarm;niveau;profondeur;temperature;voltage;profondeurpotar>
******
------Branchement NANO_ARRIERE---------------
recepteur voie 8 --> (A0) MMA7361 accelerometre
recepteur voie 3 --> (A1) Barre de plongee arriere
recepteur voie 5 --> (A2) Potar pour regler, modifier la Profondeur_Max
BMP085 --> (A4,A5,5V)
MMA7361 --> (A7,5V)
tension Batterie --> (A6)
ILS --> (D6,D7)
Fuite --> (D5)
RX/TX <--> (RX/TX)
Relais <-- (D8,D9)
servo barre AR <-- (D10)
servo pese avant <-- (D11)
servo pese arriere <-- (D12)
LED RGB <-- (D2,D3,D4)
------Branchement NANO_AVANT---------------
recepteur voie 6 --> (A0) servo ballast
recepteur voie 3 --> (A1) Barre de plongee Avant
recepteur voie 2 --> (A2) Variateur
Capteur MPX10GP --> (A3) Rajout le 25/03/2014, mesure pression dans ballast
CARD SD <--> (D10,D11,D12,D13,3v3)
RTC <--> (A4,A5,5V) pas utilis�
LCD <--> (A4,A5,5V) pas utilis�
RX/TX <--> (RX/TX)
Variateur <-- (D7)
servo ballast <-- (D8)
servo barre AV <-- (D9)
*/
//------- Ecran LCD
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4); // set the LCD address to 0x27 20 caracteres et 4 lignes ecran
//------- Fin Ecran LCD
#include <SoftwareServo.h>
#include <SD.h>
#define SD_CARD_CD_DIO 10 // DIO broche D10 utilisee pour commander le module SD, broche CS */
SoftwareServo Servo_Ballast; // Declare le servo (Pin D8 sur NANO_AVANT) servo ballast
SoftwareServo Servo_Barre; // Declare le servo (Pin D9 sur NANO_AVANT) barres de plongee AVANT
SoftwareServo Variateur; // Declare le vaiateur (Pin D7 sur NANO_AVANT) moteur Propultion
File SDFileData;
//----------
int EcrireSurSD = 1; // 1= sortie sur carte SD, 0 = Pas de sortie sur carte SD
int EcrireSurLCD = 0; // 1= sortie sur LCD, 0 = Pas de sortie sur LCD
int Alarm = 4; //= 4 pour mettre LedBleu,Calibration sur Nano1 debut sequence
int neutre=1500; // Position manche au neutre
int Echelle= 0.013; // Echelle rapport profondeur/capteur de pression
//----------
String Trame; // Chaine pour contenir la Trame entrante
boolean TrameRecu = false; // si la Trame a ete recue dans son integralite
int NbrData = 6; // Nombre de donnes qui seront recus
long Jours=0; // Chaine pour contenir les jours
long heures=0; // Chaine pour contenir les heures
long minutes=0; // Chaine pour contenir les minutes
long secondes=0; // Chaine pour contenir les minutes
//----------Servo Ballast
int SR6 = A0; // Declare la variable (Signal_Recepteur voie 6) (pin A0 sur NANO_AVANT)
int Val_SR6 = 0; // valeur du signal recepteur voie 6
int Ang_Servo_Ballast = 45; // Declare la variable (Ang_Servoballast)
int Ang_Servo_VidangeR = 45; // position servo vidange rapide (Pin D8 sur NANO_AVANT)
int Ang_Servo_VidangeL = 65; // position servo vidange lente (Pin D8 sur NANO_AVANT)
int Ang_Servo_Ballast_max = 130; // position maxi servo vidange (Pin D8 sur NANO_AVANT) (130=pompe)
int Ang_Servo_Ballast_min = 45; // position mini servo vidange (Pin D8 sur NANO_AVANT)
//----------Barre de plongee Avant et arriere
int SR3 = A1; // Declare la variable (Signal_Recepteur voie 3) (Pin A1 sur NANO_AVANT)
int Val_SR3 = 0; // valeur du signal recepteur voie 3
int Ang_Servo_Barre = 90; // Declare la variable (Ang_Servo barre de plongee)
int Ang_Servo_Remonte = 135; // position servo barre pour remonter
//----------Variateur
int SR2 = A2; // Declare la variable (Signal_Recepteur voie 2) (Pin A2 sur NANO_AVANT)
int Val_SR2 = 0; // valeur du signal recepteur voie 2
int PuissanceM= 0; // Declare la variable (variation)
int Puissance0= 90; // Declare la variable (point mort)
//----------Capteur MPX10GP (Valeur theorique du Signal_MPX10GP = 495 a 525)
int Signal_MPX10GP = A3; // Declare la variable (Signal_MPX10GP) (Pin A3 sur NANO_AVANT)
int Val_Signal_MPX10GP; // Variable pour stocker la valeur lue sur le capteur de pression MPX10GP
//=======================================================================================================
void setup(){
pinMode(10,OUTPUT); // Sortie CS de la Carte SD
pinMode(SR2, INPUT); // signal recepteur, (pin A2 sur NANO_AVANT) (Voie 2, Commande Variateur)
pinMode(SR3, INPUT); // signal recepteur, (pin A1 sur NANO_AVANT) (Voie 3, Commande servo barre de plongee Avant)
pinMode(SR6, INPUT); // signal recepteur, (pin A0 sur NANO_AVANT) (Voie 6, Commande servo ballast)
pinMode(Signal_MPX10GP, INPUT); // signal Capteur MPX10GP (pin A3 sur NANO_AVANT)
Variateur.attach(7); // Attache le Variateur moteur (Pin D7 sur NANO_AVANT)
Servo_Ballast.attach(8); // Attache le servo ballast (Pin D8 sur NANO_AVANT)
Servo_Barre.attach(9); // Attache le servo barreAV (Pin D9 sur NANO_AVANT)
Serial.begin(9600);
//------- Ecran LCD
if (EcrireSurLCD == 1){;
lcd.init(); lcd.init(); lcd.backlight(); // Initialiser le lcd
lcd.setCursor(0,2); lcd.print("calibration capteur"); //position 0,ligne 2
lcd.setCursor(0,3); lcd.print("pendant 15s ......."); //position 0,ligne 3
} //-------Fin Ecran LCD
//-------carte SD
if (EcrireSurSD == 1){;
if (!SD.begin(SD_CARD_CD_DIO)){ // Initialise la SD carte
if (EcrireSurLCD == 1){lcd.setCursor(0,0); lcd.print("ERROR: SD card");} //position 0,ligne 0
}else{
if (EcrireSurLCD == 1){lcd.setCursor(0,0); lcd.print("SD Card OK");} //position 0,ligne 0
}
SDFileData = SD.open("HMS_S107.txt", FILE_WRITE);
if (SDFileData){; // Si le fichier est bien present
SDFileData.println();
SDFileData.print("Nouvelle navigation");
SDFileData.println();
SDFileData.close(); // Ferme le fichier
}
//----suppression du fichier si il existe deja
/*while(SD.exists("HMS_S107.txt")){ // Verifiez si le fichier texte existe deja
Serial.println("HMS_S107.txt existe deja ... SUPPRESSION");
SD.remove("HMS_S107.txt");} //Si oui, alors le supprimer
*/
//while (1);
} //-------Fin EcrireSurSD
}
//=========================================================================================================
void loop() {
/*
//================== Masquer les 3 lignes suivante si emetteur en PCM (FailSafe sur Emetteur)
if (Val_SR2 < 850 || Val_SR2 > 2200){Alarm = 8;}
if (Val_SR3 < 850 || Val_SR3 > 2200){Alarm = 8;}
if (Val_SR6 < 850 || Val_SR6 > 2200){Alarm = 8;}
*/
//***** Commande BARRE DE PLONGEE AVANT (Pin A1 sur NANO_AVANT)--> (Pin D9 sur NANO_AVANT)
Val_SR3 = pulseIn(SR3, HIGH, 30000); // Donne a la variable (Val_SR3) la valeur du Signal Recepteur
if (Alarm < 4){ // si profondeur OK
if (Val_SR3 >= 900 && Val_SR3 <= 2100){ // si impultions comprisent entre 900 et 2100 (pin A1 sur NANO_AVANT)
Ang_Servo_Barre = map(Val_SR3, neutre-500,neutre+500, 45, 135); // Calibre des valeurs de pour le servo barre de 45 a 135
Ang_Servo_Barre = constrain(Ang_Servo_Barre, 45, 135); // Fixe les valeurs minimum et maximum en degre du servo
Servo_Barre.write(Ang_Servo_Barre);delay(10); SoftwareServo::refresh(); // Positionne le servo suivant les ordes de la radiocommande
}
}
//***** Commande variateur moteur (Pin A2 sur NANO_AVANT)--> (Pin D7 sur NANO_AVANT)
Val_SR2 = pulseIn(SR2, HIGH, 30000); // Donne a la variable (Val_SR2) la valeur du Signal Recepteur variateur
if (Val_SR2 >= 900 && Val_SR2 <= 2100){ // si impultions comprisent entre 900 et 2100 (pin A2 sur NANO_AVANT)
PuissanceM = map(Val_SR2, neutre-500,neutre+500, 45, 135); // Calibre des valeurs pour le Variateur
if (Alarm <= 5) {PuissanceM = constrain(PuissanceM, 45, 135);} // si OK puissance variateur normal
if (Alarm > 5) {PuissanceM = constrain(PuissanceM, 60, 110);} // si Batterie Faible ou temperature eleve reduire puissance variateur
if (Alarm == 8) {PuissanceM = Puissance0;} // si perte de reception variateur = 0
Variateur.write(PuissanceM);delay(10); SoftwareServo::refresh(); // Positionne le Variateur suivant les ordes de la radiocommande
}
//***** Commande servo Ballast (pin A0 sur NANO_AVANT) --> (Pin D10 sur NANO_AVANT)
Val_Signal_MPX10GP = analogRead(Signal_MPX10GP); // Lit la valeur du Capteur de pression
if (Val_Signal_MPX10GP > 550) { //Si pression capteur > 505 a 550
Alarm = 5; // mettre Servo en position vidange Rapide pour faire chutter la pression dans le ballast
}else{ // Si pression capteur < pression d air trop forte dans le ballast
// Commande servo Ballast (pin A0 sur NANO_AVANT) --> (Pin D10 sur NANO_AVANT)
Val_SR6 = pulseIn(SR6, HIGH, 30000); // Donne a la variable (Val_SR6) la valeur du Signal Recepteur
if (Alarm < 4){ // si OK
if (Val_SR6 >= 900 && Val_SR6 <= 2100){ // si impultions comprisent entre 900 et 2100 (pin A0 sur NANO_AVANT)
Ang_Servo_Ballast = map(Val_SR6, neutre-500,neutre+500, Ang_Servo_Ballast_min, Ang_Servo_Ballast_max); // Calibre des valeurs de pour le servo ballast de 45 a 130 (130 = pompe)
Ang_Servo_Ballast = constrain(Ang_Servo_Ballast, Ang_Servo_Ballast_min, Ang_Servo_Ballast_max); // Fixe les valeurs minimum et maximum en degre du servo ballast
Servo_Ballast.write(Ang_Servo_Ballast);delay(10);SoftwareServo::refresh(); // Positionne le servo suivant les ordes de la radiocommande
}
}
}
//*******Si la valeur de Alarm change actions a faire
switch (Alarm) {
case 0: // RAS
//LedVerte();
break;
case 1: // Periscope Bas
//LedVerte();
break;
case 2: // Periscope Haut
//LedVerte();
break;
case 3: // Accelerometre
//LedBleu();
break;
case 4: // Profondeur Maxi
//LedBleu();
VidangeL();
break;
case 5: // barre de plongee Avant
//LedRouge();
VidangeR();Remonte();
break;
case 6: // Temperature
//LedRouge()
VidangeR();Remonte();
break;
case 7: // Batterie Faible
//LedRouge();
VidangeR();Remonte();
break;
case 8: // Perte de signal radio
//LedRouge();
MoteurStop();VidangeR();Remonte();
break;
case 9: // Eau dans compartiment
//LedRouge();
VidangeR();Remonte();
break;
default: // cas par defaut
//LedVerte();
break;
}
handleCommand();
} //*************** FIN PROGRAMME
//************************* routines
void serialEvent(){
while (Serial.available()) {// si recois des donnees serial TX/RX
char incomingByte = (char)Serial.read();
if (incomingByte == '>'){ // Fin de la Trame
TrameRecu = true;
return;
}else if (incomingByte == '<'){ // Debut d une nouvelle Trame
Trame = "";
TrameRecu = false;
return;
}else{
Trame += incomingByte;
return;
}
}
}
void handleCommand() {
if (!TrameRecu) return; // aucune Trame a parser
int data[NbrData]; // un maximum de 6 nombres entiers de donnees
char cmd[Trame.length()+1];
Trame.toCharArray(cmd, Trame.length()+1);
char *token = strtok(cmd, ";");
for (int i = 0; i < NbrData; i++) { // mettre datas dans tableau
if (token) {
data[i] = atoi(token);
token = strtok(NULL, ";");
}
}
Alarm = data[0];
//------- Ecrire sur LCD
if (EcrireSurLCD == 1){;
lcd.setCursor(6,0);lcd.print(" "); //position 6,ligne 0
lcd.setCursor(0,0);lcd.print("Alarm:"); //position 0,ligne 0
lcd.setCursor(6,0);lcd.print(data[0]); //position 6,ligne 0
lcd.setCursor(15,0);lcd.print(" "); //position 15,ligne 0
lcd.setCursor(9,0); lcd.print("Angle:"); //position 9,ligne 0
lcd.setCursor(15,0);lcd.print(data[1]); //position 15,ligne 0
lcd.setCursor(6,1); lcd.print(" "); //position 6,ligne 1
lcd.setCursor(0,1); lcd.print("Depth:"); //position 0,ligne 1
lcd.setCursor(6,1); lcd.print((data[2]*0.013)/100); //position 6,ligne 1
if (((data[2]*0.013)/100) >= 0){; //gerer le signe negatif
lcd.setCursor(10,1);lcd.print("m"); //position 10,ligne 1
}else{
lcd.setCursor(11,1);lcd.print("m"); //position 11,ligne 1
}
lcd.setCursor(15,1);lcd.print(" "); //position 15,ligne 1
lcd.setCursor(15,1);lcd.print((data[5]*0.013)/100); //position 15,ligne 1
lcd.setCursor(19,1);lcd.print("m"); //position 19,ligne 1
lcd.setCursor(12,2);lcd.print(" "); //position 12,ligne 2
lcd.setCursor(0,2); lcd.print("Temperature:"); //position 0,ligne 2
lcd.setCursor(12,2);lcd.print(data[3]/100);lcd.print(".");lcd.print(data[3]%100); //position 12,ligne 2
lcd.setCursor(8,3);lcd.print(" "); //position 8,ligne 3
lcd.setCursor(0,3);lcd.print("Voltage:"); //position 0,ligne 3
lcd.setCursor(8,3);lcd.print(data[4]/100);lcd.print(".");lcd.print(data[4]%100); //position 8,ligne 3
Val_Signal_MPX10GP = analogRead(Signal_MPX10GP); // Lit la valeur du Capteur de pression
lcd.setCursor(15,3);lcd.print("P:"); //position 12,ligne 3
lcd.setCursor(17,3);lcd.print(Val_Signal_MPX10GP); //pression dans ballast (rajoute le 05/04/2014)
}//------- Fin Ecran LCD
//---Ecriture sur carte SD
if (EcrireSurSD == 1){;
CalculTemps();
SDFileData = SD.open("HMS_S107.txt", FILE_WRITE);
//if (EcrireSurLCD == 1){lcd.setCursor(14,3);lcd.print("Envoi");} //position 14,ligne 3
if (SDFileData){; // Si le fichier est bien present
SDFileData.print(heures);SDFileData.print(":");SDFileData.print(minutes);SDFileData.print(":");SDFileData.print(secondes);SDFileData.print(";"); // heure
SDFileData.print(data[0]);SDFileData.print(";"); //Alarm
SDFileData.print(data[1]);SDFileData.print(";"); //Niveau
SDFileData.print((data[2]*0.013)/100);SDFileData.print(";"); //mesure capteur profondeur rapporte en m
SDFileData.print(data[3]/100);SDFileData.print(".");SDFileData.print(data[3]%100);SDFileData.print(";"); //Temperateur
SDFileData.print(data[4]/100);SDFileData.print(".");SDFileData.print(data[4]%100);SDFileData.print(";"); //Voltage
SDFileData.print((data[5]*0.013)/100);SDFileData.print(";"); //profondeur demandee rapporte en m
SDFileData.print(PuissanceM-90);SDFileData.print(";"); //puissance moteur (rajoute le 19/02/2014)
Val_Signal_MPX10GP = analogRead(Signal_MPX10GP); // Lit la valeur du Capteur de pression
SDFileData.println(Val_Signal_MPX10GP); //pression dans ballast (rajoute le 05/04/2014)
SDFileData.close(); // Ferme le fichier
//if (EcrireSurLCD == 1){lcd.setCursor(14,3);lcd.print(" ");} //position 14,ligne 3
}//---Fin Ecriture sur carte SD
}
TrameRecu = false;// Pour dire que nous avons traite la commande
}//---Fin handleCommand
void VidangeR(){ // Servo en position vidange rapide = 45 degres
Servo_Ballast.write(Ang_Servo_VidangeR); SoftwareServo::refresh(); delay(0);
}
void VidangeL(){ // Servo en position vidange lente = 65 degres
Servo_Ballast.write(Ang_Servo_VidangeL); SoftwareServo::refresh(); delay(0);
}
void Remonte(){ // Servo avant en position remonte = 135 degres
Servo_Barre.write(Ang_Servo_Remonte); SoftwareServo::refresh(); delay(0);
}
void MoteurStop(){ // Variateur stop
Variateur.write(Puissance0); SoftwareServo::refresh(); delay(0);
}
void CalculTemps() { //-------------- Calcul du temps pour affichage
secondes = millis()/1000; //convertir millisecondes en secondes
minutes=secondes/60; //convertir secondes en minutes
heures=minutes/60; //convertir minutes en heures
Jours=heures/24; //convertir heures en Jours
secondes=secondes-(minutes*60); //soustraire les secondes converties afin d'afficher 59 secondes max
minutes=minutes-(heures*60); //soustraire les minutes converties afin d'afficher 59 minutes max
heures=heures-(Jours*24); //soustraire les heures converties afin d'afficher 59 heures max
Serial.print(heures);Serial.print(":");Serial.print(minutes);Serial.print(":");Serial.print(secondes);Serial.println(";");
}//----FIN Calcul du temps pour affichage