Lampe géodésique pilotable avec le WIFI de votre mobile !
L'idée de départ est de réutiliser une ampoule cassée pour en faire une lampe utilisant des LEDs. On peut trouver facilement des exemples d'ampoules de ce type dans le commerce !
J'ajoute des LEDs bleues à l'intérieur.
Je calcule les dimensions d'une structure géodésique en barreaux avec le site internet https://www.simplydifferently.org/Geodesic_Dome_Notes?page=3#2V/L2%20Icosahedron%20Dome
Pour le socle, je m'inspire de la montagne du destin (Mount Doom) décrite dans le roman le Seigneur des Anneaux de J. R. R. Tolkien (Sauron forge l'anneau unique dans les flammes de la montagne de feux, au Mordor ). Dans la trilogie cinématographique de Peter Jackson adaptée du Seigneur des Anneaux, le mont Ngauruhoe, un volcan de Nouvelle-Zélande, est choisi pour représenter la montagne du destin (https://fr.wikipedia.org/wiki/Mont_Destin).
J'utilise ce tutoriel pour créer le socle de la lampe : https://johnflower.org/tutorial/make-mountains-blender-heightmaps et je découpe cette simulation 3D en tranche comme j'ai déjà utilisé dans d'autres projet (par exemple T-REX Ball).
Et je modélise un nouveau culot en 3D pour assembler le tout !
Voici la simulation de l'assemblage sur Blender !
Intégration de la partie électronique dans le socle de la lampe !
Récupération d'une ampoule cassée et découpage du culot https://www.youtube.com/watch?v=KHANh7x2XtM.
Découpe à la découpeuse laser du socle .
Découpe à la découpeuse laser des barres géodésiques .
Impression 3D du culot culot.stl
Coller l'ampoule au nouveau culot en PLA !
Assembler le tout avec de la colle à bois, 5 vis M4 dans le culot, 8 vis et 8 écrous M4 pour le socle (méthode “Sandwich” en superposant les couches).
S’équiper d'un circuit ESP8266 (https://fr.aliexpress.com/item/32779189539.html) et de quatre guirlandes LEDs (https://fr.aliexpress.com/item/32799804772.html)
Voici un tuto pour comprendre les grandes lignes de la programmation de l'ESP8266 : https://f-leb.developpez.com/tutoriels/arduino/esp8266/debuter/
Ce programme comporte plusieurs animations pilotables via le navigateur WEB. Connectez-vous au WIFI de la Lampe NG avec votre téléphone, avec votre tablette ou avec votre ordinateur :
progng-20220805-vitrinecn2.ino
// Program for "LampeNG" made by Go2 on 2022/08/05 // Load Wi-Fi library #include <ESP8266WiFi.h> // Set web server port number to 80 WiFiServer server(80); // Variable to store the HTTP request String header; // Auxiliar variables to store the current output state String ONOFFState = "ON"; String GlittersState = "ON"; String FadeState = "OFF"; String GlittersSpeed = "2"; String FadeSpeed = "1"; int TimeTempo = 30; int count = 0; int brightness1 = 0; // how bright the LED is int brightness2 = 0; // how bright the LED is int brightness3 = 0; // how bright the LED is int brightness4 = 0; // how bright the LED is int fadeAmount1 = 10; // Set the amount to fade I usually do 5, 10, 15, 20, 25 etc even up to 255. int fadeAmount2 = 20; // how many points to fade the LED by int fadeAmount3 = 30; // how many points to fade the LED by int fadeAmount4 = 40; // how many points to fade the LED by static unsigned long lastTimeItHappened = 0; void setup() { Serial.begin(115200); // Initialize the output variables as outputs pinMode(D5, OUTPUT); // Initialize the D5 pin as an output pinMode(D6, OUTPUT); // Initialize the D6 pin as an output pinMode(D7, OUTPUT); // Initialize the D7 pin as an output pinMode(D8, OUTPUT); // Initialize the D8 pin as an output delay(2000); // 2 second delay for recovery // WIFI ACCESS POINT // ================= WiFi.mode(WIFI_AP); //Our ESP8266-12E is an AccessPoint WiFi.softAP("Go2design"); // Provide the SSID server.begin(); // Start the HTTP Server IPAddress HTTPS_ServerIP= WiFi.softAPIP(); // Obtain the IP of the Server Serial.print("Server IP is: "); // 192.168.4.1 Serial.println(HTTPS_ServerIP); } void loop(){ WiFiClient client = server.available(); // Listen for incoming clients // Call the current pattern function once, updating the 'leds' array if (millis() - lastTimeItHappened >= 1000) { // Ten seconds or more since it last happened lastTimeItHappened = millis(); count++; } if (count >= 115) // Reinit every 2mn (115 for execution of program) { ONOFFState = "ON"; GlittersState = "ON"; FadeState = "OFF"; TimeTempo = 30; count = 0; } if (count >= 1000) {count = 1;} // Reinit for limit of variable if (GlittersState == "ON") {Glitters(TimeTempo);} if (FadeState == "ON") {Fade(TimeTempo);} if (client) { // If a new client connects, Serial.println("New Client."); // print a message out in the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor header += c; if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println("Connection: close"); client.println(); count = 0 ; // turns the variable // push on MARCHE adress is ONOFF/off if (header.indexOf("GET /ONOFF/off") >= 0) { Serial.println("ONOFF off"); ONOFFState = "OFF"; GlittersState = "ON"; FadeState = "ON"; TimeTempo = 0; } else if (header.indexOf("GET /ONOFF/on") >= 0) { Serial.println("ONOFF on"); ONOFFState = "ON"; GlittersState = "ON"; FadeState = "OFF"; TimeTempo = 30; } else if (header.indexOf("GET /Glitters/on") >= 0) { Serial.println("Glitters on"); GlittersState = "OFF"; FadeState = "OFF"; TimeTempo = 0; } else if (header.indexOf("GET /Glitters/1") >= 0) { Serial.println("Glitters 1"); GlittersSpeed = "1"; TimeTempo = 10; } else if (header.indexOf("GET /Glitters/2") >= 0) { Serial.println("Glitters 2"); GlittersSpeed = "2"; TimeTempo = 30; } else if (header.indexOf("GET /Glitters/3") >= 0) { Serial.println("Glitters 3"); GlittersSpeed = "3"; TimeTempo = 60; } else if (header.indexOf("GET /Glitters/4") >= 0) { Serial.println("Glitters 4"); GlittersSpeed = "4"; TimeTempo = 90; } else if (header.indexOf("GET /Glitters/off") >= 0) { Serial.println("Glitter off"); ONOFFState = "ON"; GlittersState = "ON"; FadeState = "OFF"; GlittersSpeed = "2"; TimeTempo = 30; } else if (header.indexOf("GET /Fade/on") >= 0) { Serial.println("Fade on"); GlittersState = "OFF"; FadeState = "OFF"; Glitters(0); } else if (header.indexOf("GET /Fade/1") >= 0) { Serial.println("Fade 1"); FadeSpeed = "1"; TimeTempo = 30; } else if (header.indexOf("GET /Fade/2") >= 0) { Serial.println("Fade 2"); FadeSpeed = "2"; TimeTempo = 60; } else if (header.indexOf("GET /Fade/3") >= 0) { Serial.println("Fade 3"); FadeSpeed = "3"; TimeTempo = 90; } else if (header.indexOf("GET /Fade/off") >= 0) { Serial.println("Fade off"); ONOFFState = "ON"; GlittersState = "OFF"; FadeState = "ON"; FadeSpeed = "1"; TimeTempo = 30; } // Display the HTML web page client.println("<!DOCTYPE html><html>"); client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"); client.println("<link rel=\"icon\" href=\"data:,\">"); // CSS to style the on/off buttons // Feel free to change the background-color and font-size attributes to fit your preferences client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}"); client.println("body {background-color: darkblue;}"); client.println("h1 {font-family: Georgia, serif; color: white;}"); client.println("p {text-shadow: 1px 1px Gray; color: white;}"); client.println(".buttonON { background-color: #0B610B; border: none; color: white; padding: 16px 40px; border-radius: 8px; box-shadow: 0 4px 12px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19); text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer; text-shadow: #000444}"); client.println(".buttonOFF { background-color: #B40404; border: none; color: white; padding: 16px 40px; border-radius: 8px; box-shadow: 0 4px 12px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19); text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer; text-shadow: #000444;}"); client.println(".buttonGlitters { background-image: linear-gradient(90deg, grey 0%, white 15%, grey 30%, white 45%, grey 60%, white 75%, grey 90%, white 100%); border: none; color: black; padding: 15px 32px; border-radius: 8px; box-shadow: 0 2px 8px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19); font-family: Times, Times New Roman, serif; text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}"); client.println(".buttonGlittersoff { background-color: #000000; border: none; color: white; padding: 15px 32px; box-shadow: 0 2px 8px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19); text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer; border-radius: 12px;}"); client.println(".buttonFade { background-image: linear-gradient(to right, #0b2742 0%, #296bab 30%, #00dbde 51%, #296bab 70%, #0b2742 100%); border: none; color: black; padding: 15px 32px; box-shadow: 0 2px 8px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19);text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer; font-family:Impact, times, serif; border-radius: 12px;}"); client.println(".buttonFadeoff { background-color: #000000; border: none; color: white; padding: 15px 32px; box-shadow: 0 2px 8px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19); text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer; border-radius: 12px;}"); client.println(".buttonspeed { background-color: #4CAF50; border: none; color: black; padding: 15px 15px; text-align: center; text-decoration: none; display: inline-block; font-size: 15px; font-weight: bold; margin: 4px 2px; cursor: pointer; border-radius: 50%; border: 2px solid black; box-shadow: 0 4px 12px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19);}"); client.println(".buttonspeedoff { background-color: #f44336; border: none; color: black; padding: 15px 15px; text-align: center; text-decoration: none; display: inline-block; font-size: 15px; font-weight: bold; margin: 4px 2px; cursor: pointer; border-radius: 50%; border: 2px solid black; box-shadow: 0 4px 12px 0 rgba(0,0,0,1), 0 4px 20px 0 rgba(0,0,0,0.19);}"); client.println("</style></head>"); // Web Page Heading client.println("<body><h1>NG by Go²</h1>"); if (ONOFFState=="OFF") { client.println("<p><a href=/ONOFF/on><button class=buttonOFF>ARRET</button></a></p>"); } else if (ONOFFState=="ON"){ client.println("<p><a href=/ONOFF/off><button class=buttonON>MARCHE</button></a></p>"); if (GlittersState=="OFF") { client.println("<p><a href=\"/Glitters/off\"><button class=buttonGlittersoff>Glitters</button></a></p>"); } else { client.println("<p><a href=\"/Glitters/on\"><button class=buttonGlitters>Glitters</button></a></p>"); if (GlittersSpeed=="1") { client.println("<a href=\"/Glitters/1\"><button class=buttonspeed>1</button></a>"); client.println("<a href=\"/Glitters/2off\"><button class=buttonspeedoff>2</button></a>"); client.println("<a href=\"/Glitters/3off\"><button class=buttonspeedoff>3</button></a>"); client.println("<a href=\"/Glitters/4off\"><button class=buttonspeedoff>4</button></a>"); } else if (GlittersSpeed=="2") { client.println("<a href=\"/Glitters/1off\"><button class=buttonspeedoff>1</button></a>"); client.println("<a href=\"/Glitters/2\"><button class=buttonspeed>2</button></a>"); client.println("<a href=\"/Glitters/3off\"><button class=buttonspeedoff>3</button></a>"); client.println("<a href=\"/Glitters/4off\"><button class=buttonspeedoff>4</button></a>"); } else if (GlittersSpeed=="3") { client.println("<a href=\"/Glitters/1off\"><button class=buttonspeedoff>1</button></a>"); client.println("<a href=\"/Glitters/2off\"><button class=buttonspeedoff>2</button></a>"); client.println("<a href=\"/Glitters/3\"><button class=buttonspeed>3</button></a>"); client.println("<a href=\"/Glitters/4off\"><button class=buttonspeedoff>4</button></a>"); } else if (GlittersSpeed=="4") { client.println("<a href=\"/Glitters/1off\"><button class=buttonspeedoff>1</button></a>"); client.println("<a href=\"/Glitters/2off\"><button class=buttonspeedoff>2</button></a>"); client.println("<a href=\"/Glitters/3off\"><button class=buttonspeedoff>3</button></a>"); client.println("<a href=\"/Glitters/4\"><button class=buttonspeed>4</button></a>"); } } if (FadeState=="OFF") { client.println("<p><a href=\"/Fade/off\"><button class=buttonFadeoff>Fade</button></a></p>"); } else { client.println("<p><a href=\"/Fade/on\"><button class=buttonFade>Fade</button></a></p>"); if (FadeSpeed=="1") { client.println("<a href=\"/Fade/1\"><button class=buttonspeed>1</button></a>"); client.println("<a href=\"/Fade/2off\"><button class=buttonspeedoff>2</button></a>"); client.println("<a href=\"/Fade/3off\"><button class=buttonspeedoff>3</button></a>"); } else if (FadeSpeed=="2") { client.println("<a href=\"/Fade/1off\"><button class=buttonspeedoff>1</button></a>"); client.println("<a href=\"/Fade/2\"><button class=buttonspeed>2</button></a>"); client.println("<a href=\"/Fade/3off\"><button class=buttonspeedoff>3</button></a>"); } else if (FadeSpeed=="3") { client.println("<a href=\"/Fade/1off\"><button class=buttonspeedoff>1</button></a>"); client.println("<a href=\"/Fade/2off\"><button class=buttonspeedoff>2</button></a>"); client.println("<a href=\"/Fade/3\"><button class=buttonspeed>3</button></a>"); } } } client.println("</body></html>"); // The HTTP response ends with another blank line client.println(); // Break out of the while loop break; } else { // if you got a newline, then clear currentLine currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } } } // Clear the header variable header = ""; // Close the connection client.stop(); Serial.println("Client disconnected."); Serial.println(""); } } void Glitters (int TimeTempo) { if (TimeTempo > 0) { digitalWrite(D5, HIGH); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is active low on the ESP-01) delay(TimeTempo); // Wait for a second digitalWrite(D5, LOW); // Turn the LED off by making the voltage HIGH delay(TimeTempo); // Wait for two seconds (to demonstrate the active low LED) digitalWrite(D6, HIGH); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is active low on the ESP-01) delay(TimeTempo); // Wait for a second digitalWrite(D6, LOW); // Turn the LED off by making the voltage HIGH delay(TimeTempo); // Wait for two seconds (to demonstrate the active low LED) digitalWrite(D7, HIGH); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is active low on the ESP-01) delay(TimeTempo); // Wait for a second digitalWrite(D7, LOW); // Turn the LED off by making the voltage HIGH delay(TimeTempo); // Wait for two seconds (to demonstrate the active low LED) digitalWrite(D8, HIGH); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is active low on the ESP-01) delay(TimeTempo); // Wait for a second digitalWrite(D8, LOW); // Turn the LED off by making the voltage HIGH delay(TimeTempo); // Wait for two seconds (to demonstrate the active low LED) } else { digitalWrite(D5, LOW); // Turn the LED off by making the voltage HIGH digitalWrite(D6, LOW); // Turn the LED off by making the voltage HIGH digitalWrite(D7, LOW); // Turn the LED off by making the voltage HIGH digitalWrite(D8, LOW); // Turn the LED off by making the voltage HIGH } } void Fade(int TimeTempo) { if (TimeTempo > 0) { analogWrite(D5, brightness1); // change the brightness for next time through the loop: brightness1 = brightness1 + fadeAmount1; if (brightness1 <= 0 || brightness1 >= 255) { fadeAmount1 = -fadeAmount1; } // wait to see the dimming effect delay(TimeTempo); analogWrite(D6, brightness2); // change the brightness for next time through the loop: brightness2 = brightness2 + fadeAmount2; if (brightness2 <= 0 || brightness2 >= 255) { fadeAmount2 = -fadeAmount2; } // wait to see the dimming effect delay(TimeTempo); analogWrite(D7, brightness3); // change the brightness for next time through the loop: brightness3 = brightness3 + fadeAmount3; if (brightness3 <= 0 || brightness3 >= 255) { fadeAmount3 = -fadeAmount3; } // wait to see the dimming effect delay(TimeTempo); analogWrite(D8, brightness4); // change the brightness for next time through the loop: brightness4 = brightness4 + fadeAmount4; if (brightness4 <= 0 || brightness4 >= 255) { fadeAmount4 = -fadeAmount4; } // wait to see the dimming effect delay(TimeTempo); } else { digitalWrite(D5, LOW); // Turn the LED off by making the voltage HIGH digitalWrite(D6, LOW); // Turn the LED off by making the voltage HIGH digitalWrite(D7, LOW); // Turn the LED off by making the voltage HIGH digitalWrite(D8, LOW); // Turn the LED off by making the voltage HIGH } }
Malheureusement après avoir transporté plusieurs fois à vélo la Lampe NG durant l'épisode du Covid19, l'ampoule s'est décollée… Je l'ai recollée mais comme le nouveau cordon de colle dépassait de sa position initiale cela n'était plus esthétique. La partie haute de la Lampe NG est indémontable, j'ai donc du modéliser, imprimer et monter une bague haute supplémentaire en plusieurs parties pour la coller à travers les barreaux géodésiques.
Inspiration : https://blendswap.com/blend/6355
Inspiration : https://dimensiva.com/3dmodels/armchair-daw-by-vitra-eames/ & https://www.designconnected.com/fr/category/Tables/E-Volved-table_p3882
Une nouvelle lampe est en préparation, inspirée des projets suivants :
- Lampe champignon par bumblebee
- Dôme géodésique fréquence 3 par bubuchelabuche
Retrouvez cette nouvelle version sur internet avec le QRcode ci-dessous
Made by Go2