Aller au contenu
Accueil » Articles » Prise en charge des scripts Lua

Prise en charge des scripts Lua

Le Samovar prend en charge l’automatisation avec le langage de script Lua. Les scripts pilotent des équipements externes (vannes, pompes, agitateur, éléments chauffants, relais), lisent les valeurs des capteurs et modifient la logique du processus pour l’adapter à votre installation. Les fonctions de base du contrôleur ne changent pas.

L’éditeur de scripts est intégré à l’interface web : Settings → Editor. Il offre la coloration syntaxique pour Lua, JS, CSS, HTML et JSON, la vérification de l’équilibre des parenthèses et des blocs function … end, ainsi que l’autocomplétion avec la touche Tab.

Interpréteur : Lua 5.4.4. L’API de base de la bibliothèque Arduino intégrée à l’ESP32 est complétée par des fonctions d’accès aux capteurs, au chauffage, aux pompes, à l’agitateur et aux relais.

Comment l’activer

Par défaut, la prise en charge de Lua est désactivée dans le firmware. Pour l’activer, ouvrez le fichier Samovar_ini.h dans le répertoire du firmware et remplacez la ligne

//#define USE_LUA

par

#define USE_LUA

Ensuite, recompilez le firmware et téléversez-le dans le contrôleur.

Architecture

Au démarrage du contrôleur, le fichier init.lua est exécuté. Son rôle est d’initialiser les variables qui serviront dans les autres scripts et d’activer ou de désactiver la boucle d’exécution une fois par seconde (setNumVariable("loop_lua_fl", 1)).

Si la boucle est activée, deux scripts sont exécutés l’un après l’autre chaque seconde :

  1. Le script commun script.lua — il s’exécute dans tous les modes.
  2. Le script du mode en cours : beer.lua (bière), bk.lua (colonne à moût), nbk.lua (colonne à moût continue), dist.lua (distillation), rectificat.lua (rectification), cheese.lua (fabrication du fromage) ou suvid.lua (sous-vide).

Si un script n’a pas terminé au lancement suivant, ce lancement est ignoré : un script déjà en cours n’est pas interrompu.

Une exécution unique de tous les scripts est possible à l’adresse http://samovar.local/lua.

Outre les scripts principaux, des boutons supplémentaires par mode sont pris en charge — des fichiers de la forme btn_<mode>_buttonN.lua, par exemple btn_rect_button1.lua. Ils s’affichent dans l’interface web et permettent d’appeler votre propre code lors d’un appui.

Important. Lors de la mise à jour du firmware, l’interface web télécharge depuis le serveur les versions de référence de init.lua, script.lua, des fichiers de mode et de btn_*.lua, mais uniquement si ce fichier n’existe pas encore dans la mémoire du contrôleur. Les scripts de l’utilisateur ne sont pas écrasés. Conservez tout de même vos propres versions sur votre ordinateur : après une réinitialisation d’usine ou une réinstallation de l’interface web, elles seront perdues.

Équipements externes

Des extenseurs de ports I²C peuvent être connectés aux scripts :

  • PCF8575 — un extenseur de 16 ports numériques (défini par le drapeau USE_EXPANDER). Chaque port peut accueillir un actionneur ou un capteur de type « bouton ». Tous les ports sont disponibles en lecture comme en écriture.
  • PCF8591 — un extenseur de ports analogiques (défini par le drapeau USE_ANALOG_EXPANDER). Il sert aux capteurs analogiques — par exemple une électrode de pH en mode fromagerie.

Les façons d’utiliser les extenseurs sont nombreuses : vous pouvez réaliser votre propre capteur de sécurité qui arrête le Samovar depuis un script lorsqu’il se déclenche, ou piloter une résistance chauffante supplémentaire selon la température de la vapeur. La logique précise dépend de votre équipement.

Fonctions

GPIO et fonctions compatibles Arduino

pinMode(pin, mode) — le mode entrée/sortie. Seules les broches RELE_CHANNEL1, RELE_CHANNEL2, RELE_CHANNEL3, RELE_CHANNEL4 et LUA_PIN sont disponibles. Les valeurs numériques des broches dépendent du plan des broches et figurent dans la description des GPIO.

