il faut l'ancien "boot loader" .... mais il veullent pas discuter entre eux.... le slave fait 3 beep toutes 5 a 10 seconde
il faut l'ancien "boot loader" .... mais il veullent pas discuter entre eux.... le slave fait 3 beep toutes 5 a 10 seconde
le 433 MHz ça reste une fréquence encombrée, mais les modules du marché permettent de communiquer plus ou moins vite. plus on va vite plus ça influence la qualité de réception
Le module HC-12 règle son débit "Air" en fonction de la vitesse de la communication série utilisée pour lui causer. Si on lui parle à 9600 bauds, il émet à 15k bauds - ça devrait suffire pour envoyer des trames plusieurs fois par seconde.
Mais ça reste des composants "peu qualitatifs" et l'émetteur ne sait pas si le récepteur a reçu le message
à 2.4GHz on peut regarder du côté des modules XBee 2 ou 3 en version pro, c'est un peu plus cher et ça nécessite plus de configuration / main dans le cambouis - mais on pourrait explorer une liaison sans fil TTL série. Avec une bonne antenne ça va loin.
le premier souci dépendant c'est que le TF-03 n'est sans doute pas adapté au besoin.
Jay
je pense que si a la pose du Lidar on le regle en elevation peux etre que ca passe... les quai sont en beton ...
sinon il faut soit un Lidar a balayage (mais ca coute cher) soit on revient a l'ultrason...
pour le 433 on part sur ce que vous avez dit .... mais les mains dans le "cambouis" ca m'inquiette...
la console est bien à 115200 bauds ?
oui ...
j'ai commander d'autre maxsonar dans la serie 738... je pense que celui la deconne
Ok
Globalement si on n’a pas une surface orthogonale au rayon laser ou ultra sons - ce type de capteur ne fonctionnera pas. Le cas du quai en bois est aussi difficile à traiter...
Je pense que c’est plus complexe qu’une première approche pourrait laisser penser et que ça explique le fait que les constructeurs de bateaux n’en mettent pas et que sur les gros il y a des caméras et ils laissent aux humains le soin de piloter...
Je sèche sur une approche réaliste qui fonctionnerait avec un arduino. On tombe plus dans le cas du logiciel pour voiture a conduite autonome qui doit détecter des situations connues sur la base d’une tripotée de capteurs lidars en matrice et autres caméras. Il faut une puissance de calcul importante, beaucoup d’éléments câblés et un entraînement des modèles IA en cas réel... des années de R&D...
Bonjour Jay
Hummm... j'aimerais tester quand même...
pouvez vous me sortir un code pour l'ultrason avec les beep comme je vous avez indiqué? (par palier de 1 m)
il faudrait aussi la possibilité de faire comme un decalage a l'aide de dip switch ou d'un encodeur rotatif
ex: le capteur est a 1 m du cul du bateau on decale de 1 metre les beep
si il est a 2 metre pareil on decale
au moins 4 positions
une sortie balayage tilt que je regleré dans le code
et une sortie pour le HC12...
si vous avez un peu de temps ce serais cool...
j'ai trouvé un code avec un HC-SR04...
on pourrais essayer de mettre 2 Maxbotix a la place du HC-SR04
un envois Trigger... retour echo on a peux etre plus de perf...
dans le code il y a le Tilt aussi et sortie buzzer
si ca peux vous simplifier la vie... enfin ci vous voulez toujours m'aider...
je ne sais toujour pas comment on poste les codes....
quand le slave s'endort il fait 3 beeps un peu aigusQuand il ne trouve pas le HC12, il fait aussi 3 beeps mais graves et plus longs
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 void goToSleep() { for (uint8_t i = 0; i < 3; i++) { tone(buzzPin, sleepFreq, 50); delay(75); } ...==> modifiez le 3 dans initHC12 et mettez 20 à la place par exemple.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11void initHC12() { ... else { for (uint8_t i = 0; i < 3; i++) { tone(buzzPin, errorFreq, 200); delay(250); } while (true); } }
ça nous permettra de savoir mieux s'il s'endort ou s'il n'a pas trouvé le HC12.
S'il s'endort c'est que le maître a cessé d'émettre (ou qu'il lit une distance trop grande > 9m) pendant plus de 3 secondes
mais s'il se réveille ça veut dire que le maître le lui a demandé aussi.
==> est-ce que le LCD affiche une distance cohérente sur le maître ?
j'ai modifier comme ca:
mais le slave continu a faire 3 beep tres rapide toutes les 5 a 10 s a vue de nez
Code : 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 void initHC12() { uint8_t detectedBaudIndex = 0; // get parameters from DIL DIP SWITCHES getDefaults(); if (tuneToHC12BaudRate(detectedBaudIndex)) { // managed to connect // Improvement neeeded = check answer is OK for each command setATCommandMode(true); HC12.print(F("AT+FU")); HC12.println(hc12Parameters.fuMode); HC12.print(F("AT+P")); HC12.println(hc12Parameters.powerMode); HC12.print(F("AT+")); HC12.println(hc12Channels[hc12Parameters.channelIndex]); HC12.print(F("AT+B")); HC12.println(hc12BaudRates[hc12Parameters.baudRateIndex]); setATCommandMode(false); // exit AT Mode, which validates new settings HC12.end(); HC12.begin(hc12BaudRates[hc12Parameters.baudRateIndex]); HC12Ready = true; } else { for (uint8_t i = 0; i < 20; i++) { tone(buzzPin, errorFreq, 200); delay(250); } while (true);
si je debranche le master il ne beep plus... donc il recois quand meme des truc du master mais il n'interprete pas...
et ce que le master affiche est juste... mesure avec un metre pour etre sur....
C'était un code de test. Voici les codes / montages (dessins sans les alimentations des modules, à brancher bien sûr en joignant les GNDs)
N'oubliez pas de débrancher la pin 0 lors du téléchargement.
POUR LE MASTER:
Code : 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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446 // Author: Jay M for Arduino forums. // Standard MIT License applies. https://opensource.org/licenses/mit-license.php /* *** ARDUINO PIN MAPPING *** 0 Rx Radar TX 1 Tx Radar Rx 2 Encoder DT 3 Encoder CLK 4 Encoder SW 5 6 Piezo + (through 150Ω current limiting resistor) 7 HC12 Set 8 SRx HC12 Tx (AltSoftSerial imposed) 9 STx HC12 Rx (AltSoftSerial imposed) 10 11 12 13 Led A0 A1 A2 A3 A4 SCA LCD SCA A5 SCL LCD SCL *** POWER *** HC12 : 5V, GND LCD : GND, 5V Encoder : GND, 5V Servo : GND, 5V Arduino : USB, 7-20V unregulated on pin 30 (Vin), 5V regulated on pin 27 (5V) *** WIRING *** Piezo : arduino --- 150Ω --- Piezo+ () Piezo- --- GND (to limit this initial inrush current) *** LIBRARIES *** Using a Servo, Piezo and a Software Serial connection requires care as they depend on scare Timers or Pin Change Interrupts The choice below will work. AltSoftSerial imposes pins for Rx/Tx. TimerFreeTone is blocking but does not conflict with ServoTimer2 Encoder https://www.pjrc.com/teensy/td_libs_Encoder.html simpleBouton http://forum.arduino.cc/index.php?topic=375232.0 (@bricoleau) LiquidCrystal_I2C https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library ServoTimer2 https://github.com/nabontra/ServoTimer2 AltSoftSerial https://github.com/PaulStoffregen/AltSoftSerial TimerFreeTone https://bitbucket.org/teckel12/arduino-timer-free-tone */ #include <Encoder.h> // https://www.pjrc.com/teensy/td_libs_Encoder.html #include <simpleBouton.h> // http://forum.arduino.cc/index.php?topic=375232.0 (@bricoleau) #include <LiquidCrystal_I2C.h> // https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library #include <ServoTimer2.h> // https://github.com/nabontra/ServoTimer2 #include <AltSoftSerial.h> // https://github.com/PaulStoffregen/AltSoftSerial #include <TimerFreeTone.h> // https://bitbucket.org/teckel12/arduino-timer-free-tone #include <EEPROM.h> const uint32_t hc12BaudRates[] = {9600, 4800, 1200, 2400, 19200, 38400, 57600, 115200}; // 9600 is the default so testing first const uint8_t nbBaudRates = sizeof hc12BaudRates / sizeof hc12BaudRates[0]; // set channels 6 bands apart to avoid interferences with nearbye devices const char* hc12Channels[] = {"C003", "C009", "C015", "C021", "C027", "C033", "C039", "C045", "C051", "C057", "C063", "C069", "C075", "C081", "C087", "C093"}; const uint8_t nbChannels = sizeof hc12Channels / sizeof hc12Channels[0]; // 16 to be selected through DIL DIP SWITCH bool HC12Ready = false; // ****** LCD ****** LiquidCrystal_I2C lcd(0x3F, 16, 2); // address, #cols, #lines. NB other LCD may use 0x27 // ****** EEPROM ARCHIVE ****** /* For successful wireless transmission, the transparent transmission mode, serial port baud rate, and wireless communication channel of the paired modules must be set the same FU MODE FU1 FU2 FU3 FU4 Idle current 3.6mA 80µA 16mA 16mA Range for P8 100m 100m 600m @9600 1800m @1200 (Clear line of sight, ideal conditions) 1000 @2400 powerMode value 1 2 3 4 5 6 7 8 Transmitting -1 dBm 2 dBm 5 dBm 8 dBm 11 dBm 14 dBm 17 dBm 20 dBm power of module (0.8mW) (1.6mW) (3.2mW) (6.3mW) (12mW) (25mW) (50mW) (100mW) Channel: wireless working frequency band is 433.4-473.0MHz. Multiple channels can be set, with a channel stepping of 400kHz and a total of 100 channels. */ struct __attribute__ ((packed)) _paramS { uint8_t fuMode; // 1 to 4 uint8_t powerMode; // 1 to 8 uint8_t channelIndex; // 0 to 15 uint8_t baudRateIndex; // 0 to 7, index in hc12BaudRates array } hc12Parameters; const uint32_t keyword = 0xDEADBEEF; const uint16_t keywordAddress = 0x00; const uint16_t paramAddress = keywordAddress + sizeof(keyword); void printDefaults() { lcd.clear(); lcd.setCursor(0, 0); lcd.print(F("fu")); lcd.print(hc12Parameters.fuMode); lcd.print(F(" p")); lcd.print(hc12Parameters.powerMode, HEX); lcd.print(F(" c")); lcd.print(hc12Parameters.channelIndex, HEX); lcd.print(F(" b")); lcd.print(hc12Parameters.baudRateIndex, HEX); } void saveDefaults() { EEPROM.put(keywordAddress, keyword); EEPROM.put(paramAddress, hc12Parameters); } void getDefaults(bool forceInitialize = false) { uint32_t tmpKey; EEPROM.get(keywordAddress, tmpKey); if (!forceInitialize && (tmpKey == keyword)) { bool valid = true; EEPROM.get(paramAddress, hc12Parameters); // EEPROM was already initialized OK to read // check for coherence if ((hc12Parameters.fuMode == 0) || (hc12Parameters.fuMode > 4)) { hc12Parameters.fuMode = 2; // FU2 valid = false; } if ((hc12Parameters.powerMode == 0) || (hc12Parameters.powerMode > 8)) { hc12Parameters.powerMode = 4; // P4 valid = false; } if (hc12Parameters.channelIndex > nbChannels) { hc12Parameters.channelIndex = 0; // C003 valid = false; } if (hc12Parameters.fuMode >= nbBaudRates) { hc12Parameters.baudRateIndex = 1; // 4800 bauds valid = false; } if (!valid) saveDefaults(); } else { // First run on this arduino, memory was never initialized. so establish default values hc12Parameters.fuMode = 2; // AT+FU2 --> 80µA idle hc12Parameters.powerMode = 4; // AT+P4 --> 8dBm, 6.3mW hc12Parameters.channelIndex = 0; // AT+C003 hc12Parameters.baudRateIndex = 1; // AT+B4800 --> 4800 bauds saveDefaults(); } } // ****** AUDIO ****** const uint8_t buzzPin = 6; // Piezo + through a current limiting resistor (150Ω) const uint16_t buzFreq = 1000; // frequency used during distance beeping // Rotary encoder const uint8_t encoderDTPin = 2; // Encoder DT const uint8_t encoderCLKPin = 3; // Encoder CLK const uint8_t encoderSwitchPin = 4; // Encoder SW long oldRotaryEncoderPosition; Encoder rotaryEncoder(encoderDTPin, encoderCLKPin); simpleBouton encoderSwitch(encoderSwitchPin); // ****** Servo ****** const uint8_t tiltPin = 5; ServoTimer2 tiltServo; int tiltServoMin = 750; // don't get the servo below this int tiltServoMax = 2250; // don't get the servo above that int currentTiltAngle; // ****** XL-MaxSonar-WRC1 ****** #define maxSonar Serial const uint32_t sonarBaudRate = 9600; const uint16_t minDistanceAlert_cm = 50; // in cm. continuous beep if distance less than 50 cm const uint16_t maxDistanceAlert_cm = 900; // in cm. Start beeping if distance less than 9 m uint16_t distance = 2 * maxDistanceAlert_cm; // large value to avoid beeping at first const char minDistanceBeepCode = '0'; // continuous beep const char maxDistanceBeepCode = '9'; // no beep char distanceCode = maxDistanceBeepCode; // very crude XL-MaxSonar-WRC1 reading interface based on https://www.robotshop.com/media/files/PDF/datasheet-mb7060.pdf // Serial @ 9600 8N1 (0 - Vcc) // Frame format: Rxxxx<CR> where xxxx is the distance in mm, start marker is 'R', end marker is a carriage return (ASCII 13) enum : byte {STARTMARKER, PAYLOAD, ENDMARKER} parserState = STARTMARKER; bool acquisition() { static uint16_t payloadDistance; static uint8_t payloadByteCount; bool acquired = false; int rec = maxSonar.read(); if (rec != -1) { uint16_t byteReceived = rec & 0xFF; switch (parserState) { case STARTMARKER: if (byteReceived == 'R') { payloadByteCount = 0; payloadDistance = 0; parserState = PAYLOAD; } break; case PAYLOAD: if ((byteReceived >= '0') && (byteReceived <= '9')) { payloadDistance = 10 * payloadDistance + (byteReceived - '0'); if (++payloadByteCount >= 4) parserState = ENDMARKER; } else if (byteReceived == 'R') { // handle double 'R' payloadByteCount = 0; payloadDistance = 0; } else parserState = STARTMARKER; break; case ENDMARKER: if (byteReceived == '\r') { acquired = true; distance = payloadDistance / 10; // DIDVIDE BY 10 TO GET CM parserState = STARTMARKER; } else if (byteReceived == 'R') { payloadByteCount = 0; payloadDistance = 0; parserState = PAYLOAD; } else parserState = STARTMARKER; break; } } return acquired; } // ****** HC12 ****** // https://opencircuit.shop/resources/file/0f8d974f31fd813604c4d3fb0e9004ec3b483706466/HC-12-Datasheet.pdf const uint8_t hc12RxPin = 9; // connnected to Nano acting as Tx const uint8_t hc12TxPin = 8; // connnected to Nano acting as Rx const uint8_t hc12SetPin = 7; // used to go to AT mode if connected to GND (10kΩ internal pullup, could float). AltSoftSerial HC12; const uint8_t messageMaxSize = 50; char hc12Message[messageMaxSize + 1] = {'\0'}; // +1 for trailing '\0' boolean waifForHC12Message(uint32_t timeout = 500) { uint8_t hc12MessageIndex = 0; boolean messageReady = false; uint32_t t0 = millis(); while (!messageReady && (millis() - t0 < timeout)) { int r = HC12.read(); if (r != -1) { t0 = millis(); if (r == '\n') { if (hc12MessageIndex == 0) hc12Message[0] = '\0'; //empty cString messageReady = true; } else if (r != '\r') { // ignore CR hc12Message[hc12MessageIndex++] = (char) r; hc12Message[hc12MessageIndex] = '\0'; // maintain cString if (hc12MessageIndex >= messageMaxSize) hc12MessageIndex = messageMaxSize - 1; // don't overrflow } } } return messageReady; } bool ATCommandMode = true; void setATCommandMode(bool mode) { digitalWrite(hc12SetPin, mode ? LOW : HIGH); // pull SET to LOW to activate AT command mode delay(mode ? 40 : 80); // according to specifications (40ms to be active, 80ms to save changes upon exit) ATCommandMode = mode; } bool tuneToHC12BaudRate(uint8_t& index) { uint8_t baudIndex = 0xFF; setATCommandMode(true); for (baudIndex = 0; baudIndex < nbBaudRates; baudIndex++) { HC12.begin(hc12BaudRates[baudIndex]); delay(1); HC12.println(F("AT")); if (waifForHC12Message() && !strncmp(hc12Message, "OK", 2)) { index = baudIndex; break; } else HC12.end(); } setATCommandMode(false); return baudIndex < nbBaudRates; } void initHC12() { uint8_t detectedBaudIndex = 0; if (tuneToHC12BaudRate(detectedBaudIndex)) { // managed to connect // Improvement neeeded = check answer is OK for each command setATCommandMode(true); HC12.print(F("AT+FU")); HC12.println(hc12Parameters.fuMode); HC12.print(F("AT+P")); HC12.println(hc12Parameters.powerMode); HC12.print(F("AT+")); HC12.println(hc12Channels[hc12Parameters.channelIndex]); HC12.print(F("AT+B")); HC12.println(hc12BaudRates[hc12Parameters.baudRateIndex]); setATCommandMode(false); // exit AT Mode, which validates new settings HC12.end(); HC12.begin(hc12BaudRates[hc12Parameters.baudRateIndex]); HC12Ready = true; } else { lcd.clear(); lcd.print(F("HC12 unavailable")); for (uint8_t i = 0; i < 5; i++) { TimerFreeTone(buzzPin, 500, 50); delay(500); } while (true); } } void calculateDistanceCode() { // calculate beep code ('0' to '9') depending on proximity. '0' = continuous beep, '9' = no beep if (distance >= maxDistanceAlert_cm) distanceCode = maxDistanceBeepCode; else if (distance <= minDistanceAlert_cm) distanceCode = minDistanceBeepCode; else distanceCode = map(distance, minDistanceAlert_cm, maxDistanceAlert_cm, minDistanceBeepCode + 1, maxDistanceBeepCode); lcd.clear(); lcd.print(F("D:")); lcd.print(distance); lcd.print(F(" cm")); } void submitDistance() { static char previousDistanceCode = 'A'; static uint32_t previousSendChrono = 0; if (HC12Ready) { // send updates or a heartbeat every second if ((distanceCode != previousDistanceCode) || (millis() - previousSendChrono > 1000)) { HC12.write(distanceCode); previousSendChrono = millis(); previousDistanceCode = distanceCode; } } } void audioFeedback() { static uint32_t lastTrigger; submitDistance(); if (distanceCode == minDistanceBeepCode) TimerFreeTone(buzzPin, buzFreq, 10); else if (distanceCode != maxDistanceBeepCode) { uint32_t deltaT = (distanceCode < '4' ? 100ul : 150ul) * (distanceCode - '0'); // (100ms x distance index + ∆t if further) in between two consecutive beeps if (millis() - lastTrigger >= deltaT) { TimerFreeTone(buzzPin, buzFreq, 50); // active wait lastTrigger = millis(); } } } void setAngle(int t) { currentTiltAngle = constrain(t, tiltServoMin, tiltServoMax); tiltServo.write(currentTiltAngle); } // a simple Click changes the edit mode enum : uint8_t {LOCKED_MODE, EDIT_MODE} currentMode = LOCKED_MODE; void selectMode() { if (currentMode == LOCKED_MODE) { currentMode = EDIT_MODE; lcd.clear(); // init rotary oldRotaryEncoderPosition = currentTiltAngle << 1; rotaryEncoder.write(oldRotaryEncoderPosition); TimerFreeTone(buzzPin, 2000, 100); } else { lcd.clear(); lcd.print(F("LOCKED")); currentMode = LOCKED_MODE; TimerFreeTone(buzzPin, 500, 100); } } // returns true if the user modified the position bool handleRotary() { bool servoMoved = false; if (encoderSwitch) selectMode(); if (currentMode == EDIT_MODE) { long newRotaryEncoderPosition = rotaryEncoder.read() >> 1; // my rotary has 2 ticks per click if (newRotaryEncoderPosition != oldRotaryEncoderPosition) { if (newRotaryEncoderPosition > tiltServoMax) { rotaryEncoder.write(tiltServoMax << 1); newRotaryEncoderPosition = tiltServoMax; } else if (newRotaryEncoderPosition <= tiltServoMin) { rotaryEncoder.write(tiltServoMin << 1); newRotaryEncoderPosition = tiltServoMin; } currentTiltAngle = newRotaryEncoderPosition; setAngle(currentTiltAngle); lcd.setCursor(0, 0); lcd.print(currentTiltAngle); lcd.write(' '); servoMoved = oldRotaryEncoderPosition != newRotaryEncoderPosition; oldRotaryEncoderPosition = newRotaryEncoderPosition; } } return servoMoved; } void setup() { pinMode(hc12SetPin, OUTPUT); // LOW by default pinMode(tiltPin, OUTPUT); pinMode(buzzPin, OUTPUT); Serial.begin(sonarBaudRate); // init lcd lcd.begin(); lcd.backlight(); lcd.print(F("Welcome")); // get parameters from EEPROM getDefaults(); printDefaults(); // init Servo tiltServo.attach(tiltPin); setAngle(tiltServoMin); // init rotary oldRotaryEncoderPosition = tiltServoMin << 1; rotaryEncoder.write(oldRotaryEncoderPosition); // get HC12 ready (based on EEPROM defaults) initHC12(); // ready to Go lcd.setCursor(0, 1); lcd.print(F("Ready")); TimerFreeTone(buzzPin, 3000, 200); // active wait } void loop() { if (acquisition()) calculateDistanceCode(); audioFeedback(); }
POUR LE SLAVE:
Code : 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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266 // Author: Jay M for Arduino forums. // Standard MIT License applies. https://opensource.org/licenses/mit-license.php /* *** ARDUINO PIN MAPPING *** 0 Rx HC12 Tx (==> UNPLUG DURING CODE UPLOAD) 1 Tx HC12 Rx 2 3 4 5 6 Piezo + (through 150Ω current limiting resistor) 7 HC12 Set 8 9 10 11 12 13 Led A0 A1 A2 A3 A4 SCA LCD SCA A5 SCL LCD SCL *** POWER *** HC12 : 5V, GND LCD : GND, 5V Arduino : USB, 7-20V unregulated on pin 30 (Vin), 5V regulated on pin 27 (5V) *** WIRING *** Piezo : arduino --- 150Ω --- Piezo+ () Piezo- --- GND (to limit this initial inrush current) *** LIBRARIES *** LowPower https://github.com/rocketscream/Low-Power LiquidCrystal_I2C https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library */ #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x27, 16, 2); // address, #cols, #lines. NB other LCD may use 0x3F #include <LowPower.h> // https://github.com/rocketscream/Low-Power struct __attribute__ ((packed)) _paramS { uint8_t fuMode; // 1 to 4 uint8_t powerMode; // 1 to 8 uint8_t channelIndex; // 0 to 15 uint8_t baudRateIndex; // 0 to 7, index in hc12BaudRates array } hc12Parameters; const uint32_t hc12BaudRates[] = {9600, 4800, 1200, 2400, 19200, 38400, 57600, 115200}; // 9600 is the default so testing first const uint8_t nbBaudRates = sizeof hc12BaudRates / sizeof hc12BaudRates[0]; // set channels 6 bands apart to avoid interferences with nearbye devices const char* hc12Channels[] = {"C003", "C009", "C015", "C021", "C027", "C033", "C039", "C045", "C051", "C057", "C063", "C069", "C075", "C081", "C087", "C093"}; const uint8_t nbChannels = sizeof hc12Channels / sizeof hc12Channels[0]; // 16 to be selected through DIL DIP SWITCH const uint8_t hc12TxPin = 0; // connnected to Ardiuno Serial Rx (0) const uint8_t hc12RxPin = 1; // connnected to Ardiuno Serial Tx (1) const uint8_t hc12SetPin = 7; // used to go to AT mode if connected to GND (10kΩ internal pullup, could float) #define HC12 Serial bool HC12Ready = false; const uint8_t magicByte = 'S'; // 'S' for sleep uint32_t keepAliveChrono; // last time we saw some HC12 activity const uint32_t maxSilenceBeforeSleep = 5000; // go to sleep after 5 seconds without any Serial update const uint8_t buzzPin = 6; // passive buzzer const uint16_t buzFreq = 1000; // frequency used for distance notification const uint16_t sleepFreq = 3000; // frequency used when module goes to sleep const uint16_t errorFreq = 300; // frequency used when eror is detected at boot const char minDistanceBeepCode = '0'; // continuous beep const char maxDistanceBeepCode = '9'; // no beep char distanceCode = maxDistanceBeepCode; // last distance code void getDefaults() { hc12Parameters.fuMode = 2; // AT+FU2 --> 80µA idle hc12Parameters.baudRateIndex = 1; // AT+B4800 --> 4800 bauds // TO DO: READ THOSE FROM DIL DIP SWITCHES INSTEAD OF CANNED VALUES hc12Parameters.powerMode = 4; // AT+P4 --> 8dBm, 6.3mW [8 values = 3 DIP SWITCHES] hc12Parameters.channelIndex = 0; // AT+C003 [16 values = 4 DIP SWITCHES] } // *** SLEEP MANAGEMENT *** void enablePinChangeInterrupt() { *digitalPinToPCMSK(hc12TxPin) |= bit(digitalPinToPCMSKbit(hc12TxPin)); // PCMSK2 |= bit(PCINT16); // enable PC interrupts for pin D0 PCIFR |= bit (digitalPinToPCICRbit(hc12TxPin)); // PCIFR |= bit(PCIF2); // clear any outstanding interrupt PCICR |= bit (digitalPinToPCICRbit(hc12TxPin)); // PCICR |= bit(PCIE2); // enable pin change interrupts for the group D0 to D7 } void disablePinChangeInterrupt() { *digitalPinToPCMSK(hc12TxPin) &= ~bit(digitalPinToPCMSKbit(hc12TxPin)); // PCMSK2 &= ~bit(PCINT16); // disable PC interrupts for pin D0 PCICR &= ~bit(digitalPinToPCICRbit(hc12TxPin)); // PCICR = ~bit(PCIE2); // disable pin change interrupts for the group D0 to D7 } ISR (PCINT2_vect) {} // handle pin change interrupt for D0 to D7 here void goToSleep() { for (uint8_t i = 0; i < 3; i++) { tone(buzzPin, sleepFreq, 50); delay(75); } digitalWrite(LED_BUILTIN, LOW); HC12.end(); pinMode(hc12TxPin, INPUT_PULLUP); enablePinChangeInterrupt(); LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF); disablePinChangeInterrupt(); HC12.begin(hc12BaudRates[hc12Parameters.baudRateIndex]); distanceCode = maxDistanceBeepCode; keepAliveChrono = millis(); } // *** HC12 MANAGEMENT *** void setATCommandMode(bool activate) { digitalWrite(hc12SetPin, activate ? LOW : HIGH); delay(activate ? 40 : 80); // according to specifications (40ms to be active, 80ms to save changes upon exit) } const uint8_t messageMaxSize = 50; char hc12Message[messageMaxSize + 1] = {'\0'}; // +1 for trailing '\0' boolean waifForHC12Message(uint32_t timeout = 500) { uint8_t hc12MessageIndex = 0; boolean messageReady = false; uint32_t t0 = millis(); hc12Message[0] = '\0'; //empty cString while (!messageReady && (millis() - t0 < timeout)) { int r = HC12.read(); if (r != -1) { t0 = millis(); if (r == '\n') messageReady = true; else if (r != '\r') { // ignore CR hc12Message[hc12MessageIndex++] = (char) r; hc12Message[hc12MessageIndex] = '\0'; // maintain cString if (hc12MessageIndex >= messageMaxSize) hc12MessageIndex = messageMaxSize - 1; // don't overrflow } } } return messageReady; } bool tuneToHC12BaudRate(uint8_t& index) { uint8_t baudIndex = 0xFF; setATCommandMode(true); for (baudIndex = 0; baudIndex < nbBaudRates; baudIndex++) { HC12.begin(hc12BaudRates[baudIndex]); delay(1); HC12.println(F("AT")); if (waifForHC12Message() && !strncmp(hc12Message, "OK", 2)) { index = baudIndex; break; } else HC12.end(); } setATCommandMode(false); return baudIndex < nbBaudRates; } void initHC12() { uint8_t detectedBaudIndex = 0; // get parameters from DIL DIP SWITCHES getDefaults(); if (tuneToHC12BaudRate(detectedBaudIndex)) { // managed to connect // Improvement neeeded = check answer is OK for each command setATCommandMode(true); HC12.print(F("AT+FU")); HC12.println(hc12Parameters.fuMode); HC12.print(F("AT+P")); HC12.println(hc12Parameters.powerMode); HC12.print(F("AT+")); HC12.println(hc12Channels[hc12Parameters.channelIndex]); HC12.print(F("AT+B")); HC12.println(hc12BaudRates[hc12Parameters.baudRateIndex]); setATCommandMode(false); // exit AT Mode, which validates new settings HC12.end(); HC12.begin(hc12BaudRates[hc12Parameters.baudRateIndex]); HC12Ready = true; } else { for (uint8_t i = 0; i < 3; i++) { tone(buzzPin, errorFreq, 200); delay(250); } while (true); } } void checkHC12() { if (HC12.peek() != -1) { // did we get an update from the Master? char received = HC12.read(); switch (received) { case magicByte: goToSleep(); break; case minDistanceBeepCode ... maxDistanceBeepCode: keepAliveChrono = millis(); distanceCode = received; lcd.clear(); lcd.print(F("Code: '")); lcd.print(distanceCode); lcd.print(F("' ")); break; default: break; } } } void audioFeedback() { static uint32_t lastTrigger; if (distanceCode >= maxDistanceBeepCode) noTone(buzzPin); else if (distanceCode == minDistanceBeepCode) tone(buzzPin, buzFreq); else { uint32_t deltaT = (distanceCode < '4' ? 100ul : 150ul) * (distanceCode - '0'); // (100ms x distance index + ∆t if further) in between two consecutive beeps if (millis() - lastTrigger >= deltaT) { tone(buzzPin, buzFreq, 50); lastTrigger = millis(); } } } void checkKeepAlive() { static uint32_t blinkChrono = 0; if (millis() - keepAliveChrono > maxSilenceBeforeSleep) goToSleep(); // if there is no heart beat for a while, go to sleep. // show when we are not sleeping if (millis() - blinkChrono > 250) { digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) == LOW ? HIGH : LOW); blinkChrono = millis(); } } // --------------------- MAIN FEATURES --------------------- void setup() { pinMode(hc12SetPin, OUTPUT); // LOW by default (=> AT Command mode) pinMode(LED_BUILTIN, OUTPUT); // show heartbeat // init lcd lcd.begin(); lcd.backlight(); lcd.print(F("Welcome")); // get HC12 ready initHC12(); keepAliveChrono = millis(); } void loop() { checkHC12(); // did we receive something? audioFeedback(); // provide audio feedback when necessary checkKeepAlive(); // check if we need to go to sleep }
pour le HC12, c'est aussi une communication série, on passera par Software Serial, il faudra un Arduino de chaque côté
j'ai ces modules HC-12 SI4463 (trouvables sur amazon), si vous en avez on peut essayer
y'a un peu de config à faire, il y a des infos ici par exemple
16mA les HC 12 en veille?
vous pouvez vérifier éventuellement en connectant un oscilloscope ou voltmètre entre AN et GND et en alimentation 5V. Vous devriez avoir une tension qui varie entre 0V et 5V, proportionnellement à la distance mesurée
oui c'est la premiere chose que j'ai faites ... ca varie mais pas dans cette tranche la! on tourne en mV... ce qui me fait dire que le capteur a sans doute un probleme...
là je suis en vadrouille pour quelques jours sans mon matos...
passez toujours le lien vers le code que vous avez trouvé
Mais avant de coder quoi que ce soit, faites des essais avec le capteur faisant un angle plus ou moins important avec le sol / quai et essayez de voir ce que vous lisez. Je pense que ça va sortir n'importe quoi...
Code : 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 #include <Servo.h> #include <LiquidCrystal.h> Servo myservo; LiquidCrystal lcd(7, 6, 5, 4, 3, 2); // Creates an LCD object. Parameters: (rs, enable, d4, d5, d6, d7) int pos = 0; // la position initiale du servo moteur const int trigPin = 9; const int echoPin = 10; const int moteur = 11; const int buzzer = 12; const int ledPin1 = 14; const int ledPin2 = 15; float distanceCm, DistanceSec,duration; void setup() { myservo.attach(moteur); // attache le Servo moteur a la pin numéro 11 lcd.begin(16,2); // Initialiser l'interface de Lcd avec leurs Dimensions pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(buzzer, OUTPUT); pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT); DistanceSec=20; } void loop() { for (pos = 0; pos <= 180; pos += 1) { // aller de 0 a 180 degée // in steps of 1 degree myservo.write(pos); // Programmer le Servo pour aller a la position (pos) digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); //envoyer une impulsion de 10 micro seconds delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distanceCm= duration*0.034/2; if (distanceCm <= DistanceSec) { if(distanceCm <= DistanceSec/2) { tone(buzzer, 10); // Send 1KHz sound signal... digitalWrite(ledPin1, LOW); digitalWrite(ledPin2, HIGH); delay(700); noTone(buzzer); // Stop sound... lcd.setCursor(0,0); // positionner le cursor a 0,0 lcd.print("Distance: "); // Printe "Distance" sur LCD lcd.print(distanceCm); // Printe la valeur Obtenue sur LCD lcd.print(" cm "); // Printe l'unité sur LCD delay(10); lcd.setCursor(0,1); lcd.print("Angle : "); lcd.print(pos); lcd.print(" deg "); delay(2000); } else { digitalWrite(buzzer, HIGH); digitalWrite(ledPin2, LOW); digitalWrite(ledPin1, HIGH); delay(100); digitalWrite(buzzer, LOW); lcd.setCursor(0,0); // positionner le cursor a 0,0 lcd.print("Distance: "); // Printe "Distance" sur LCD lcd.print(distanceCm); // Printe la valeur Obtenue sur LCD lcd.print(" cm "); // Printe l'unité sur LCD delay(10); lcd.setCursor(0,1); lcd.print("Angle : "); lcd.print(pos); lcd.print(" deg "); delay(2000); } } else{ digitalWrite(buzzer, LOW); digitalWrite(ledPin1, LOW); digitalWrite(ledPin2, LOW); } lcd.setCursor(0,0); // positionner le cursor a 0,0 lcd.print("Distance: "); // Printe "Distance" sur LCD lcd.print(distanceCm); // Printe la valeur Obtenue sur LCD lcd.print(" cm "); // Printe l'unité sur LCD delay(10); lcd.setCursor(0,1); lcd.print("Angle : "); lcd.print(pos); lcd.print(" deg "); delay(80); //attendre 100ms pour que le servo cherche sa position } for (pos = 180; pos >= 0; pos -= 1) { // myservo.write(pos); // digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distanceCm= duration*0.034/2; if (distanceCm <= DistanceSec){ if(distanceCm <= DistanceSec/2) { tone(buzzer, 10); // Send 1KHz sound signal... digitalWrite(ledPin1, LOW); digitalWrite(ledPin2, HIGH); delay(700); noTone(buzzer); // Stop sound... lcd.setCursor(0,0); // positionner le cursor a 0,0 lcd.print("Distance: "); // Printe "Distance" sur LCD lcd.print(distanceCm); // Printe la valeur Obtenue sur LCD lcd.print(" cm "); // Printe l'unité sur LCD delay(10); lcd.setCursor(0,1); lcd.print("Angle : "); lcd.print(pos); lcd.print(" deg "); delay(2000); } else { digitalWrite(buzzer, HIGH); digitalWrite(ledPin2, LOW); digitalWrite(ledPin1, HIGH); delay(100); digitalWrite(buzzer, LOW); lcd.setCursor(0,0); // positionner le cursor a 0,0 lcd.print("Distance: "); // Printe "Distance" sur LCD lcd.print(distanceCm); // Printe la valeur Obtenue sur LCD lcd.print(" cm "); // Printe l'unité sur LCD delay(10); lcd.setCursor(0,1); lcd.print("Angle : "); lcd.print(pos); lcd.print(" deg "); delay(2000); } } else{ digitalWrite(buzzer, LOW); digitalWrite(ledPin1, LOW); digitalWrite(ledPin2, LOW); } lcd.setCursor(0,0); // lcd.print("Distance: "); // lcd.print(distanceCm); // lcd.print(" cm "); delay(10); lcd.setCursor(0,1); lcd.print("Angle : "); lcd.print(pos); lcd.print(" deg "); delay(80); } }
Il y a trois modes dits FU1, FU2 et FU3. En état de repos la consommation correspondante est de 80 μa, 3,6 mA et 16 mA et Effectivement FU3 est le mode par défaut. Ça monte à 100*mA en émission
J ai pris ca au cas ou...
https://www.amazon.fr/gp/product/B07...A3U3NV7MT8POQS
Partager