Bonjour,

Je travaille actuellement sur un projet de pilote automatique de bateau à base de Raspberry et Arduino J'ai installé sur le Raspberry la distribution OpenPlotter qui me fournit entre autre la dernière version de l'incontournable logiciel de navigation OpenCpn. Sur lequel, je peux tracer au port la route que je compte suivre lors de la navigation. Lorsque j'active cette route, Opencpn me donne entre autres le cap vers le prochain waypoint. Mon idée est de récupérer ce cap, de l'envoyer à un Arduino qui le transformerait en impulsions à destination du pilote automatique (un ancien autohelm 4000 dont on peut faire varier le cap par impulsions sur des boutons +10 ,-10,+1 et -1.
L'Arduino reçoit donc par le port usb connecté au Raspberry une indication de cap qui sera convertie en impulsions à destination des boutons du pilote.
Le programme du Raspberry est entièrement compris dans OpenCpn qui m'envoie une trame $ECAPB comprenant entre autres le cap à suivre, dès qu'il est en mode 'suivi de route'
Du côté de l'Arduino, j'ai imaginé le programme suivant qui récupère les infos du Raspberry par la trame ECAPB, effectue des calculs pour définir l'angle de correction à apporter ainsi que sa direction (Babord ou Tribord)*. Pour l'instant en phase d'essais à terre, j'ai associé les impulsions destinées au pilote à des leds pour pouvoir les contrôler visuellement*; par la suite, ces leds seront remplacées par des triacs montés en interrupteurs*!. Ce programme est le suivant*:

Code 'compas_pilote_nokia' :
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include <LCD5110_Basic.h>
String sen;
 
LCD5110 myGLCD(
    13, 11, 9, 8,
    10); /*  (CLK,DIN,DC,RST,CE)  initialisation d'un écran lcd 5110 Nokia*/
extern uint8_t SmallFont[];
extern uint8_t MediumNumbers[];
 
#include <TinyGPS++.h> //pour parser le phrase nmea reçue.
TinyGPSPlus gps;
TinyGPSCustom ang(gps, "ECAPB", 11);
// TinyGPSCustom dir(gps, "ECAPB",4);
int temp = 0;
int val = 0;
int comp = 0;
bool flag = true;
bool tempo = false;
const int red = 2;
const int green = 3;
const int plusdix = A2;
const int moinsdix = 5;
const int plusun = 6;
const int moinsun = 7;
const int pin = A0;
int dif;
int res;
unsigned long depart = millis();
 
void setup() {
    pinMode(red, OUTPUT);
    pinMode(green, OUTPUT);
    pinMode(plusdix, OUTPUT);
    pinMode(moinsdix, OUTPUT);
    pinMode(plusun, OUTPUT);
    pinMode(moinsun, OUTPUT);
    pinMode(pin, INPUT_PULLUP);
    myGLCD.InitLCD();
    myGLCD.setFont(SmallFont);
    Serial.begin(4800);
    myGLCD.print("Pilote", CENTER, 0);
    myGLCD.print("en attente", CENTER, 16);
 
    myGLCD.print("d\'ordres!", CENTER, 32);
}
void loop() {
    bool lu = digitalRead(pin);
    char sens;
    digitalWrite(red, LOW); //-Initialisation des impulsions à 0--------->
    digitalWrite(green, LOW);
    digitalWrite(plusdix, LOW);
    digitalWrite(moinsdix, LOW);
    digitalWrite(moinsdix, LOW);
    digitalWrite(moinsun, LOW);
    comp = gps.course.deg(); //-----------reception du cap-------------->
    // if (strcmp(dir.value(),"R")==0)
    // sens='T';
    // if (strcmp(dir.value(),"L")==0)
    // sens='B';
    if (ang.isUpdated()) {
        // myGLCD.clrScr();
        int val = atoi(ang.value());
 
        //--------------------------------------Calcul de la direction de la
        // correction----------------->
 
        int c = val - comp;
        if (c >= 0 && c <= 180) // cap > waypoint
            dif = c;
        sens = 'T';
        if (c > 0 && c > 180) {
            sens = 'B';
            c = 360 - c;
            dif = c;
        }
 
        if (c < 0) { // cap < waypoint
            res = c + 360;
            if (res > 180) {
                dif = 360 - res;
                sens = 'B';
            } else {
                dif = res;
                sens = 'T';
            }
        }
        //-------------------------------------AFFICHAGE---------------------------------------->
        if (val != temp) {
            myGLCD.clrScr(); //----------On attend 3 secondes, le temps que le
                             //nouveau
            // wpt soit établi----->
            bool tempo = HIGH;
            depart = millis();
        } else {
            affichage(comp, val, sens);
            if (flag == true) {
 
                cmd(dif, sens);
            }
        }
 
        if (tempo == HIGH && ((millis() - depart) > 3000)) {
            affichage(comp, val, sens);
            // if (flag==true){
 
            cmd(dif, sens);
            //}
            tempo = LOW;
        }
 
        temp = val; // Variable temp pour pouvoir comparer si le waypoint a changé
    }
    if (lu == LOW) { /*si j'appuie sur le bouton, je force le flag à true par la
                        mise à 0 de la valeur de la dif, ce qui d’éclenche la
                        commande moteur!*/
        dif = 0;
    }
 
    if (dif == 0) {
        flag = true;
    }
    delay(50);
    while (Serial.available() > 0)
        gps.encode(Serial.read());
}
 
//-----------------FONCTION AFFICHAGE------------------------------------>
 
void affichage(int comp, int val, char sens) {
    myGLCD.setFont(SmallFont);
    myGLCD.print("Cap =", LEFT, 8);
    myGLCD.setFont(MediumNumbers);
    myGLCD.printNumI(comp, 35, 0);
    // myGLCD.print("Cap = ");myGLCD.print(comp);
    myGLCD.setFont(SmallFont);
    myGLCD.print("Wpt =", LEFT, 24);
    myGLCD.setFont(MediumNumbers);
    myGLCD.printNumI(val, 35, 16);
    if (sens == 'T') {
        digitalWrite(green, HIGH);
        String sen = "Tri";
        myGLCD.setFont(SmallFont);
        myGLCD.print(sen, RIGHT, 40);
    }
 
    if (sens == 'B') {
        digitalWrite(red, HIGH);
        String sen = "Bab";
        myGLCD.setFont(SmallFont);
        myGLCD.print(sen, RIGHT, 40);
    }
 
    myGLCD.setFont(SmallFont);
    myGLCD.print("Dif =", LEFT, 40);
    myGLCD.setFont(MediumNumbers);
    myGLCD.printNumI(dif, 30, 35);
}
 
//----------------------------FONCTION CMD (impulsions vers boutons
// pilote)------------>
 
void cmd(int x, char y) {
    flag = false;
    int c = x / 10;
    if (y == 'T') {
        for (int i = 0; i < c; i++) {
            digitalWrite(plusdix, HIGH);
            delay(100);
            digitalWrite(plusdix, LOW);
            delay(100);
            // flag=false;
        }
        int d = x - (c * 10);
        for (int i = 0; i < d; i++) {
            digitalWrite(plusun, HIGH);
            delay(100);
            digitalWrite(plusun, LOW);
            delay(100);
            // flag=false;
        }
    }
    if (y == 'B') {
        for (int i = 0; i < c; i++) {
            digitalWrite(moinsdix, HIGH);
            delay(100);
            digitalWrite(moinsdix, LOW);
            delay(100);
        }
        int d = x - (c * 10);
        for (int i = 0; i < d; i++) {
            digitalWrite(moinsun, HIGH);
            delay(100);
            digitalWrite(moinsun, LOW);
            delay(100);
        }
    }
}
Mon problème est le suivant :
Ce code fonctionne comme souhaité sur PC en branchant l'Arduino sur un port usb, aussi bien avec windows qu'avec linux.
Par contre, avec le Raspberry Pi3, l'Arduino semble marcher mais reboot de façon intempestive, ce qui re-déclenche les correction déjà effectuées par le programme et on tourne en rond!!!
Pensant à une problème d'alimentation (surcharge du port usb du Raspberry), j'ai tenté sans succès de rajouter un hub alimenté entre les 2 appareils, mais il reboot toujours*!!!
Mon plan de secours serait d'embarquer un PC, mais l'économie d'énergie est fondamentale sur un voilier et le Raspberry devrait pouvoir suffire!!
Merci de me permettre de conserver mon petit précieux!