digitalWrite(pin, value) — envoie HIGH (1) ou LOW (0) sur une broche.

digitalRead(pin) — lit la valeur actuelle d’une broche (HIGH ou LOW).

analogRead() — lit la valeur analogique de la broche LUA_PIN dans la plage 0–4095. Une électrode de pH ou un capteur de pression MPX5010DP est relié à cette broche, donc n’y appliquez pas plus de 3,3 V : cela détruirait l’ESP32.

delay(ms) — une pause en millisecondes.

millis() — les millisecondes écoulées depuis le démarrage du contrôleur.

Extenseurs de ports

exp_pinMode(pin, mode), exp_digitalWrite(pin, value), exp_digitalRead(pin) — comme les fonctions GPIO, mais pour les ports du PCF8575 (0–15).

exp_analogRead(), exp_analogWrite(value) — opérations analogiques sur le PCF8591. Disponibles uniquement lorsque USE_ANALOG_EXPANDER est activé.

Contrôle du processus

setPower(power) — allume (1) ou éteint (0) le chauffage.

setCurrentPower(value) — règle la tension du régulateur de puissance. Si le régulateur est piloté en puissance, l’argument définit la puissance. Disponible uniquement avec SAMOVAR_USE_POWER.

setBodyTemp(temp) — définit la température du cœur pendant la rectification. Dans les autres modes, la fonction affiche seulement un message dans la console et dans Blynk.

setMixer(value) — allume (1) ou éteint (0) l’agitateur.

openValve(value) — ouvre (1) ou ferme (0) la vanne d’arrivée d’eau.

setAlarm() — mode d’urgence : le contrôleur coupe le chauffage, ferme la vanne et arrête la pompe à eau.

setNextProgram() — passe à la ligne suivante du programme (équivalent du bouton de l’interface).

setPauseWithdrawal(value) — met en pause (1) ou reprend (0) le soutirage.

setCapacity(num) — change le récipient de soutirage en cours. Plage valide : 0…CAPACITY_NUM.

setLuaStatus(value) — définit le statut du mode Lua. Si celui-ci est occupé, la fonction lève l’erreur « Lua_status busy ».

setPumpPwm(pwm) — contrôle PWM de la sortie de la pompe à eau (0…1023). Disponible avec USE_WATER_PUMP.

setServoAngle(angle) — règle l’angle du servomoteur (0…SERVO_ANGLE). Disponible avec SERVO_PIN.

setTimer(num, sec) — règle le minuteur num (1…10) sur sec secondes. Il y a 10 minuteurs au total.

getTimer(num) — le temps restant sur le minuteur, en millisecondes. Si le minuteur n’est pas réglé ou est déjà écoulé, la fonction renvoie 0.

getState() — le statut numérique du contrôleur.

Variables du contrôleur

getNumVariable(name) et setNumVariable(name, value) — lecture et écriture des variables numériques. L’écriture n’est possible que pour les variables explicitement marquées comme modifiables (voir le tableau ci-dessous). Exemple : setNumVariable("TankTemp", 85) réglera la température du bouilleur à 85 °C. Sans comprendre la logique du Samovar, modifier des variables est risqué — vous pouvez casser les algorithmes.

getStrVariable(name) et setStrVariable(name, value) — la même chose pour les variables de type chaîne.

Les noms des variables accessibles depuis un script sont donnés dans le tableau de la section suivante.

Objets — stockage persistant

Les variables Lua ordinaires n’existent que pendant l’exécution du script et sont perdues au lancement suivant. Pour transmettre une valeur d’un lancement à l’autre, utilisez setObject et getObject :

setObject("name", value)     -- enregistrer
getObject("name")            -- lire (renvoie "" si absent)
getObject("name", "NUMERIC") -- lire comme nombre (renvoie 0 si absent)

Au maximum 32 clés (LUA_OBJECT_STORE_MAX_KEYS). Les valeurs sont conservées jusqu’au redémarrage du contrôleur.

Journal, débogage, HTTP

sendMsg(msg, level) — affiche un message. Avec level = -1 — vers le port COM et la console du navigateur (pour le débogage). Avec level = 0, 1, 2 — vers la console et vers Blynk.

