{"id":36,"date":"2026-10-13T15:03:06","date_gmt":"2026-10-13T15:03:06","guid":{"rendered":"https:\/\/rf-diy.com\/?p=36"},"modified":"2026-10-13T15:25:26","modified_gmt":"2026-10-13T15:25:26","slug":"page-web-pour-synthetiseur-dds-ad9850-sur-raspberry","status":"publish","type":"post","link":"https:\/\/rf-diy.com\/index.php\/2026\/10\/13\/page-web-pour-synthetiseur-dds-ad9850-sur-raspberry\/","title":{"rendered":"Page Web pour Synth\u00e9tiseur DDS AD9850 sur Raspberry"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Pour piloter un synth\u00e9tiseur DDS <strong>AD9850<\/strong> depuis une page web h\u00e9berg\u00e9e sur un <strong>Raspberry Pi 3<\/strong> sous le dernier OS (Raspberry Pi OS Bookworm, qui utilise nativement la biblioth\u00e8que <code>lgpio<\/code> pour les GPIO), voici l&rsquo;architecture compl\u00e8te, le sch\u00e9ma de flux, le c\u00e2blage et le code source pr\u00eat \u00e0 l&#8217;emploi.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Architecture et Flux de Donn\u00e9es<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Le syst\u00e8me repose sur une architecture client-serveur l\u00e9g\u00e8re o\u00f9 le Raspberry Pi h\u00e9berge \u00e0 la fois le serveur web et le contr\u00f4leur mat\u00e9riel.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"559\" src=\"https:\/\/rf-diy.com\/wp-content\/uploads\/2026\/10\/image.png\" alt=\"Architecture et flux DDS AD9850 sur Raspberry PI et serveur Web\" class=\"wp-image-39\" srcset=\"https:\/\/rf-diy.com\/wp-content\/uploads\/2026\/10\/image.png 1024w, https:\/\/rf-diy.com\/wp-content\/uploads\/2026\/10\/image-300x164.png 300w, https:\/\/rf-diy.com\/wp-content\/uploads\/2026\/10\/image-768x419.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. C\u00e2blage Mat\u00e9riel (Raspberry Pi 3 vers AD9850)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Le module AD9850 est branch\u00e9 en <strong>mode s\u00e9rie<\/strong> pour \u00e9conomiser les broches GPIO du Raspberry Pi.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><td><strong>Broche AD9850<\/strong><\/td><td><strong>R\u00f4le<\/strong><\/td><td><strong>Broche Raspberry Pi 3 (BCM)<\/strong><\/td><td><strong>Num\u00e9ro de Broche Physique (Header 40 pins)<\/strong><\/td><\/tr><\/thead><tbody><tr><td><strong>VCC<\/strong><\/td><td>Alimentation 3.3V \/ 5V<\/td><td>Pin 5V ou 3.3V<\/td><td>Pin 2 ou Pin 1<\/td><\/tr><tr><td><strong>GND<\/strong><\/td><td>Masse<\/td><td>GND<\/td><td>Pin 6<\/td><\/tr><tr><td><strong>W_CLK<\/strong><\/td><td>Word Load Clock<\/td><td>GPIO 11<\/td><td>Pin 23<\/td><\/tr><tr><td><strong>FQ_UD<\/strong><\/td><td>Frequency Update<\/td><td>GPIO 8<\/td><td>Pin 24<\/td><\/tr><tr><td><strong>DATA<\/strong><\/td><td>Donn\u00e9es S\u00e9rie<\/td><td>GPIO 10<\/td><td>Pin 19<\/td><\/tr><tr><td><strong>RESET<\/strong><\/td><td>R\u00e9initialisation<\/td><td>GPIO 25<\/td><td>Pin 22<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>Note :<\/strong> La plupart des modules AD9850 du commerce poss\u00e8dent un oscillateur \u00e0 quartz de <strong>125 MHz<\/strong>. C&rsquo;est cette valeur qui est utilis\u00e9e dans le calcul math\u00e9matique de la fr\u00e9quence.<\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\">3. Pr\u00e9requis et Installation sur le dernier OS (Bookworm)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Sur Raspberry Pi OS Bookworm, la gestion des GPIO a \u00e9volu\u00e9 vers <code>lgpio<\/code> et les environnements Python doivent \u00eatre virtualis\u00e9s.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ouvrez un terminal sur votre Raspberry Pi et ex\u00e9cutez ces commandes :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\"><span class=\"hljs-comment\"># Mettre \u00e0 jour le syst\u00e8me<\/span>\nsudo apt update &amp;&amp; sudo apt upgrade -y\n\n<span class=\"hljs-comment\"># Installer Python 3, pip et l&#x27;outil de virtualisation<\/span>\nsudo apt install python3-pip python3-flask python3-lgpio -y\n\n<span class=\"hljs-comment\"># Cr\u00e9er un dossier pour le projet<\/span>\nmkdir ad9850_web &amp;&amp; cd ad9850_web\nmkdir templates<\/code><\/pre><\/template><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">4. Code Source du Programme<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">A. Le Backend Python (<code>app.py<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Cr\u00e9ez le fichier principal du serveur web :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Python<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\"><span class=\"hljs-keyword\">from<\/span> flask import Flask, render_template, request, jsonify\nimport time\nimport lgpio\n\napp = <span class=\"hljs-title function_ invoke__\">Flask<\/span>(__name__)\n\n<span class=\"hljs-comment\"># Configuration des broches BCM pour Raspberry Pi 3<\/span>\nW_CLK = <span class=\"hljs-number\">11<\/span>  <span class=\"hljs-comment\"># GPIO 11 (Pin 23)<\/span>\nFQ_UD = <span class=\"hljs-number\">8<\/span>   <span class=\"hljs-comment\"># GPIO 8  (Pin 24)<\/span>\nDATA = <span class=\"hljs-number\">10<\/span>   <span class=\"hljs-comment\"># GPIO 10 (Pin 19)<\/span>\nRESET = <span class=\"hljs-number\">25<\/span>  <span class=\"hljs-comment\"># GPIO 25 (Pin 22)<\/span>\n\n<span class=\"hljs-comment\"># Fr\u00e9quence de l&#x27;oscillateur de l&#x27;AD9850 (125 MHz par d\u00e9faut)<\/span>\nF_CLK = <span class=\"hljs-number\">125000000.0<\/span>\n\n<span class=\"hljs-comment\"># Initialisation de la puce lgpio<\/span>\nh = lgpio.<span class=\"hljs-title function_ invoke__\">gpiochip_open<\/span>(<span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, W_CLK, <span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, FQ_UD, <span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, DATA, <span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, RESET, <span class=\"hljs-number\">0<\/span>)\n\ndef <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(pin):\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, pin, <span class=\"hljs-number\">0<\/span>)\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, pin, <span class=\"hljs-number\">1<\/span>)\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, pin, <span class=\"hljs-number\">0<\/span>)\n\ndef <span class=\"hljs-title function_ invoke__\">reset_ad9850<\/span>():\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, RESET, <span class=\"hljs-number\">1<\/span>)\n    time.<span class=\"hljs-title function_ invoke__\">sleep<\/span>(<span class=\"hljs-number\">0.001<\/span>)\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, RESET, <span class=\"hljs-number\">0<\/span>)\n    time.<span class=\"hljs-title function_ invoke__\">sleep<\/span>(<span class=\"hljs-number\">0.001<\/span>)\n    <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(W_CLK)\n    <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(FQ_UD)\n\ndef <span class=\"hljs-title function_ invoke__\">set_ad9850_frequency<\/span>(frequency_hz):\n    <span class=\"hljs-comment\"># Calcul du Tuning Word : W = (F_out * 2^32) \/ F_clk<\/span>\n    tuning_word = <span class=\"hljs-keyword\">int<\/span>((frequency_hz * (<span class=\"hljs-number\">2<\/span>**<span class=\"hljs-number\">32<\/span>)) \/ F_CLK)\n    \n    <span class=\"hljs-comment\"># 40 bits : 32 bits de fr\u00e9quence + 8 bits de contr\u00f4le (0x00)<\/span>\n    data = tuning_word &amp; <span class=\"hljs-number\">0xFFFFFFFF<\/span>\n    control = <span class=\"hljs-number\">0x00<\/span>\n    \n    <span class=\"hljs-comment\"># Envoi des 32 bits (du LSB au MSB)<\/span>\n    <span class=\"hljs-keyword\">for<\/span> i in <span class=\"hljs-title function_ invoke__\">range<\/span>(<span class=\"hljs-number\">32<\/span>):\n        bit = (data &gt;&gt; i) &amp; <span class=\"hljs-number\">0x01<\/span>\n        lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, DATA, bit)\n        <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(W_CLK)\n        \n    <span class=\"hljs-comment\"># Envoi des 8 bits de contr\u00f4le<\/span>\n    <span class=\"hljs-keyword\">for<\/span> i in <span class=\"hljs-title function_ invoke__\">range<\/span>(<span class=\"hljs-number\">8<\/span>):\n        bit = (control &gt;&gt; i) &amp; <span class=\"hljs-number\">0x01<\/span>\n        lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, DATA, bit)\n        <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(W_CLK)\n        \n    <span class=\"hljs-comment\"># Validation par FQ_UD<\/span>\n    <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(FQ_UD)\n\n<span class=\"hljs-comment\"># Initialisation au d\u00e9marrage du script<\/span>\n<span class=\"hljs-title function_ invoke__\">reset_ad9850<\/span>()\n\n@app.<span class=\"hljs-title function_ invoke__\">route<\/span>(<span class=\"hljs-string\">&#x27;\/&#x27;<\/span>)\ndef <span class=\"hljs-title function_ invoke__\">index<\/span>():\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">render_template<\/span>(<span class=\"hljs-string\">&#x27;index.html&#x27;<\/span>)\n\n@app.<span class=\"hljs-title function_ invoke__\">route<\/span>(<span class=\"hljs-string\">&#x27;\/set_freq&#x27;<\/span>, methods=[<span class=\"hljs-string\">&#x27;POST&#x27;<\/span>])\ndef <span class=\"hljs-title function_ invoke__\">set_freq<\/span>():\n    data = request.<span class=\"hljs-title function_ invoke__\">get_json<\/span>()\n    <span class=\"hljs-keyword\">try<\/span>:\n        freq = <span class=\"hljs-keyword\">float<\/span>(data.<span class=\"hljs-title function_ invoke__\">get<\/span>(<span class=\"hljs-string\">&#x27;frequency&#x27;<\/span>, <span class=\"hljs-number\">1000000<\/span>)) <span class=\"hljs-comment\"># D\u00e9faut \u00e0 1 MHz<\/span>\n        <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-number\">0<\/span> &lt; freq &lt;= <span class=\"hljs-number\">40000000<\/span>: <span class=\"hljs-comment\"># Limite s\u00e9curis\u00e9e de l&#x27;AD9850 (~40 MHz max conseill\u00e9)<\/span>\n            <span class=\"hljs-title function_ invoke__\">set_ad9850_frequency<\/span>(freq)\n            <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">jsonify<\/span>({<span class=\"hljs-string\">&quot;status&quot;<\/span>: <span class=\"hljs-string\">&quot;success&quot;<\/span>, <span class=\"hljs-string\">&quot;frequency&quot;<\/span>: freq})\n        <span class=\"hljs-keyword\">else<\/span>:\n            <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">jsonify<\/span>({<span class=\"hljs-string\">&quot;status&quot;<\/span>: <span class=\"hljs-string\">&quot;error&quot;<\/span>, <span class=\"hljs-string\">&quot;message&quot;<\/span>: <span class=\"hljs-string\">&quot;Fr\u00e9quence hors limites (1 Hz - 40 MHz)&quot;<\/span>}), <span class=\"hljs-number\">400<\/span>\n    except ValueError:\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">jsonify<\/span>({<span class=\"hljs-string\">&quot;status&quot;<\/span>: <span class=\"hljs-string\">&quot;error&quot;<\/span>, <span class=\"hljs-string\">&quot;message&quot;<\/span>: <span class=\"hljs-string\">&quot;Valeur invalide&quot;<\/span>}), <span class=\"hljs-number\">400<\/span>\n\n<span class=\"hljs-keyword\">if<\/span> __name__ == <span class=\"hljs-string\">&#x27;__main__&#x27;<\/span>:\n    <span class=\"hljs-comment\"># Lance le serveur accessible sur le r\u00e9seau local du Raspberry Pi sur le port 5000<\/span>\n    app.<span class=\"hljs-title function_ invoke__\">run<\/span>(host=<span class=\"hljs-string\">&#x27;0.0.0.0&#x27;<\/span>, port=<span class=\"hljs-number\">5000<\/span>, debug=False)\n<\/code><\/pre><\/template><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">B. L&rsquo;Interface Web (<code>templates\/index.html<\/code>)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Cr\u00e9ez le fichier HTML de l&rsquo;interface dans le dossier <code>templates\/<\/code> :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">HTML<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\">&lt;!DOCTYPE html&gt;\n&lt;html lang=<span class=\"hljs-string\">&quot;fr&quot;<\/span>&gt;\n&lt;head&gt;\n    &lt;meta charset=<span class=\"hljs-string\">&quot;UTF-8&quot;<\/span>&gt;\n    &lt;meta name=<span class=\"hljs-string\">&quot;viewport&quot;<\/span> content=<span class=\"hljs-string\">&quot;width=device-width, initial-scale=1.0&quot;<\/span>&gt;\n    &lt;title&gt;Contr\u00f4leur DDS AD9850&lt;\/title&gt;\n    &lt;style&gt;\n        body { font-family: Arial, sans-serif; background-color: <span class=\"hljs-comment\">#f4f7f6; text-align: center; margin-top: 50px; }<\/span>\n        .card { background: white; padding: <span class=\"hljs-number\">30<\/span>px; border-radius: <span class=\"hljs-number\">10<\/span>px; box-shadow: <span class=\"hljs-number\">0<\/span>px <span class=\"hljs-number\">4<\/span>px <span class=\"hljs-number\">10<\/span>px <span class=\"hljs-title function_ invoke__\">rgba<\/span>(<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0.1<\/span>); display: inline-block; }\n        input { padding: <span class=\"hljs-number\">10<\/span>px; font-size: <span class=\"hljs-number\">16<\/span>px; width: <span class=\"hljs-number\">220<\/span>px; text-align: center; }\n        button { padding: <span class=\"hljs-number\">10<\/span>px <span class=\"hljs-number\">20<\/span>px; font-size: <span class=\"hljs-number\">16<\/span>px; background-color: <span class=\"hljs-comment\">#007bff; color: white; border: none; border-radius: 5px; cursor: pointer; }<\/span>\n        button:hover { background-color: <span class=\"hljs-comment\">#0056b3; }<\/span>\n        <span class=\"hljs-comment\">#status { margin-top: 15px; font-weight: bold; }<\/span>\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=&quot;<span class=\"hljs-title\">card<\/span>&quot;&gt;\n        &lt;<span class=\"hljs-title\">h2<\/span>&gt;<span class=\"hljs-title\">Synth<\/span>\u00e9<span class=\"hljs-title\">tiseur<\/span> <span class=\"hljs-title\">DDS<\/span> <span class=\"hljs-title\">AD9850<\/span>&lt;\/<span class=\"hljs-title\">h2<\/span>&gt;\n        &lt;<span class=\"hljs-title\">p<\/span>&gt;<span class=\"hljs-title\">Pilotez<\/span> <span class=\"hljs-title\">la<\/span> <span class=\"hljs-title\">fr<\/span>\u00e9<span class=\"hljs-title\">quence<\/span> <span class=\"hljs-title\">de<\/span> <span class=\"hljs-title\">sortie<\/span> <span class=\"hljs-title\">en<\/span> <span class=\"hljs-title\">temps<\/span> <span class=\"hljs-title\">r<\/span>\u00e9<span class=\"hljs-title\">el<\/span>&lt;\/<span class=\"hljs-title\">p<\/span>&gt;\n        &lt;<span class=\"hljs-title\">br<\/span>&gt;\n        &lt;<span class=\"hljs-title\">input<\/span> <span class=\"hljs-title\">type<\/span>=&quot;<span class=\"hljs-title\">number<\/span>&quot; <span class=\"hljs-title\">id<\/span>=&quot;<span class=\"hljs-title\">freqInput<\/span>&quot; <span class=\"hljs-title\">value<\/span>=&quot;1000000&quot; <span class=\"hljs-title\">min<\/span>=&quot;1&quot; <span class=\"hljs-title\">max<\/span>=&quot;40000000&quot; <span class=\"hljs-title\">step<\/span>=&quot;1&quot;&gt;\n        &lt;<span class=\"hljs-title\">span<\/span>&gt;<span class=\"hljs-title\">Hz<\/span>&lt;\/<span class=\"hljs-title\">span<\/span>&gt;\n        &lt;<span class=\"hljs-title\">br<\/span>&gt;&lt;<span class=\"hljs-title\">br<\/span>&gt;\n        &lt;<span class=\"hljs-title\">button<\/span> <span class=\"hljs-title\">onclick<\/span>=&quot;<span class=\"hljs-title\">updateFrequency<\/span>()&quot;&gt;<span class=\"hljs-title\">Appliquer<\/span> <span class=\"hljs-title\">la<\/span> <span class=\"hljs-title\">Fr<\/span>\u00e9<span class=\"hljs-title\">quence<\/span>&lt;\/<span class=\"hljs-title\">button<\/span>&gt;\n        &lt;<span class=\"hljs-title\">div<\/span> <span class=\"hljs-title\">id<\/span>=&quot;<span class=\"hljs-title\">status<\/span>&quot;&gt;&lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n    &lt;\/<span class=\"hljs-title\">div<\/span>&gt;\n\n    &lt;<span class=\"hljs-title\">script<\/span>&gt;\n        <span class=\"hljs-title\">async<\/span> <span class=\"hljs-title\">function<\/span> <span class=\"hljs-title\">updateFrequency<\/span>() <\/span>{\n            <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-variable constant_\">freq<\/span> = document.<span class=\"hljs-title function_ invoke__\">getElementById<\/span>(<span class=\"hljs-string\">&#x27;freqInput&#x27;<\/span>).value;\n            <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-variable constant_\">statusDiv<\/span> = document.<span class=\"hljs-title function_ invoke__\">getElementById<\/span>(<span class=\"hljs-string\">&#x27;status&#x27;<\/span>);\n            statusDiv.style.color = <span class=\"hljs-string\">&quot;black&quot;<\/span>;\n            statusDiv.innerText = <span class=\"hljs-string\">&quot;Mise \u00e0 jour en cours...&quot;<\/span>;\n\n            <span class=\"hljs-keyword\">try<\/span> {\n                <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-variable constant_\">response<\/span> = await <span class=\"hljs-title function_ invoke__\">fetch<\/span>(<span class=\"hljs-string\">&#x27;\/set_freq&#x27;<\/span>, {\n                    <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">&#x27;POST&#x27;<\/span>,\n                    <span class=\"hljs-attr\">headers<\/span>: { <span class=\"hljs-string\">&#x27;Content-Type&#x27;<\/span>: <span class=\"hljs-string\">&#x27;application\/json&#x27;<\/span> },\n                    <span class=\"hljs-attr\">body<\/span>: JSON.<span class=\"hljs-title function_ invoke__\">stringify<\/span>({ <span class=\"hljs-attr\">frequency<\/span>: <span class=\"hljs-title function_ invoke__\">parseFloat<\/span>(freq) })\n                });\n                <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-variable constant_\">result<\/span> = await response.<span class=\"hljs-title function_ invoke__\">json<\/span>();\n                <span class=\"hljs-keyword\">if<\/span> (response.ok) {\n                    statusDiv.style.color = <span class=\"hljs-string\">&quot;green&quot;<\/span>;\n                    statusDiv.innerText = `Fr\u00e9quence r\u00e9gl\u00e9e \u00e0 ${result.frequency} Hz avec succ\u00e8s !`;\n                } <span class=\"hljs-keyword\">else<\/span> {\n                    statusDiv.style.color = <span class=\"hljs-string\">&quot;red&quot;<\/span>;\n                    statusDiv.innerText = `Erreur : ${result.message}`;\n                }\n            } <span class=\"hljs-keyword\">catch<\/span> (error) {\n                statusDiv.style.color = <span class=\"hljs-string\">&quot;red&quot;<\/span>;\n                statusDiv.innerText = <span class=\"hljs-string\">&quot;Erreur de communication avec le Raspberry Pi.&quot;<\/span>;\n            }\n        }\n    &lt;\/script&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre><\/template><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">5. Lancement et Utilisation<\/h2>\n\n\n\n<ol start=\"1\" class=\"wp-block-list\">\n<li>D\u00e9marrez l&rsquo;application Flask depuis votre terminal :<br>Bash<code>python3 app.py<\/code><\/li>\n\n\n\n<li>Ouvrez un navigateur web (depuis un ordinateur ou un smartphone connect\u00e9 au m\u00eame r\u00e9seau Wi-Fi\/Ethernet que le Raspberry Pi) et acc\u00e9dez \u00e0 l&rsquo;adresse IP de votre Pi sur le port 5000 :<br>Plaintext<code>http:\/\/&lt;IP_DE_VOTRE_RASPBERRY_PI&gt;:5000<\/code><\/li>\n\n\n\n<li>Saisissez la fr\u00e9quence d\u00e9sir\u00e9e en Hertz (ex: <code>7100000<\/code> pour 7.1 MHz) et cliquez sur <strong>Appliquer la Fr\u00e9quence<\/strong> pour piloter instantan\u00e9ment votre module AD9850.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Annexe : Ajouter des mots de passe pour se connecter<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Pour s\u00e9curiser l&rsquo;acc\u00e8s \u00e0 la page web et au pilotage du DDS AD9850 avec un syst\u00e8me d&rsquo;authentification multi-utilisateurs (plusieurs identifiants\/mots de passe), nous allons utiliser le syst\u00e8me de <strong>sessions Flask<\/strong> et de hachage s\u00e9curis\u00e9 de mots de passe (<code>werkzeug.security<\/code>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Voici les modifications \u00e0 apporter au projet :<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Mise \u00e0 jour du code Backend (<code>app.py<\/code>)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Remplacez votre fichier <code>app.py<\/code> par la version suivante. Elle int\u00e8gre un dictionnaire s\u00e9curis\u00e9 d&rsquo;utilisateurs, une page de connexion (<code>\/login<\/code>), une d\u00e9connexion (<code>\/logout<\/code>) et une protection par d\u00e9corateur sur les routes sensibles.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Python<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\"><span class=\"hljs-keyword\">from<\/span> flask import Flask, render_template, request, jsonify, session, redirect, url_for\n<span class=\"hljs-keyword\">from<\/span> werkzeug.security import generate_password_hash, check_password_hash\nimport time\nimport lgpio\n\napp = <span class=\"hljs-title function_ invoke__\">Flask<\/span>(__name__)\n<span class=\"hljs-comment\"># Cl\u00e9 secr\u00e8te indispensable pour g\u00e9rer les sessions de mani\u00e8re s\u00e9curis\u00e9e<\/span>\napp.secret_key = <span class=\"hljs-string\">&#x27;votre_cle_secrete_tres_complexe_a_changer&#x27;<\/span>\n\n<span class=\"hljs-comment\"># --- GESTION DES UTILISATEURS (Multi-login) ---<\/span>\n<span class=\"hljs-comment\"># Les mots de passe sont hach\u00e9s pour des raisons de s\u00e9curit\u00e9.<\/span>\n<span class=\"hljs-comment\"># Exemples de comptes par d\u00e9faut :<\/span>\n<span class=\"hljs-comment\"># - admin \/ MonMotDePasseAdmin123<\/span>\n<span class=\"hljs-comment\"># - operateur \/ OpeSecurise2026<\/span>\nUSERS = {\n    <span class=\"hljs-string\">&quot;admin&quot;<\/span>: <span class=\"hljs-title function_ invoke__\">generate_password_hash<\/span>(<span class=\"hljs-string\">&quot;MonMotDePasseAdmin123&quot;<\/span>),\n    <span class=\"hljs-string\">&quot;operateur&quot;<\/span>: <span class=\"hljs-title function_ invoke__\">generate_password_hash<\/span>(<span class=\"hljs-string\">&quot;OpeSecurise2026&quot;<\/span>)\n}\n\n<span class=\"hljs-comment\"># Configuration des broches BCM pour Raspberry Pi 3<\/span>\nW_CLK = <span class=\"hljs-number\">11<\/span>  <span class=\"hljs-comment\"># GPIO 11 (Pin 23)<\/span>\nFQ_UD = <span class=\"hljs-number\">8<\/span>   <span class=\"hljs-comment\"># GPIO 8  (Pin 24)<\/span>\nDATA = <span class=\"hljs-number\">10<\/span>   <span class=\"hljs-comment\"># GPIO 10 (Pin 19)<\/span>\nRESET = <span class=\"hljs-number\">25<\/span>  <span class=\"hljs-comment\"># GPIO 25 (Pin 22)<\/span>\n\nF_CLK = <span class=\"hljs-number\">125000000.0<\/span>\n\n<span class=\"hljs-comment\"># Initialisation de la puce lgpio<\/span>\nh = lgpio.<span class=\"hljs-title function_ invoke__\">gpiochip_open<\/span>(<span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, W_CLK, <span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, FQ_UD, <span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, DATA, <span class=\"hljs-number\">0<\/span>)\nlgpio.<span class=\"hljs-title function_ invoke__\">gpio_claim_output<\/span>(h, RESET, <span class=\"hljs-number\">0<\/span>)\n\ndef <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(pin):\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, pin, <span class=\"hljs-number\">0<\/span>)\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, pin, <span class=\"hljs-number\">1<\/span>)\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, pin, <span class=\"hljs-number\">0<\/span>)\n\ndef <span class=\"hljs-title function_ invoke__\">reset_ad9850<\/span>():\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, RESET, <span class=\"hljs-number\">1<\/span>)\n    time.<span class=\"hljs-title function_ invoke__\">sleep<\/span>(<span class=\"hljs-number\">0.001<\/span>)\n    lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, RESET, <span class=\"hljs-number\">0<\/span>)\n    time.<span class=\"hljs-title function_ invoke__\">sleep<\/span>(<span class=\"hljs-number\">0.001<\/span>)\n    <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(W_CLK)\n    <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(FQ_UD)\n\ndef <span class=\"hljs-title function_ invoke__\">set_ad9850_frequency<\/span>(frequency_hz):\n    tuning_word = <span class=\"hljs-keyword\">int<\/span>((frequency_hz * (<span class=\"hljs-number\">2<\/span>**<span class=\"hljs-number\">32<\/span>)) \/ F_CLK)\n    data = tuning_word &amp; <span class=\"hljs-number\">0xFFFFFFFF<\/span>\n    control = <span class=\"hljs-number\">0x00<\/span>\n    \n    <span class=\"hljs-keyword\">for<\/span> i in <span class=\"hljs-title function_ invoke__\">range<\/span>(<span class=\"hljs-number\">32<\/span>):\n        bit = (data &gt;&gt; i) &amp; <span class=\"hljs-number\">0x01<\/span>\n        lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, DATA, bit)\n        <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(W_CLK)\n        \n    <span class=\"hljs-keyword\">for<\/span> i in <span class=\"hljs-title function_ invoke__\">range<\/span>(<span class=\"hljs-number\">8<\/span>):\n        bit = (control &gt;&gt; i) &amp; <span class=\"hljs-number\">0x01<\/span>\n        lgpio.<span class=\"hljs-title function_ invoke__\">gpio_write<\/span>(h, DATA, bit)\n        <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(W_CLK)\n        \n    <span class=\"hljs-title function_ invoke__\">pulse_pin<\/span>(FQ_UD)\n\n<span class=\"hljs-title function_ invoke__\">reset_ad9850<\/span>()\n\n<span class=\"hljs-comment\"># --- ROUTES DE CONNEXION ---<\/span>\n\n@app.<span class=\"hljs-title function_ invoke__\">route<\/span>(<span class=\"hljs-string\">&#x27;\/login&#x27;<\/span>, methods=[<span class=\"hljs-string\">&#x27;GET&#x27;<\/span>, <span class=\"hljs-string\">&#x27;POST&#x27;<\/span>])\ndef <span class=\"hljs-title function_ invoke__\">login<\/span>():\n    error = None\n    <span class=\"hljs-keyword\">if<\/span> request.method == <span class=\"hljs-string\">&#x27;POST&#x27;<\/span>:\n        username = request.form.<span class=\"hljs-title function_ invoke__\">get<\/span>(<span class=\"hljs-string\">&#x27;username&#x27;<\/span>)\n        password = request.form.<span class=\"hljs-title function_ invoke__\">get<\/span>(<span class=\"hljs-string\">&#x27;password&#x27;<\/span>)\n        \n        <span class=\"hljs-keyword\">if<\/span> username in USERS <span class=\"hljs-keyword\">and<\/span> <span class=\"hljs-title function_ invoke__\">check_password_hash<\/span>(USERS[username], password):\n            session[<span class=\"hljs-string\">&#x27;username&#x27;<\/span>] = username\n            <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">redirect<\/span>(<span class=\"hljs-title function_ invoke__\">url_for<\/span>(<span class=\"hljs-string\">&#x27;index&#x27;<\/span>))\n        <span class=\"hljs-keyword\">else<\/span>:\n            error = <span class=\"hljs-string\">&quot;Identifiant ou mot de passe incorrect.&quot;<\/span>\n            \n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">render_template<\/span>(<span class=\"hljs-string\">&#x27;login.html&#x27;<\/span>, error=error)\n\n@app.<span class=\"hljs-title function_ invoke__\">route<\/span>(<span class=\"hljs-string\">&#x27;\/logout&#x27;<\/span>)\ndef <span class=\"hljs-title function_ invoke__\">logout<\/span>():\n    session.<span class=\"hljs-title function_ invoke__\">pop<\/span>(<span class=\"hljs-string\">&#x27;username&#x27;<\/span>, None)\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">redirect<\/span>(<span class=\"hljs-title function_ invoke__\">url_for<\/span>(<span class=\"hljs-string\">&#x27;login&#x27;<\/span>))\n\n<span class=\"hljs-comment\"># --- ROUTES PROT\u00c9G\u00c9ES ---<\/span>\n\n@app.<span class=\"hljs-title function_ invoke__\">route<\/span>(<span class=\"hljs-string\">&#x27;\/&#x27;<\/span>)\ndef <span class=\"hljs-title function_ invoke__\">index<\/span>():\n    <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-string\">&#x27;username&#x27;<\/span> not in session:\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">redirect<\/span>(<span class=\"hljs-title function_ invoke__\">url_for<\/span>(<span class=\"hljs-string\">&#x27;login&#x27;<\/span>))\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">render_template<\/span>(<span class=\"hljs-string\">&#x27;index.html&#x27;<\/span>, username=session[<span class=\"hljs-string\">&#x27;username&#x27;<\/span>])\n\n@app.<span class=\"hljs-title function_ invoke__\">route<\/span>(<span class=\"hljs-string\">&#x27;\/set_freq&#x27;<\/span>, methods=[<span class=\"hljs-string\">&#x27;POST&#x27;<\/span>])\ndef <span class=\"hljs-title function_ invoke__\">set_freq<\/span>():\n    <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-string\">&#x27;username&#x27;<\/span> not in session:\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">jsonify<\/span>({<span class=\"hljs-string\">&quot;status&quot;<\/span>: <span class=\"hljs-string\">&quot;error&quot;<\/span>, <span class=\"hljs-string\">&quot;message&quot;<\/span>: <span class=\"hljs-string\">&quot;Non autoris\u00e9&quot;<\/span>}), <span class=\"hljs-number\">401<\/span>\n        \n    data = request.<span class=\"hljs-title function_ invoke__\">get_json<\/span>()\n    <span class=\"hljs-keyword\">try<\/span>:\n        freq = <span class=\"hljs-keyword\">float<\/span>(data.<span class=\"hljs-title function_ invoke__\">get<\/span>(<span class=\"hljs-string\">&#x27;frequency&#x27;<\/span>, <span class=\"hljs-number\">1000000<\/span>))\n        <span class=\"hljs-keyword\">if<\/span> <span class=\"hljs-number\">0<\/span> &lt; freq &lt;= <span class=\"hljs-number\">40000000<\/span>:\n            <span class=\"hljs-title function_ invoke__\">set_ad9850_frequency<\/span>(freq)\n            <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">jsonify<\/span>({<span class=\"hljs-string\">&quot;status&quot;<\/span>: <span class=\"hljs-string\">&quot;success&quot;<\/span>, <span class=\"hljs-string\">&quot;frequency&quot;<\/span>: freq})\n        <span class=\"hljs-keyword\">else<\/span>:\n            <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">jsonify<\/span>({<span class=\"hljs-string\">&quot;status&quot;<\/span>: <span class=\"hljs-string\">&quot;error&quot;<\/span>, <span class=\"hljs-string\">&quot;message&quot;<\/span>: <span class=\"hljs-string\">&quot;Fr\u00e9quence hors limites (1 Hz - 40 MHz)&quot;<\/span>}), <span class=\"hljs-number\">400<\/span>\n    except ValueError:\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_ invoke__\">jsonify<\/span>({<span class=\"hljs-string\">&quot;status&quot;<\/span>: <span class=\"hljs-string\">&quot;error&quot;<\/span>, <span class=\"hljs-string\">&quot;message&quot;<\/span>: <span class=\"hljs-string\">&quot;Valeur invalide&quot;<\/span>}), <span class=\"hljs-number\">400<\/span>\n\n<span class=\"hljs-keyword\">if<\/span> __name__ == <span class=\"hljs-string\">&#x27;__main__&#x27;<\/span>:\n    app.<span class=\"hljs-title function_ invoke__\">run<\/span>(host=<span class=\"hljs-string\">&#x27;0.0.0.0&#x27;<\/span>, port=<span class=\"hljs-number\">5000<\/span>, debug=False)\n<\/code><\/pre><\/template><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">2. Cr\u00e9ation de la page de Connexion (<code>templates\/login.html<\/code>)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Dans votre dossier <code>templates\/<\/code>, cr\u00e9ez un nouveau fichier nomm\u00e9 <code>login.html<\/code> :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">HTML<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\">&lt;!DOCTYPE html&gt;\n&lt;html lang=<span class=\"hljs-string\">&quot;fr&quot;<\/span>&gt;\n&lt;head&gt;\n    &lt;meta charset=<span class=\"hljs-string\">&quot;UTF-8&quot;<\/span>&gt;\n    &lt;meta name=<span class=\"hljs-string\">&quot;viewport&quot;<\/span> content=<span class=\"hljs-string\">&quot;width=device-width, initial-scale=1.0&quot;<\/span>&gt;\n    &lt;title&gt;Connexion - Contr\u00f4leur DDS AD9850&lt;\/title&gt;\n    &lt;style&gt;\n        body { font-family: Arial, sans-serif; background-color: <span class=\"hljs-comment\">#f4f7f6; text-align: center; margin-top: 80px; }<\/span>\n        .card { background: white; padding: <span class=\"hljs-number\">30<\/span>px; border-radius: <span class=\"hljs-number\">10<\/span>px; box-shadow: <span class=\"hljs-number\">0<\/span>px <span class=\"hljs-number\">4<\/span>px <span class=\"hljs-number\">10<\/span>px <span class=\"hljs-title function_ invoke__\">rgba<\/span>(<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0<\/span>,<span class=\"hljs-number\">0.1<\/span>); display: inline-block; width: <span class=\"hljs-number\">300<\/span>px; }\n        input { padding: <span class=\"hljs-number\">10<\/span>px; font-size: <span class=\"hljs-number\">16<\/span>px; width: <span class=\"hljs-number\">90<\/span>%; margin-bottom: <span class=\"hljs-number\">15<\/span>px; text-align: center; border: <span class=\"hljs-number\">1<\/span>px solid <span class=\"hljs-comment\">#ccc; border-radius: 5px; }<\/span>\n        button { padding: <span class=\"hljs-number\">10<\/span>px <span class=\"hljs-number\">20<\/span>px; font-size: <span class=\"hljs-number\">16<\/span>px; background-color: <span class=\"hljs-comment\">#007bff; color: white; border: none; border-radius: 5px; cursor: pointer; width: 100%; }<\/span>\n        button:hover { background-color: <span class=\"hljs-comment\">#0056b3; }<\/span>\n        .error { color: red; margin-bottom: <span class=\"hljs-number\">15<\/span>px; font-size: <span class=\"hljs-number\">14<\/span>px; }\n    &lt;\/style&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=&quot;<span class=\"hljs-title\">card<\/span>&quot;&gt;\n        &lt;<span class=\"hljs-title\">h2<\/span>&gt;<span class=\"hljs-title\">Connexion<\/span> <span class=\"hljs-title\">requise<\/span>&lt;\/<span class=\"hljs-title\">h2<\/span>&gt;\n        &lt;<span class=\"hljs-title\">p<\/span>&gt;<span class=\"hljs-title\">Pilote<\/span> <span class=\"hljs-title\">DDS<\/span> <span class=\"hljs-title\">AD9850<\/span>&lt;\/<span class=\"hljs-title\">p<\/span>&gt;\n        &lt;<span class=\"hljs-title\">br<\/span>&gt;\n        <\/span>{% <span class=\"hljs-keyword\">if<\/span> error %}\n            &lt;div <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span>=&quot;<span class=\"hljs-title\">error<\/span>&quot;&gt;<\/span>{{ error }}&lt;\/div&gt;\n        {% <span class=\"hljs-keyword\">endif<\/span> %}\n        &lt;form method=<span class=\"hljs-string\">&quot;POST&quot;<\/span>&gt;\n            &lt;input type=<span class=\"hljs-string\">&quot;text&quot;<\/span> name=<span class=\"hljs-string\">&quot;username&quot;<\/span> placeholder=<span class=\"hljs-string\">&quot;Identifiant&quot;<\/span> required autocomplete=<span class=\"hljs-string\">&quot;username&quot;<\/span>&gt;\n            &lt;input type=<span class=\"hljs-string\">&quot;password&quot;<\/span> name=<span class=\"hljs-string\">&quot;password&quot;<\/span> placeholder=<span class=\"hljs-string\">&quot;Mot de passe&quot;<\/span> required autocomplete=<span class=\"hljs-string\">&quot;current-password&quot;<\/span>&gt;\n            &lt;button type=<span class=\"hljs-string\">&quot;submit&quot;<\/span>&gt;Se connecter&lt;\/button&gt;\n        &lt;\/form&gt;\n    &lt;\/div&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;\n<\/code><\/pre><\/template><\/div>\n\n\n\n<pre class=\"wp-block-code\"><code><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3. Ajout d&rsquo;un bouton de d\u00e9connexion dans l&rsquo;interface principale (<code>templates\/index.html<\/code>)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Modifiez l\u00e9g\u00e8rement votre fichier <code>templates\/index.html<\/code> pour y inclure un message de bienvenue et un bouton de d\u00e9connexion dans le coin sup\u00e9rieur (ou sous le titre) :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">HTML<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\">&lt;!-- Ajoutez ce bloc en haut de votre carte dans index.html --&gt;\n&lt;div style=<span class=\"hljs-string\">&quot;text-align: right; margin-bottom: 10px;&quot;<\/span>&gt;\n    &lt;span style=<span class=\"hljs-string\">&quot;font-size: 14px; color: #555;&quot;<\/span>&gt;Connect\u00e9 en tant que : &lt;b&gt;{{ username }}&lt;\/b&gt;&lt;\/span&gt; | \n    &lt;a href=<span class=\"hljs-string\">&quot;\/logout&quot;<\/span> style=<span class=\"hljs-string\">&quot;color: #dc3545; text-decoration: none; font-size: 14px;&quot;<\/span>&gt;D\u00e9connexion&lt;\/a&gt;\n&lt;\/div&gt;\n<\/code><\/pre><\/template><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">4. Comment ajouter de nouveaux utilisateurs ?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Pour ajouter d&rsquo;autres comptes, vous pouvez g\u00e9n\u00e9rer le hachage s\u00e9curis\u00e9 d&rsquo;un mot de passe directement en Python dans un terminal sur votre Raspberry Pi :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bash<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\">python3 -c <span class=\"hljs-string\">&quot;from werkzeug.security import generate_password_hash; print(generate_password_hash(&#x27;VotreNouveauMotDePasse&#x27;))&quot;<\/span>\n<\/code><\/pre><\/template><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Copiez la cha\u00eene de caract\u00e8res g\u00e9n\u00e9r\u00e9e et ajoutez-la dans le dictionnaire <code>USERS<\/code> du fichier <code>app.py<\/code> :<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Python<\/p>\n\n\n\n<div class=\"wp-block-code-syntax-highlighting-block-code-syntax-highlighting-block\"><template shadowrootmode=\"open\"><link rel=\"stylesheet\" href=\"\/wp-content\/plugins\/code-syntax-highlighting-block\/public\/css\/themes\/atom-one-dark.min.css?i=4237ffca7ce6aadb438c457e0a675b125c534bbdda5b87f41f3a1495603bcc9b\"\/><pre><code class=\"hljs\">USERS = {\n    <span class=\"hljs-string\">&quot;admin&quot;<\/span>: <span class=\"hljs-string\">&quot;...&quot;<\/span>,\n    <span class=\"hljs-string\">&quot;operateur&quot;<\/span>: <span class=\"hljs-string\">&quot;...&quot;<\/span>,\n    <span class=\"hljs-string\">&quot;nouvel_utilisateur&quot;<\/span>: <span class=\"hljs-string\">&quot;SCIENT_HASH_G\u00c9N\u00c9R\u00c9_ICI...&quot;<\/span>\n}\n<\/code><\/pre><\/template><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pour piloter un synth\u00e9tiseur DDS AD9850 depuis une page web h\u00e9berg\u00e9e sur un Raspberry Pi 3 sous le dernier OS (Raspberry Pi OS Bookworm, qui utilise nativement la biblioth\u00e8que lgpio pour les GPIO), voici l&rsquo;architecture compl\u00e8te, le sch\u00e9ma de flux, le c\u00e2blage et le code source pr\u00eat \u00e0 l&#8217;emploi. 1. Architecture et Flux de Donn\u00e9es [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-36","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/posts\/36","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/comments?post=36"}],"version-history":[{"count":7,"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/posts\/36\/revisions"}],"predecessor-version":[{"id":45,"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/posts\/36\/revisions\/45"}],"wp:attachment":[{"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/media?parent=36"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/categories?post=36"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rf-diy.com\/index.php\/wp-json\/wp\/v2\/tags?post=36"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}