Récupération d’une boîte de séchage de filament eSUN
Quand j’ai reçu cette boîte de séchage, achetée sur Amazon, elle n’affichait rien. Plutôt que de la retourner, j’ai décidé de la réparer et de l’améliorer juste pour le plaisir.
Modifications :
Le panneau frontal
Je l’ai dessiné, à l’époque, avec 123D Design d’Autodesk et imprimé en PLA.

Vous pouvez télécharger les fichiers 3D en cliquant sur le bouton ci-dessous
Le programme 123D design a été vérifié avec l’anti-virus Sophos Home.
Voici l’empreinte SHA256 du fichier ZIP : 2C3111B28E834064A1E5CDF74F7114953A0B6639050717DD5F2B7C39E10669EF
Le panneau imprimé

Muni de l’interrupteur, de l’écran et du circuit

Peuplé et câblé

Vue de l’adaptateur de programmation

Le schéma

Le programme
Il est encore à peaufiner mais il fonctionne déjà.
7.95 KB
```cpp
// ============================================================================
// BOÎTE DE SÉCHAGE / CHAUFFAGE DE FILAMENT
// VERSION 2 - CORRIGÉE ET COMMENTÉE
// ============================================================================
//
// Matériel utilisé :
// - Arduino
// - Écran OLED SSD1306 128x32 en I2C
// - Capteur DHT22
// - CTN pour mesurer la température du lit chauffant
// - Chauffage commandé par le pin 9
// - Ventilateur commandé par le pin 3
// - Bouton + sur le pin 10
// - Bouton - sur le pin 11
// - Bouton MODE sur le pin 12
//
// Fonctionnement général :
// 1. Choix du type de filament
// 2. Choix de la durée
// 3. Chauffage et ventilation
// 4. Régulation de la température de la chambre
// 5. Fin du cycle
// 6. Refroidissement pendant 30 secondes
//
// ============================================================================
// ============================================================================
// BIBLIOTHÈQUES
// ============================================================================
#include <U8g2_for_Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>
// ============================================================================
// CONFIGURATION DE L'ÉCRAN
// ============================================================================
// Écran OLED 128 x 32 pixels.
// &Wire = communication I2C.
// 4 = broche RESET utilisée par l'écran.
Adafruit_SSD1306 display(128, 32, &Wire, 4);
// Objet permettant d'utiliser les polices U8g2
// avec la bibliothèque Adafruit GFX.
U8G2_FOR_ADAFRUIT_GFX udisplay;
// ============================================================================
// CONFIGURATION DU DHT22
// ============================================================================
// Le DHT22 est connecté sur la broche 2.
#define DHT_PIN 2
DHT dht(DHT_PIN, DHT22);
// ============================================================================
// BROCHES
// ============================================================================
#define bouton_plus_pin 10
#define bouton_moins_pin 11
#define bouton_mode_pin 12
#define ctn_pin A3
#define chauffage_pin 9
#define ventilo_pin 3
// ============================================================================
// PROFILS DE FILAMENT
// ============================================================================
// Chaque valeur représente la température souhaitée
// dans la chambre de séchage.
//
// Index :
// 0 = Refroidir
// 1 = PLA & PLA+
// 2 = PETG
// 3 = ABS & ABS+
// 4 = PVA
// 5 = NYLON
// 6 = PC
// 7 = TPU
const float consigne_chambre[] = {
0,
40,
50,
50,
55,
55,
55,
40
};
// Nom des différents profils.
const char* filament[] = {
"Refroidir",
"PLA & PLA+",
"PETG",
"ABS & ABS+",
"PVA",
"NYLON",
"PC",
"TPU"
};
// Nombre de profils disponibles.
const byte NOMBRE_FILAMENTS = 8;
// ============================================================================
// VARIABLES DES BOUTONS
// ============================================================================
//
// Les boutons utilisent INPUT_PULLUP.
//
// Donc :
// HIGH = bouton relâché
// LOW = bouton appuyé
//
// ============================================================================
bool bouton_plus = HIGH;
bool bouton_moins = HIGH;
bool bouton_mode = HIGH;
// ============================================================================
// VARIABLES DE FONCTIONNEMENT
// ============================================================================
// Index du filament sélectionné.
byte indexFilament = 0;
// Indique si un cycle de séchage est actuellement en cours.
bool en_service = false;
// Indique si le programme est dans la phase de refroidissement.
bool refroidissement = false;
// ============================================================================
// VARIABLES DE TEMPERATURE
// ============================================================================
// Température de la chambre mesurée par le DHT22.
float temperature_chambre = 0.0;
// Humidité mesurée par le DHT22.
float humidite_chambre = 0.0;
// Température estimée du lit chauffant.
float temperature_lit = 0.0;
// ============================================================================
// REGULATION DU LIT
// ============================================================================
//
// Cette valeur correspond à la mesure brute de la CTN.
//
// Dans ton programme original :
//
// température_lit = 1024 - analogRead(ctn_pin)
//
// puis :
//
// température approximative = température_lit / 8.5
//
// On conserve ici cette méthode afin de ne pas changer ton étalonnage.
//
// ============================================================================
int consigne_lit = 550;
// Consigne maximale autorisée pour le lit.
const int CONSIGNE_LIT_MAX = 550;
// Consigne minimale.
//
// On évite qu'elle descende trop bas.
const int CONSIGNE_LIT_MIN = 0;
// ============================================================================
// GESTION DU TEMPS
// ============================================================================
// Moment de la dernière lecture du DHT22.
unsigned long mesure_precedente = 0;
// Intervalle entre deux mesures DHT22.
const unsigned long INTERVALLE_DHT = 3000;
// Durée choisie par l'utilisateur.
//
// Cette variable contient une durée en millisecondes
// pendant la sélection.
//
// Une fois le cycle lancé, elle devient le moment de fin.
unsigned long duree = 0;
// Moment auquel le cycle doit se terminer.
unsigned long fin_cycle = 0;
// Moment auquel le refroidissement doit se terminer.
unsigned long fin_refroidissement = 0;
// ============================================================================
// SYMBOLES DE L'ÉCRAN
// ============================================================================
int symbole_chauffage = 72;
int symbole_ventilo = 32;
// ============================================================================
// FONCTIONS DE COMMANDE DU CHAUFFAGE
// ============================================================================
// ---------------------------------------------------------------------------
// Allume le chauffage.
// ---------------------------------------------------------------------------
void chauffageON() {
digitalWrite(chauffage_pin, HIGH);
// Symbole indiquant que le chauffage fonctionne.
symbole_chauffage = 67;
}
// ---------------------------------------------------------------------------
// Éteint le chauffage.
// ---------------------------------------------------------------------------
void chauffageOFF() {
digitalWrite(chauffage_pin, LOW);
// Symbole indiquant que le chauffage est arrêté.
symbole_chauffage = 64;
}
// ============================================================================
// FONCTIONS DE COMMANDE DU VENTILATEUR
// ============================================================================
// ---------------------------------------------------------------------------
// Allume le ventilateur.
// ---------------------------------------------------------------------------
void ventiloON() {
digitalWrite(ventilo_pin, HIGH);
// Symbole indiquant que le ventilateur fonctionne.
symbole_ventilo = 64;
}
// ---------------------------------------------------------------------------
// Éteint le ventilateur.
// ---------------------------------------------------------------------------
void ventiloOFF() {
digitalWrite(ventilo_pin, LOW);
// Symbole indiquant que le ventilateur est arrêté.
symbole_ventilo = 32;
}
// ============================================================================
// LECTURE DU DHT22
// ============================================================================
//
// Le DHT22 ne doit pas être interrogé en permanence.
//
// On effectue donc une lecture toutes les 3 secondes.
//
// ============================================================================
void lireDHT() {
// Vérifie si 3 secondes se sont écoulées depuis la dernière mesure.
if (millis() - mesure_precedente >= INTERVALLE_DHT) {
// Mémorise le moment de la mesure.
mesure_precedente = millis();
// Lecture de l'humidité.
float nouvelleHumidite = dht.readHumidity();
// Lecture de la température.
float nouvelleTemperature = dht.readTemperature();
// Vérification des mesures.
if (isnan(nouvelleHumidite) || isnan(nouvelleTemperature)) {
Serial.println("Erreur de lecture du DHT22");
// On conserve les anciennes valeurs
// si la nouvelle mesure est invalide.
return;
}
// Les mesures sont valides :
// on peut les enregistrer.
humidite_chambre = nouvelleHumidite;
temperature_chambre = nouvelleTemperature;
// Affichage dans le moniteur série.
Serial.print("Temperature : ");
Serial.print(temperature_chambre);
Serial.print(" C Humidite : ");
Serial.print(humidite_chambre);
Serial.println(" %");
}
}
// ============================================================================
// MESURE DE LA CTN
// ============================================================================
void lireCTN() {
// Lecture analogique de la CTN.
int mesureCTN = analogRead(ctn_pin);
// Inversion de la mesure comme dans ton programme original.
int valeur = 1024 - mesureCTN;
// Conversion approximative en température.
//
// ATTENTION :
// Cette conversion dépend de ton montage et de ton étalonnage.
// Le facteur 8.5 vient de ton programme original.
temperature_lit = valeur / 8.5;
}
// ============================================================================
// REGULATION DE LA TEMPERATURE
// ============================================================================
void regulation() {
// Mesure du lit.
lireCTN();
// Mesure du DHT22 lorsque l'intervalle est atteint.
lireDHT();
// --------------------------------------------------------------------------
// SI LE CYCLE EST EN COURS
// --------------------------------------------------------------------------
if (en_service) {
// ------------------------------------------------------------------------
// REGULATION DU LIT
// ------------------------------------------------------------------------
// Si le lit est trop chaud :
// on coupe le chauffage.
if (temperature_lit > (consigne_lit / 8.5) + 0.5) {
chauffageOFF();
}
// Si le lit est suffisamment froid :
// on peut chauffer.
//
// On vérifie également que la chambre n'est pas déjà
// au-dessus de sa température cible.
if (temperature_lit < (consigne_lit / 8.5) - 0.5 &&
temperature_chambre < consigne_chambre[indexFilament]) {
chauffageON();
}
// ------------------------------------------------------------------------
// ADAPTATION DE LA CONSIGNE DU LIT
// ------------------------------------------------------------------------
//
// Si la chambre est trop chaude :
// on diminue la consigne du lit.
//
// Si la chambre est trop froide :
// on augmente la consigne du lit.
//
// Cela constitue une régulation simple de la température de la chambre.
// ------------------------------------------------------------------------
if (temperature_chambre >
consigne_chambre[indexFilament] + 0.5) {
consigne_lit -= 10;
}
if (temperature_chambre <
consigne_chambre[indexFilament] - 0.5) {
consigne_lit += 10;
}
// ------------------------------------------------------------------------
// LIMITATION DE LA CONSIGNE DU LIT
// ------------------------------------------------------------------------
if (consigne_lit > CONSIGNE_LIT_MAX) {
consigne_lit = CONSIGNE_LIT_MAX;
}
if (consigne_lit < CONSIGNE_LIT_MIN) {
consigne_lit = CONSIGNE_LIT_MIN;
}
}
}
// ============================================================================
// AFFICHAGE
// ============================================================================
void affichage() {
// Efface l'écran.
display.clearDisplay();
// --------------------------------------------------------------------------
// ICÔNE CHAUFFAGE
// --------------------------------------------------------------------------
udisplay.setFont(u8g2_font_open_iconic_arrow_1x_t);
udisplay.setFontMode(1);
udisplay.setCursor(0, 8);
udisplay.print(char(symbole_chauffage));
// --------------------------------------------------------------------------
// ICÔNE VENTILATEUR
// --------------------------------------------------------------------------
udisplay.setFont(u8g2_font_open_iconic_other_1x_t);
udisplay.setCursor(10, 8);
udisplay.print(char(symbole_ventilo));
// Police normale.
udisplay.setFont(u8g2_font_6x12_tf);
// --------------------------------------------------------------------------
// COMPTE À REBOURS
// --------------------------------------------------------------------------
if (en_service) {
// Calcul du temps restant.
//
// Cette écriture est sûre tant que le test est effectué
// avant la soustraction.
unsigned long restant = 0;
if (fin_cycle > millis()) {
restant = fin_cycle - millis();
}
// Position du compteur.
udisplay.setCursor(30, 8);
// Conversion en heures.
unsigned long heures = restant / 3600000UL;
// Conversion en minutes.
unsigned long minutes =
(restant / 60000UL) % 60;
// Affichage HH:MM.
if (heures < 10) {
udisplay.print("0");
}
udisplay.print(heures);
udisplay.print(":");
if (minutes < 10) {
udisplay.print("0");
}
udisplay.print(minutes);
}
// --------------------------------------------------------------------------
// TEMPERATURE DU LIT
// --------------------------------------------------------------------------
udisplay.setCursor(96, 8);
udisplay.print(temperature_lit, 0);
// --------------------------------------------------------------------------
// TEMPERATURE / HUMIDITE DE LA CHAMBRE
// --------------------------------------------------------------------------
udisplay.setFont(u8g2_font_10x20_tf);
// Température.
udisplay.setCursor(0, 23);
udisplay.print(temperature_chambre, 1);
udisplay.print("°");
// Humidité.
udisplay.setCursor(64, 23);
udisplay.print(humidite_chambre, 1);
udisplay.print("%");
// Envoie l'affichage vers l'écran.
display.display();
}
// ============================================================================
// ATTENTE D'UN APPUI SUR MODE
// ============================================================================
//
// Petite fonction permettant d'attendre que l'utilisateur appuie sur MODE.
//
// ============================================================================
void attendreMode() {
// Attendre que le bouton soit relâché avant de commencer.
while (digitalRead(bouton_mode_pin) == LOW) {
delay(10);
}
// Attendre un appui.
while (digitalRead(bouton_mode_pin) == HIGH) {
delay(10);
}
// Anti-rebond.
delay(80);
// Attendre que le bouton soit relâché.
while (digitalRead(bouton_mode_pin) == LOW) {
delay(10);
}
}
// ============================================================================
// CHOIX DU FILAMENT
// ============================================================================
void choisirFilament() {
// --------------------------------------------------------------------------
// BOUCLE DE SELECTION
// --------------------------------------------------------------------------
while (true) {
// Lecture du bouton +.
if (digitalRead(bouton_plus_pin) == LOW) {
delay(80);
if (digitalRead(bouton_plus_pin) == LOW) {
indexFilament++;
// Retour au premier choix après le dernier.
if (indexFilament >= NOMBRE_FILAMENTS) {
indexFilament = 0;
}
// Attendre le relâchement du bouton.
while (digitalRead(bouton_plus_pin) == LOW) {
delay(10);
}
}
}
// ------------------------------------------------------------------------
// BOUTON -
// ------------------------------------------------------------------------
if (digitalRead(bouton_moins_pin) == LOW) {
delay(80);
if (digitalRead(bouton_moins_pin) == LOW) {
// Si on est déjà au premier choix,
// on revient au dernier.
if (indexFilament == 0) {
indexFilament = NOMBRE_FILAMENTS - 1;
}
else {
indexFilament--;
}
// Attendre le relâchement.
while (digitalRead(bouton_moins_pin) == LOW) {
delay(10);
}
}
}
// ------------------------------------------------------------------------
// AFFICHAGE
// ------------------------------------------------------------------------
display.clearDisplay();
udisplay.setFont(u8g2_font_6x12_tf);
udisplay.setCursor(0, 8);
udisplay.print("Choix du Filament");
udisplay.setFont(u8g2_font_10x20_tf);
udisplay.setCursor(0, 23);
udisplay.print(filament[indexFilament]);
display.display();
// ------------------------------------------------------------------------
// VALIDATION AVEC MODE
// ------------------------------------------------------------------------
if (digitalRead(bouton_mode_pin) == LOW) {
delay(80);
if (digitalRead(bouton_mode_pin) == LOW) {
// Attendre le relâchement.
while (digitalRead(bouton_mode_pin) == LOW) {
delay(10);
}
return;
}
}
}
}
// ============================================================================
// CHOIX DE LA DUREE
// ============================================================================
//
// La durée est réglable par pas de 15 minutes.
//
// Minimum : 15 minutes
// Maximum : 18 heures
//
// ============================================================================
void choisirDuree() {
// Durée initiale.
unsigned long dureeChoisie = 0;
// --------------------------------------------------------------------------
// BOUCLE DE SELECTION
// --------------------------------------------------------------------------
while (true) {
// ------------------------------------------------------------------------
// BOUTON +
// ------------------------------------------------------------------------
if (digitalRead(bouton_plus_pin) == LOW) {
delay(80);
if (digitalRead(bouton_plus_pin) == LOW) {
// +15 minutes.
dureeChoisie += 15UL * 60UL * 1000UL;
// Si on dépasse 18 heures :
// on revient à zéro.
if (dureeChoisie > 18UL * 60UL * 60UL * 1000UL) {
dureeChoisie = 0;
}
// Attendre le relâchement.
while (digitalRead(bouton_plus_pin) == LOW) {
delay(10);
}
}
}
// ------------------------------------------------------------------------
// BOUTON -
// ------------------------------------------------------------------------
if (digitalRead(bouton_moins_pin) == LOW) {
delay(80);
if (digitalRead(bouton_moins_pin) == LOW) {
// Si la durée vaut zéro,
// le bouton - ramène à 18 heures.
if (dureeChoisie < 15UL * 60UL * 1000UL) {
dureeChoisie =
18UL * 60UL * 60UL * 1000UL;
}
else {
dureeChoisie -=
15UL * 60UL * 1000UL;
}
// Attendre le relâchement.
while (digitalRead(bouton_moins_pin) == LOW) {
delay(10);
}
}
}
// ------------------------------------------------------------------------
// AFFICHAGE
// ------------------------------------------------------------------------
display.clearDisplay();
udisplay.setFont(u8g2_font_6x12_tf);
udisplay.setCursor(0, 8);
udisplay.print("Duree (Max 18 H)");
udisplay.setFont(u8g2_font_10x20_tf);
udisplay.setCursor(0, 23);
// Conversion en heures.
unsigned long heures =
dureeChoisie / 3600000UL;
// Conversion en minutes.
unsigned long minutes =
(dureeChoisie / 60000UL) % 60;
// Affichage HH:MM.
if (heures < 10) {
udisplay.print("0");
}
udisplay.print(heures);
udisplay.print(":");
if (minutes < 10) {
udisplay.print("0");
}
udisplay.print(minutes);
display.display();
// ------------------------------------------------------------------------
// VALIDATION
// ------------------------------------------------------------------------
if (digitalRead(bouton_mode_pin) == LOW) {
delay(80);
if (digitalRead(bouton_mode_pin) == LOW) {
// On mémorise la durée choisie.
duree = dureeChoisie;
// Attendre le relâchement.
while (digitalRead(bouton_mode_pin) == LOW) {
delay(10);
}
return;
}
}
}
}
// ============================================================================
// MENU PRINCIPAL
// ============================================================================
void Choix() {
// --------------------------------------------------------------------------
// CHOIX DU FILAMENT
// --------------------------------------------------------------------------
choisirFilament();
// --------------------------------------------------------------------------
// CHOIX DE LA DUREE
// --------------------------------------------------------------------------
choisirDuree();
// --------------------------------------------------------------------------
// DEMARRAGE DU CYCLE
// --------------------------------------------------------------------------
// Si l'utilisateur a choisi "Refroidir",
// il n'y a pas de cycle de chauffage.
if (indexFilament == 0) {
return;
}
// Calcul du moment exact où le cycle devra se terminer.
//
// IMPORTANT :
// millis() + durée est utilisé ici.
//
// Les tests de temps dans le reste du programme sont effectués
// de manière compatible avec le débordement de millis().
fin_cycle = millis() + duree;
// La boîte passe en fonctionnement.
en_service = true;
refroidissement = false;
// Mise en route du ventilateur.
ventiloON();
// La consigne du lit repart à sa valeur maximale.
consigne_lit = CONSIGNE_LIT_MAX;
// --------------------------------------------------------------------------
// BOUCLE DU CYCLE
// --------------------------------------------------------------------------
while (en_service) {
// Mesures et régulation.
regulation();
// Affichage.
affichage();
// ------------------------------------------------------------------------
// VERIFICATION DE LA FIN DU CYCLE
// ------------------------------------------------------------------------
if ((long)(millis() - fin_cycle) >= 0) {
// Le temps est écoulé.
en_service = false;
}
// ------------------------------------------------------------------------
// POSSIBILITE D'ARRET MANUEL
// ------------------------------------------------------------------------
if (digitalRead(bouton_mode_pin) == LOW) {
delay(80);
if (digitalRead(bouton_mode_pin) == LOW) {
// Arrêt immédiat du cycle.
en_service = false;
// Attendre le relâchement du bouton.
while (digitalRead(bouton_mode_pin) == LOW) {
delay(10);
}
}
}
// Petite pause pour ne pas faire tourner le programme
// inutilement à pleine vitesse.
delay(50);
}
// --------------------------------------------------------------------------
// FIN DU CHAUFFAGE
// --------------------------------------------------------------------------
chauffageOFF();
// --------------------------------------------------------------------------
// REFROIDISSEMENT
// --------------------------------------------------------------------------
// Le ventilateur reste allumé pendant 30 secondes.
refroidissement = true;
fin_refroidissement = millis() + 30000UL;
while ((long)(millis() - fin_refroidissement) < 0) {
// Le ventilateur continue de tourner.
ventiloON();
// On continue à mesurer les températures.
regulation();
// Affichage.
affichage();
delay(50);
}
// Fin du refroidissement.
ventiloOFF();
refroidissement = false;
// --------------------------------------------------------------------------
// RESET
// --------------------------------------------------------------------------
indexFilament = 0;
consigne_lit = CONSIGNE_LIT_MAX;
duree = 0;
symbole_chauffage = 72;
// Petit délai avant de revenir au menu.
delay(100);
}
// ============================================================================
// SETUP
// ============================================================================
void setup() {
// --------------------------------------------------------------------------
// BOUTONS
// --------------------------------------------------------------------------
pinMode(bouton_plus_pin, INPUT_PULLUP);
pinMode(bouton_moins_pin, INPUT_PULLUP);
pinMode(bouton_mode_pin, INPUT_PULLUP);
// --------------------------------------------------------------------------
// CHAUFFAGE
// --------------------------------------------------------------------------
pinMode(chauffage_pin, OUTPUT);
chauffageOFF();
// --------------------------------------------------------------------------
// VENTILATEUR
// --------------------------------------------------------------------------
pinMode(ventilo_pin, OUTPUT);
ventiloOFF();
// --------------------------------------------------------------------------
// PORT SERIE
// --------------------------------------------------------------------------
Serial.begin(9600);
// --------------------------------------------------------------------------
// ECRAN
// --------------------------------------------------------------------------
display.begin(SSD1306_SWITCHCAPVCC);
udisplay.begin(display);
// --------------------------------------------------------------------------
// DHT22
// --------------------------------------------------------------------------
dht.begin();
// Petite pause de démarrage.
delay(500);
// Première lecture du DHT22.
temperature_chambre = dht.readTemperature();
humidite_chambre = dht.readHumidity();
// Si la première lecture échoue,
// on utilise des valeurs par défaut.
if (isnan(temperature_chambre)) {
temperature_chambre = 0;
}
if (isnan(humidite_chambre)) {
humidite_chambre = 0;
}
}
// ============================================================================
// LOOP PRINCIPAL
// ============================================================================
void loop() {
// --------------------------------------------------------------------------
// AFFICHAGE DU MENU PRINCIPAL
// --------------------------------------------------------------------------
display.clearDisplay();
udisplay.setFont(u8g2_font_6x12_tf);
udisplay.setCursor(0, 8);
udisplay.print("Boite Filament");
udisplay.setCursor(0, 20);
udisplay.print("MODE = choix");
udisplay.setCursor(0, 31);
udisplay.print("Temp: ");
udisplay.print(temperature_chambre, 1);
udisplay.print(" C");
display.display();
// Mise à jour du DHT22.
lireDHT();
// --------------------------------------------------------------------------
// BOUTON MODE
// --------------------------------------------------------------------------
if (digitalRead(bouton_mode_pin) == LOW) {
delay(80);
if (digitalRead(bouton_mode_pin) == LOW) {
// Lance le menu.
Choix();
// Attendre le relâchement du bouton.
while (digitalRead(bouton_mode_pin) == LOW) {
delay(10);
}
}
}
delay(50);
}
```