http_request(url [, method, headers, body]) — une requête HTTP. Pratique pour l’intégration avec des services externes : envoi de notifications Telegram, journalisation, webhooks. Le délai d’attente est plus court que pour un téléchargement normal, et l’appel s’exécute sous un mutex partagé, de sorte que des appels simultanés depuis différents scripts n’entrent pas en conflit.

Périphériques I²C

check_I2C_device(address) — vérifie si un périphérique est présent sur le bus I²C à l’adresse indiquée. Renvoie 1 si le périphérique a répondu, sinon 0.

get_i2c_rele_state(relay) et set_i2c_rele_state(relay, state) — l’état et la commutation d’un relais I²C. Numéros valides : 1…4.

Module pas à pas

set_stepper_by_time(speed, direction, seconds) — fait tourner le moteur pas à pas à la vitesse indiquée (0…65535) et dans le sens indiqué (0 ou 1) pendant la durée donnée. Renvoie 1 si le démarrage a eu lieu.

set_stepper_target(speed, direction, target) — exécute le nombre de pas indiqué. Renvoie 1 si le démarrage a eu lieu.

get_stepper_status() — l’état actuel du module pas à pas.

set_mixer_pump_target(target) et get_mixer_pump_status() — commande de la pompe de l’agitateur (0 ou 1).

Pompe I²C

Disponible lorsque use_I2C_dev = 2 :

i2cpump_start(rate, ml)     -- démarrer la pompe à la vitesse et au volume indiqués
i2cpump_stop()              -- arrêter
i2cpump_get_speed()         -- vitesse actuelle
i2cpump_get_target_ml()     -- volume cible
i2cpump_get_remaining_ml()  -- volume restant à pomper
i2cpump_get_running()       -- 1 si en marche, sinon 0

Les valeurs incorrectes (NaN, Inf, ≤ 0) sont ignorées en silence, sans erreur.

Chien de garde des coroutines

Dans la version pour ESP32, la limite d’appels C Lua imbriqués est abaissée de 200 à 60 (LUAI_MAXCCALLS = 60), car sur la pile de 8 Ko de la tâche do_lua_script la limite d’origine est inatteignable. Si votre script utilise coroutine.create / wrap / resume, appelez impérativement armCoroutineWatchdog() dans init.lua : sinon une coroutine consommera toute la pile avant que la limite ne s’applique.

Variables

La liste ci-dessous présente les variables accessibles depuis un script. RO signifie lecture seule, RW signifie qu’elle peut être modifiée via setNumVariable.

Valeurs des capteurs (RO)

  • SteamTemp — la température du capteur de vapeur.
  • PipeTemp — la température du capteur de l’élément de colonne.
  • WaterTemp — la température du capteur d’eau.
  • TankTemp — la température du capteur du bouilleur.
  • ACPTemp — la température du capteur du TCA (tube d’évent atmosphérique).
  • pressure_value — la pression dans le système.
  • alcohol — le degré alcoolique calculé en temps réel.
  • alcohol_s — le degré alcoolique à l’état stabilisé.

État et statuts (RO)

  • PowerOn — 0/1, l’indicateur de chauffage allumé.
  • PauseOn — 0/1, l’indicateur de pause du soutirage.
  • pump_started — 0/1, la pompe à eau fonctionne.
  • valve_status — 0/1, la vanne d’eau.
  • water_pump_speed — la vitesse actuelle de la pompe.
  • program_Wait — 0/1, le programme est en pause.
  • SamSetup_Mode — le mode de fonctionnement du Samovar.
  • Samovar_Mode — le mode de processus en cours.
  • Samovar_CR_Mode — le mode en cours selon la classification interne.
  • target_power_volt — la tension cible du régulateur.
  • WFpulseCount, WFflowRate, WFtotalMilliLitres — valeurs du débitmètre (s’il est présent).

Les paramètres de la ligne de programme en cours (program_volume, program_speed, program_temp, program_power, program_time, program_capacity_num) et le récipient de soutirage en cours (capacity_num) sont eux aussi en lecture seule.

