Parte 2
en el Primera parte de la serie del blog Apoyamos el conejito de Pascua para que pueda almacenar los huevos de Pascua en una escondite emocionante, que solo encontraremos apoyo técnico. Lo teníamos equipado con un receptor GPS. Ocultar y leer la posición fue un juego ligero, porque los valores se mostraron en nuestra pantalla y solo tuvieron que ser anotados.
La búsqueda nos muestra esta vez con desafíos más grandes, porque primero debemos determinar nuestra posición actual y luego calcular el curso y la distancia al destino. Esto requiere un grado de conocimiento de las matemáticas, pero en el que podemos hacer algunas simplificaciones en Alemania o en Europa Central debido a distancias cortas.
¿Qué necesitamos? En cuanto a la primera parte:
1 |
|
1 |
LCD, por ejemplo, que Lcd-keypad-shield |
1 |
Módulo GPS / GSM SIM 808 (en la tercera parte con tarjeta SIM) |
|
Batería o batería |
Primero, hacemos un juicio de pensamiento y vuelve a tomar la imagen de la línea de manzana similar a nuestra tierra. Pelamos la naranja y tratamos de empujar un poco de concha como sea posible en la mesa. Se conoce el resultado: la cáscara se desgarrará en algunos lugares. Pero cuanto menor sea la pieza de cáscara, mejor será lo que tendrá éxito y no notará la diferencia o apenas se dará cuenta. Utilizamos esta circunstancia con las siguientes consideraciones. En lugar de calcular las fórmulas de cálculo para la navegación a gran escala, que proviene de la trigonometría esférica (bola de tierra), por la presente meta suficientes fórmulas precisas.
Pero completamente sin cálculos triangulares (la trigonometría es la palabra griega para Medición del triángulo) Con el Sr. Pitágoras, el ángulo funciona sin, cos y bronceado y un pequeño kit de haz que no salimos. Repetición corta: dibujamos un circuito unitario (radio = 1) en el sistema de coordenadas cartesiano (x, eje y) y un recto desde el centro hasta un punto en el círculo. En matemáticas contamos (a diferencia de la navegación) el ángulo (alfa) en sentido contrario a las agujas del reloj desde el eje x. En el siguiente paso, dibujamos un triángulo rectangular con nuestra directa como hipotenusa y los catéteres cada uno paralelo a los ejes. Es:
Conjunto de Pitágoras: H² = A² + G² con H = Hipotenuse, A = Ankathet y G = Catetment Counter
pecado = g / h cos = A / H Tan = G / a y tost = g '/ a',
En el círculo de la unidad, la longitud de H y A 'es 1. Por lo tanto, podemos eliminar los valores respectivos para las funciones de ángulo directamente desde el dibujo (por ejemplo, en un círculo con un radio de 10 cm).
Se puede ver que los valores para el seno y el coseno pueden ser entre -1 y +1, para tangentes, los valores en ángulos menores de 45 ° más pequeños que 1, por encima de 45 ° mayor que 1 y (cuidado :) A 90 ° y 270 ° infinito. Tenemos que considerar que más tarde.
Tenemos que considerar algo más: no solo existe el grado de grado en las matemáticas para la descripción del ángulo. El arco circular desde el punto (1.0) en el eje X al punto P también es un valor común. La conversión es fácil: el círculo de la unidad tiene una circunferencia de 2πr con R = 1, es decir, 2π corresponde a 360 °, reduce el factor de conversión π / 180. En nuestro lenguaje de programación, se determinó que se aplica el cálculo de las funciones de ángulo de esta hoja. Entonces, si necesitamos el coseno del ancho geográfico, tenemos que multiplicar el ángulo con π y dividir a través de 180. Si luego calculamos el ángulo con la función inversa de Tangent, desde donde determinamos el curso, debemos multiplicar el valor con 180 y dividirnos a través de π.
Agradecemos a: La tierra no es una rebanada,
Pero una capa de cilindro de heridas (al menos nuestra tarjeta con la proyección Mercator). Podemos simplificar nuestros cálculos porque determinamos en las latitudes templadas y el curso y la distancia para distancias relativamente cortas entre el punto y el punto de tiempo, donde las diferencias entre el ortódromo (círculo grande) y el telódromo (equivalentes) no están en peso.
Solo necesitamos las respectivas diferencias angulares en las posiciones geográficas; En el programa, le llamamos Deltafi por la diferencia en el ancho y Deltalambda por la diferencia de longitud. De esto calculamos los catéteres de nuestro triángulo auxiliar, porque necesitamos unidades de longitud. Esto es fácil con Deltaphi. Desde la primera parte, sabemos que un minuto de hoja en el meridiano / círculo grande = una parte náutica = 1.852 km. Con este multiplicador, nuestra contracatitudina (Deltay) se calcula rápidamente. También recordamos que la distancia de los meridianos, por lo que para nuestro deltalambita en el polo siempre es más estrecho. Por lo tanto, como un multiplicador adicional del coseno de ancho central, simplifica COS del punto de partida, es decir, Deltax = Deltafi (MM) * 1,852 * COS (PHI).
Con Deltay y Deltax, ahora puedo calcular la distancia y el ángulo matemático entre nuestro punto de inicio y tiempo. La distancia es las moscas del cuervo, por lo que ciertamente más cortas que el camino al aire libre. Y en el cálculo del curso Tenemos que ser sugeridos como por encima de las matemáticas. Convertir ángulo a un ángulo de precios. Esto es muy simple: tcourse = 90 -, con = 180 * atan2 (Deltay, Deltax) / π. El curso debe estar entre 000 y 360, por lo que si es necesario, 360 agregue o reste. Incidentalmente, necesitamos la biblioteca para la función Arcus Tadns. matemáticas
En el boceto desde la primera parte, tuvimos todo el botón izquierdo de nuestro teclado LCD-Shield solo con el texto Az-delivery.com ocupado. Ahora aceptamos este botón para el cálculo y la visualización del curso y la distancia a los puntos de ruta. A modo de ejemplo, he insertado cinco puntos de referencia en el boceto. El botón SELECT se "gallina" a los puntos de referencia respectivos. La moneda y la distancia siempre se calculan a partir de la posición actual al punto de referencia respectivo que se selecciona a través del índice.
Para utilizar el boceto para la búsqueda de huevos de Pascua, solo necesita las coordenadas mencionadas por el conejito de Pascua en las líneas
Flotando latwp [] = {5354.0000,4850.0000,5231.0000,5237.0000,5541.0000};
Flotando lonwp [] = {952.0000,1258.0000,1324.0000.973.0000.1235.0000};
Ingrese y configure el número de puntos de referencia en WayPointMax = 5.
El boceto:
/****************************************************************************
GPS con pantalla LCD
Basado en la biblioteca DFROBOT_SIM808 y Ejemplo SIM808_GETGPS por jason.lung@dfrobot.com
Adaptado para UNO, NANO Y COMPATIBLE MCUS y LCD1602 Keypad Shield
Offset para Mez = 1 hora, posiblemente personalizar para MESZ -> OFFSET = 2
La hora y el día se ajustarán poco después de la medianoche, pero el mes y el año no.
Conexiones:
TX del GPS se conecta a A3 = GPIO 17 del teclado LCD
Rx del GPS se conecta a A4 = GPIO 18 del teclado LCD
Los umlauts de los textos fueron reemplazados por las secuencias de escape.
Lcd.print ("\ xe1"); // da un ä
Lcd.print ("\ xef"); // da un Ö
Lcd.print ("\ xf5"); // da un ü
lcd.print ("\ xe2"); // da un ß
lcd.print ("\ xdf"); // salidas A °
lcd.print ("\ x22"); // da un "fuera
lcd.print ("\ xe4"); // salidas un μ
lcd.print ("\ xf4"); // salidas un Ω
*****************************************************************************/#include
#include
#define pin_tx 17
#define pin_rx 18
// LCD no tiene ningún adaptador I2C, transferencia de datos con pines D4 a D7
#include
// Pin LCD a Arduino
// const int pin_bl = 15;
Const int pin_en = 9;
const int pin_rs = 8;
Const int pin_d4 = 4;
const int pin_d5 = 5;
const int pin_d6 = 6;
const int pin_d7 = 7;
LCD líquidoCrystal (PIN_RS, PIN_EN, PIN_D4, PIN_D5, PIN_D6, PIN_D7);
// Desplazamiento por tiempo, aquí UTC ZU MEZ / MESZ
// Summertime Mesz: 2, WintreTime MEZ: 1
#define offset 2
Softwareserial Myserial (PIN_TX, PIN_RX);
DFROBOT_SIM808 SIM808 (y MISERIAL); // conectar rx, tx, pwr
// unterbrechungsfreie zeitsteuerung
Largo sin firmar AnteriorMILLIS = 0;
Intervalo largo constante = 1000;
INT mes = 0;
int día = 0;
int daylcl = 0;
int hora = 0;
int arenalcl = 0;
int minuto = 0;
int segundo = 0;
flotando lat = 0.0;
int latdd = 0;
flotando latmmmmmm = 0.0;
int latmm = 0;
int latddwp = 0;
flotando latmmmmmmmwp = 0.0;
flotando latssss = 0.0;
flotando deltafi = 0.0;
flotar deltay = 0.0;
flotando lon = 0.0;
int londdd = 0;
flotando lonmmmmmm = 0.0;
int lonmm = 0;
int londdwp = 0;
flotando lonmmmmmmwp = 0.0;
Lonssss de flotador = 0.0;
flotar deltalambda = 0.0;
flotando deltax = 0.0;
velocidad de flotador = 0.0;
flotando latwp [] = {5354.0000,4850.0000,5231.0000,5237.0000,5541.0000};
flotando lonwp [] = {952.0000,1258.0000,1324.0000.973.0000.1235.0000};
int waypointindex = 0;
int waypointmax = 5;
char dirsn = 'n';
char direw = 'e';
int tcourse;
distancia de flotación;
// botones
int ButtonInPut = -1;
int ButtotonsLect = 0;
int buttoninput_old = 0;
bool buttonhold = false;
Configuración de vacío () {
myserial.begin (9600);
Serial.begin (9600);
lcd.begin (16,2); // Inicializar la pantalla LCD
LCD.Clear ();
lcd.setcursor (0,0); // Zählung Beginnt Bei Null, Ert Zeichen, Dann Zeile
lcd.print ("az-delivery.com");
lcd.setcursor (0,1); // 0 = erstes zeichen, 1 = zweite zeile
// ******** Inicializar el módulo SIM808 ***************
Mientras (! Sim808.init ()) {
demora (1000);
Serial.print ("Error de inicio SIM808 \ R \ N");
}
// ************* Encienda la potencia GPS ************
if (sim808.attachgps ())
Serial.println ("Abra el éxito de potencia GPS");
demás
Serial.println ("Abra la falla de potencia GPS");
}
bucle vacío () {
ButtonInput = Button ();
// botón muss losgelaassen werden
if (! ButtonHold) {
ButtonInput_old = ButtonInPut;
if (ButtonInput == 4) WayPointIndex + = 1;
Buttonhold = verdadero;
}
Cambiar (ButtonInput) {
Caso 0: Serial.Println ("0"); BUTTONSELECT = 0; descanso;
Caso 1: Serial.Println ("1"); ButtonsELECT = 1; descanso;
Caso 2: Serial.Println ("2"); ButtonsELECT = 2; descanso;
Caso 3: Serial.Println ("3"); ButtonsELECT = 3; descanso;
Caso 4: Serial.Println ("4");
Si (WayPointIndex> WayPointMax-1) WayPointIndex = 0;
Buttonselect = 4;
Serial.print ("waypointindex");
Serial.println (WayPointIndex); descanso;
Predeterminado: romper;
}
// botón loslassen pruefen
Si (ButtonInput! = ButtonInPut_old) {
Buttonhold = False;
}
if (milis () - anteriormillis> = intervalo) {
// ************** Obtener datos GPS *******************
if (sim808.getgps ()) {
Mes = sim808.gpsdata.month;
Día = sim808.gpsdata.day;
Daylcl = day;
Hora = sim808.gpsdata.hur;
Hotllcl = hora + offset;
Minuto = sim808.gpsdata.minute;
Segundo = sim808.gpsdata.segundo;
if (hotlcl> 24) {
Hotllcl = hourlcl-24;
Daylcl = daylcl + 1; }
Serial.print (sim808.gpsdata.year);
Serial.print ("/");
Serial.print (mes);
Serial.print ("/");
Serial.print (día);
Serial.print ("");
Serial.print (hora);
Serial.print (":");
Serial.print (minuto);
Serial.print (":");
Serial.println (segundo);
Lat = sim808.gpsdata.lat;
Tatdd = int (lat);
Latmmmmmm = (lat - tatdd) * 100;
Latddwp = int (latwp [waypointindex] / 100);
Latmmmmmmwp = latwp [waypointindex] - 100 * latddwp;
Deltaphi = 60 * (latddwp - tatdd) + (latmmmmmmwp - latmmmmmmm);
Deltay = Deltaphi * 1.852;
Serial.print ("Deltafi =");
Serial.println (Deltaphi);
Serial.println (Deltay);
Lon = sim808.gpsdata.lon;
Londdd = int (lon);
Lonmmmmmmm = (Lon - LondDD) * 100;
Londdwp = int (lonwp [waypointindex] / 100);
Lonmmmmmmwp = lonwp [waypointindex] - 100 * londdwp;
Deltalambda = 60 * (LonddWP - LondDD) + (LONMMMMMMMMWP - LONMMMMMMMM);
Deltax = Deltalambda * 1.852 * COS (DEG_TO_RAD * LAT);
Serial.print ("Deltalambda =");
Serial.println (Deltalambda);
Serial.println (Deltax);
Serial.print ("latitud:");
Serial.print (LATDD);
Serial.print ("°");
Serial.print (latmmmmmm, 4);
Serial.println ("'n");
Serial.print ("longitud:");
if (lon <100.0) serial.print ("0");
if (Lon <10.0) Serial.Print ("0");
Serial.print (londdd);
Serial.print ("°");
Serial.print (lonmmmmmmm, 4);
Serial.println ("'e");
Si (Deltax> 0) {
DIREW = "E";
Serial.println (Direw);
}
otra cosa si (Deltalambda <0) {
DIREW = "W";
Serial.println (Direw);
}
else {serial.print ("NSNS"); }
Serial.print ("Lon");
Serial.println (LON);
Serial.print ("londdd");
Serial.println (londdd);
Serial.print ("lonwp");
Serial.print (LONWP [WayPointIndex]);
Serial.println ("");
Serial.print ("latitud:");
Serial.print (LATDD);
Serial.print ("°");
Serial.print (latmmmmmm, 4);
Serial.println ("'n");
Serial.print ("longitud:");
if (lon <100.0) serial.print ("0");
if (Lon <10.0) Serial.Print ("0");
Serial.print (londdd);
Serial.print ("°");
Serial.print (lonmmmmmmm, 4);
Serial.println ("'e");
if (ABS (Deltay) <0.5) {
if (Deltax <0.1 && Deltax> -0.1) {
tcourse = 1359;
distancia = 0;
}
otra cosa si (Deltax> 0) {
tcourse = 90;
Distancia = Deltax;
}
otra cosa si (Deltax <0) {
tcourse = 270;
distancia = - Deltax;
}
}
otra cosa si (Deltay> 0) {
if (Deltax <0.1 && Deltax> -0.1) {
tcourse = 360;
distancia = Deltay;
}
otra cosa si (Deltax> 0) {
tcourse = (90 - rad_to_deg * atan2 (Deltay, Deltax));
distancia = sqrt (cuadrado (deltax) + cuadrado (Deltay));
}
otra cosa si (Deltax <0) {
tcourse = (90 - rad_to_deg * atan2 (Deltay, Deltax));
distancia = sqrt (cuadrado (deltax) + cuadrado (Deltay));
}
}
otra cosa si (Deltay <0) {
if (Deltax <0.1 && Deltax> -0.1) {
tcourse = 180;
distancia = -detray;
}
otra cosa si (Deltax> 0) {
tcourse = (90 - rad_to_deg * atan2 (Deltay, Deltax));
distancia = sqrt (cuadrado (deltax) + cuadrado (Deltay));
}
otra cosa si (Deltax <0) {
tcourse = (90 - rad_to_deg * atan2 (Deltay, Deltax));
distancia = sqrt (cuadrado (deltax) + cuadrado (Deltay));
}
}
if (tcourse <0) tcourse = tcourse + 360;
if (tcourse> 360) tcourse = tcourse-360;
Serial.print ("verdadero curso =");
Serial.println (tcourse);
Serial.print ("distancia =");
Serial.println (distancia);
Velocidad = sim808.gpsdata.speed_kph;
if (velocidad> = 3.0) {
Serial.print ("speed_kph:");
Serial.println (velocidad);
Serial.print ("encabezado:");
Serial.println (sim808.gpsdata.heading); }
demás {
Serial.print ("speed_kph:");
Serial.println ("por debajo de 3");
Serial.print ("encabezado:");
Serial.println ("no determinado"); }
if (Buttonselect == 0) {
LCD.Clear ();
lcd.setcursor (0,0);
lcd.print (LATDD);
lcd.print ("\ xdf");
Latmm = int (latmmmmmmm);
Latssss = (latmmmmmm-latmm) * 60;
lcd.print (latmm);
lcd.print ("'');
lcd.print (latssss, 1);
lcd.print ("\ x22 \ n");
lcd.setcursor (0,1);
if (LON <100.0) LCD.Print ("0");
if (LON <10.0) LCD.Print ("0");
lcd.print (londdd);
lcd.print ("\ xdf");
Lonmm = int (lonmmmmmmm);
Lonsssss = (lonmmmmmm-lonmm) * 60;
if (lonmm <10) lcd.print ("0");
lcd.print (LONMM);
lcd.print ("'');
Si (Lonsssss <10.0) LCD.Print ("0");
lcd.print (Lonssss, 1);
lcd.print ("\ x22 \ e"); }
otra cosa si (Buttonselect == 1) {
LCD.Clear ();
lcd.setcursor (0,0);
lcd.print ("EUR:");
if (DaylCl <10) LCD.Print ("0");
lcd.print (daylcl);
lcd.print ("");
if (mes <10) lcd.print ("0");
lcd.print (mes);
lcd.print ("");
lcd.print (sim808.gpsdata.year);
lcd.setcursor (5,1);
if (Hourlcl <10) LCD.Print ("0");
lcd.print (hourlcl);
lcd.print (":");
if (minuto <10) lcd.print ("0");
lcd.print (minuto);
lcd.print (":");
Si (segundo <10) LCD.Print ("0");
lcd.print (segundo);
}
otra cosa si (Buttonselect == 2) {
LCD.Clear ();
lcd.setcursor (0,0);
lcd.print ("UTC:");
lcd.print (sim808.gpsdata.year);
lcd.print ("/");
if (mes <10) lcd.print ("0");
lcd.print (mes);
lcd.print ("/");
if (Día <10) LCD.Print ("0");
lcd.print (día);
lcd.setcursor (5,1);
si (hora <10) lcd.print ("0");
lcd.print (hora);
lcd.print (":");
if (minuto <10) lcd.print ("0");
lcd.print (minuto);
lcd.print (":");
Si (segundo <10) LCD.Print ("0");
lcd.print (segundo);
}
otra cosa si (Buttonselect == 3) {
LCD.Clear ();
lcd.setcursor (0,0);
lcd.print (LATDD);
lcd.print ("\ xdf");
lcd.print (latmmmmmm, 4);
lcd.print ("'n");
lcd.setcursor (0,1);
if (LON <100.0) LCD.Print ("0");
if (LON <10.0) LCD.Print ("0");
lcd.print (londdd);
lcd.print ("\ xdf");
if (LONMMMMMMMM <10.0) LCD.Print ("0");
lcd.print (lonmmmmmm, 4);
lcd.print ("'e"); }
otra cosa si (Buttonselect == 4) {
LCD.Clear ();
lcd.setcursor (0,0);
lcd.print ("wp");
lcd.print (WayPointIndex);
lcd.setcursor (5,0);
lcd.print ("kurs");
lcd.print (tcourse);
lcd.setcursor (0,1);
lcd.print ("distanz");
lcd.print (distancia);
}
//
// // ************* Apague la potencia GPS ************
// sim808.detachgps ();
AnteriorMILLIS = MILIS ();
}
}
}
botón int () {
INT A0;
// Todos los botones están conectados a A0 a través del divisor de voltaje
// Los valores de ADC están entre 0 y 1023
// si es necesario, los valores deben cambiarse ligeramente
A0 = analogreead (0); //
Si (A0 <60) {
return 0;
}
de lo contrario si (A0> = 60 && A0 <250) {
return 1;
}
otra cosa si (A0> = 250 && A0 <450) {
retorno 2;
}
otra cosa si (A0> = 450 && A0 <700) {
regreso 3;
}
otra cosa si (A0> = 700 && A0 <900) {
retorno 4;
}
demás {
Buttonhold = False;
return -1;
}
} // Botón final ()
Nun Sollte Die Ostereiersuche MIT GPS Keine Douse Mehr Bereiten. Wir Wünschen Ihnen Schöne und Sonnige Osterfeiertage en Der Freien Natur.
6 comentarios
Andreas S.
Nach fundierter Hilfe bei der Fehleranalyse von AZ habe ich unkompliziert ein neues Modul bekommen, mit dem funktioniert nun alles einwandfrei.
Damit kann ich auch noch einen kleinen Nachtrag zu Teil1 liefern:
Wenn man anstelle von AT+CGNSTST=1 den Befehl AT+CGNSINF schickt, bekommt man anstelle den Rohdaten die bereits ausgewerteten Werte (einmalig) zurück.
Und mit AT+CGNSURC=5 bekommt man die ausgewerteten Daten im 5-Sekunden-Takt ( Den Takt kann man anpassen, ein Wert von 0 schaltet das wieder ab).
Das Modul bietet übrigens auch eine Bluetooth-Schnittstelle. Ich freue mich schon darauf, wenn die in einem eigenen Blog-Beitrag auch einmal aufgegriffen wird.
Bernd Albrecht
@ Carlo M.
Der Link für den Download des Sketches befindet sich in der Überschrift „Der Sketch“, die ich auf Ihren Kommentar hin in „Download Sketch“ geändert habe. Download des Beitrags als pdf habe ich am Ende eingefügt.
@ Ingo
Der Sonderfall „kurze Distanzen“ wurde eingefügt, um 1. eine Division durch 0 zu verhindern, und 2. „springende Werte“ für den Kurs aufgrund der Positionsungenauigkeit von nicht-militärischen GPS-Empfängern zu verhindern. Also Anzeige Kurs=999 und Distanz=0 bedeutet Nahbereich. Der Wert in der if-Anfrage kann selbstverständlich etwas kleiner (z.B. 0.02) gewählt werden. Auf den Sonderfall verzichten sollte man aber nicht.
Ingo
Hallo Zusammen,
Wenn ich mich nicht total falsch liege (und ich habe es gerade getestet) wird mit dem Code das Eiersuchen echt zu einer Herausvorderung.
Durch die Codezeilen:
if (abs(deltaY)<0.5) {
if (deltaX < 0.1 && deltaX > -0.1) {
tCourse = 1359;
distance = 0;
}
Wird alles was Delta Y kleiner 100m und Delta Y kleiner 100 Meter auf ungültigen Winkel und Distanz 0 gesetzt. Dadurch gebit sich ein Bereich von 200m x200mum die Zielkoordinaten in dem das GPS nicht die Distanz und Richtung ausgiebt.
Hat das mal jemand getestet?
Gruß Ingo
Carlo M.
An sich ein guter Beitrag, bei der Länge des Sketches aber recht verwirrend. Besonders am Anfang bei den Erklärungen ging es recht schnell zu. Ich vermisse ein Downloadangebot für den Sketch und den Artikel selbst, wie beim ersten Teil.
Andreas S.
Interessanter Beitrag, nur leider scheitere ich bereits beim Versuch, das Modul mit einem Terminalprogramm anzusprechen. Es gab weder GPS-Ausgaben, noch reagierte es auf AT-Kommandos bei 6900 oder bei 34800 Baud. (GND, TX und RX an Serial/USB-Konverter (z.B. den FT232), Stromversorgung über die Extra Buchse angeschlossen, Stromschalter an und auch Starttaste betätigt).
Muss man das Modul noch extra initialisieren ?
Etwas ungewöhnlich ist, dass auf der Steckerleiste laut Beschriftung über Kreuz je 2 Rx und Tx Anschlüsse vorhanden sind. Vielleicht würde ein funktionierendes Anschlussbild Unsicherheiten beseitigen.
Aus welchem Grund verwendet das Projekt nicht wie oft gesehen die digitalen Ports D7 und D8 für das Software Serial, sondern die Analogpins ?
Frohe Ostern
Andreas
Alain Tanguy
Dans la version française, le programme C pour Arduino est traduit en français même les mots réservés du langage C. Pour accéder à la version originale allemande supprimer “/fr” dans le lien de la page française :
https://www.az-delivery.de/fr/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/ostereier…etc.