Paramètres modifiables (RW)

  • acceleration_temp — la température de l’élément chauffant d’accélération.
  • boil_temp — la température d’ébullition.
  • loop_lua_fl — 0/1, désactive ou active le lancement du script une fois par seconde.
  • SetScriptOff — 0/1, arrêt forcé des scripts.
  • show_lua_script — 0/1, affiche le corps du script et les valeurs des variables sur le port COM et dans la console (pour le débogage).
  • test_num_val — une variable numérique pour le débogage.
  • wp_count — le nombre d’impulsions du débitmètre (avec USE_WATER_PUMP).

Variables de type chaîne

  • SamovarStatus (RW) — le statut actuel affiché dans l’interface.
  • program_type (RO) — le type du programme en cours d’exécution.
  • test_str_val (RW) — une variable de type chaîne pour le débogage.
  • Msg (spéciale) — la lecture fait avancer le curseur dans l’anneau d’événements ; l’écriture se fait via setStrVariable.

Capteurs virtuels (SAMOVAR_LUA_SIMULATION)

Lorsque la simulation est activée, VirtualSteamTemp, VirtualPipeTemp, VirtualWaterTemp, VirtualTankTemp, VirtualACPTemp sont disponibles (toutes en RW). Elles servent à déboguer les scripts sans matériel.

Horloge (RO)

YY, MM, DD, HH, MI, SS — l’année, le mois, le jour, l’heure, la minute et la seconde actuels selon l’horloge RTC du contrôleur.

Exemples

setObject et getObject

n = 156
setObject("MyObject", n)
print(n)            -- 156
n = n + 5
print(n)            -- 161
n = getObject("MyObject")
print(n)            -- 156 (valeur enregistrée relue)

Envoi de la température du bouilleur vers Telegram

local function urlencode(url)
  if url == nil then return end
  url = url:gsub("\n", "\r\n")
  url = url:gsub("([^%w ])", function(c)
    return string.format("%%%02X", string.byte(c))
  end)
  url = url:gsub(" ", "+")
  return url
end

function SendTelegram(text)
  local token = "5177...:AAG0b...."
  local chat_id = "38806....."
  http_request("http://api.telegram.org/bot" .. token
    .. "/sendMessage?chat_id=" .. chat_id
    .. "&text=" .. urlencode(text))
end

local text = "Température actuelle du bouilleur = "
  .. getNumVariable("TankTemp")
SendTelegram(text)

Capteur de niveau analogique et pompe à eau

L’exemple lit un capteur de niveau analogique et allume la pompe lorsque le niveau se situe dans une plage donnée. L’état de la pompe est conservé entre les lancements via setObject.

start_pump = getObject("start_pump", "NUMERIC") + 0

sensor = analogRead()
if sensor >= 1000 and sensor <= 2000 and start_pump == 0 then
  setObject("start_pump", 1)
  digitalWrite(4, 1)
  print("Start pump")
elseif sensor == 0 then
  setObject("start_pump", 0)
  if start_pump == 1 then
    digitalWrite(4, 0)
    print("Finish pump")
  end
end

Sécurité et limitations

  • 10 minuteurs à la fois.
  • 32 clés dans le stockage d’objets (LUA_OBJECT_STORE_MAX_KEYS).
  • La limite d’appels C Lua imbriqués : 60 (LUAI_MAXCCALLS). Si vous utilisez coroutine.*, appelez impérativement armCoroutineWatchdog().
  • Broches pour pinMode : uniquement RELE_CHANNEL1…RELE_CHANNEL4 et LUA_PIN. La broche occupée par l’électrode de pH du fromage ne peut pas être utilisée — la fonction renverra une erreur.
  • N’appliquez pas plus de 3,3 V à analogRead().
  • setBodyTemp ne fonctionne qu’en mode rectification ; dans les autres modes, elle affiche un avertissement.
  • Lorsque setAlarm() est appelée, le contrôleur arrête le chauffage, ferme la vanne et éteint la pompe.
  • Les arguments numériques de i2cpump_start doivent être des nombres positifs finis ; NaN/Inf/≤0 sont ignorés en silence.

Ressources complémentaires

Laisser un commentaire