627 lines
21 KiB
Lua
627 lines
21 KiB
Lua
--------------------------------------------------------------------
|
|
-- drone.lua : programme principal V2.
|
|
-- Usage: drone demarrer
|
|
-- drone maj <url> mettre a jour depuis <url> (Forgejo raw)
|
|
-- Modes: off, sol, stationnement, vol, atterrissage.
|
|
--------------------------------------------------------------------
|
|
local FICHIERS = {
|
|
"drone.lua",
|
|
"lib/conf.lua", "lib/etat.lua", "lib/pid.lua", "lib/materiel.lua",
|
|
"lib/regulation.lua", "lib/calib.lua", "lib/ecran.lua",
|
|
"lib/journal.lua",
|
|
}
|
|
|
|
local args = { ... }
|
|
if args[1] == "maj" then
|
|
local base = args[2]
|
|
if not base then print("usage: drone maj <url_base>") return end
|
|
if base:sub(-1) ~= "/" then base = base .. "/" end
|
|
for _, fichier in ipairs(FICHIERS) do
|
|
write("maj " .. fichier .. " ... ")
|
|
local reponse, err = http.get(base .. fichier)
|
|
if not reponse then print("ECHEC: " .. tostring(err)) return end
|
|
local contenu = reponse.readAll()
|
|
reponse.close()
|
|
if fs.exists(fichier) then fs.delete(fichier) end
|
|
local f = fs.open(fichier, "w")
|
|
f.write(contenu)
|
|
f.close()
|
|
print("ok")
|
|
end
|
|
print("mise a jour terminee: relancer drone")
|
|
return
|
|
end
|
|
|
|
local function charger(chemin)
|
|
local f = assert(fs.open(chemin, "r"),
|
|
chemin .. " manquant: drone maj <url>")
|
|
local src = f.readAll()
|
|
f.close()
|
|
return assert(load(src, chemin))()
|
|
end
|
|
|
|
local journal = charger("lib/journal.lua")
|
|
local conf = charger("lib/conf.lua").charger(journal)
|
|
local Etat = charger("lib/etat.lua")
|
|
local etat = Etat.charger(journal)
|
|
local Pid = charger("lib/pid.lua")
|
|
local materiel = charger("lib/materiel.lua")
|
|
.initialiser(conf, etat, journal)
|
|
|
|
--------------------------------------------------------------------
|
|
-- PARAMETRES EDITABLES (page PARAM); surcharges persistees dans
|
|
-- drone.etat, elles PRIMENT sur drone.conf sans l'ecraser
|
|
--------------------------------------------------------------------
|
|
local PARAMS = {
|
|
{ chemin = "ANGLE_MAX", label = "angle max (deg)", pas = 0.25,
|
|
mini = 0.25 },
|
|
{ chemin = "DIST_SOL", label = "distance sol", pas = 0.2,
|
|
mini = 0.4 },
|
|
{ chemin = "VITESSE_ATTERRISSAGE", label = "v atterrissage (b/s)",
|
|
pas = 0.25, mini = 0.25 },
|
|
{ chemin = "V_MONTEE_MAX", label = "v montee max (b/s)",
|
|
pas = 0.5, mini = 0.5 },
|
|
{ chemin = "V_DESCENTE_MAX", label = "v descente max (b/s)",
|
|
pas = 0.5, mini = 0.5 },
|
|
{ chemin = "RAMPE", label = "rampe consigne (b/s)", pas = 0.5,
|
|
mini = 0.5 },
|
|
{ chemin = "ASSIETTE_PLAFOND", label = "autorite assiette",
|
|
pas = 0.05, mini = 0.05, maxi = 1 },
|
|
{ chemin = "PID.alt.kp", label = "altitude kp", pas = 0.1,
|
|
mini = 0.1 },
|
|
{ chemin = "PID.vitesse.kp", label = "vitesse kp", pas = 0.5,
|
|
mini = 0 },
|
|
{ chemin = "PID.vitesse.ki", label = "vitesse ki", pas = 0.5,
|
|
mini = 0 },
|
|
{ chemin = "PID.vitesse.kd", label = "vitesse kd", pas = 0.25,
|
|
mini = 0 },
|
|
{ chemin = "PID.tangage.kp", label = "tangage kp", pas = 0.25,
|
|
mini = 0 },
|
|
{ chemin = "PID.tangage.ki", label = "tangage ki", pas = 0.05,
|
|
mini = 0 },
|
|
{ chemin = "PID.tangage.kd", label = "tangage kd", pas = 0.25,
|
|
mini = 0 },
|
|
{ chemin = "PID.roulis.kp", label = "roulis kp", pas = 0.25,
|
|
mini = 0 },
|
|
{ chemin = "PID.roulis.ki", label = "roulis ki", pas = 0.05,
|
|
mini = 0 },
|
|
{ chemin = "PID.roulis.kd", label = "roulis kd", pas = 0.25,
|
|
mini = 0 },
|
|
{ chemin = "MOTEUR.MARGE", label = "marge moteur", pas = 0.05,
|
|
mini = 0.05, maxi = 0.5 },
|
|
{ chemin = "REGUL.DELTA_MAX", label = "autorite vitesse",
|
|
pas = 0.05, mini = 0.2, maxi = 1 },
|
|
{ chemin = "REGUL.PENTE", label = "pente base (x sust/s)",
|
|
pas = 0.25, mini = 0.5, maxi = 6 },
|
|
}
|
|
|
|
local function lireChemin(chemin)
|
|
local noeud = conf
|
|
for partie in chemin:gmatch("[^%.]+") do
|
|
if type(noeud) ~= "table" then return nil end
|
|
noeud = noeud[partie]
|
|
end
|
|
return noeud
|
|
end
|
|
|
|
local function ecrireChemin(chemin, valeur)
|
|
local noeud, parent, cle = conf, nil, nil
|
|
for partie in chemin:gmatch("[^%.]+") do
|
|
parent, cle = noeud, partie
|
|
noeud = noeud[partie]
|
|
end
|
|
parent[cle] = valeur
|
|
end
|
|
|
|
etat.surcharges = etat.surcharges or {}
|
|
for chemin, valeur in pairs(etat.surcharges) do
|
|
ecrireChemin(chemin, valeur)
|
|
end
|
|
|
|
local regulation = charger("lib/regulation.lua")
|
|
.nouveau(conf, etat, materiel, Pid, journal)
|
|
local Calib = charger("lib/calib.lua")
|
|
local ecran = charger("lib/ecran.lua")
|
|
.nouveau(conf, materiel, journal)
|
|
|
|
-- coherence des versions de modules (desynchronisation de maj)
|
|
local function exigerInterface(objet, fichier, fonctions)
|
|
local manquantes = {}
|
|
for _, nom in ipairs(fonctions) do
|
|
if type(objet[nom]) ~= "function" then
|
|
table.insert(manquantes, nom)
|
|
end
|
|
end
|
|
if #manquantes > 0 then
|
|
error(("%s obsolete (manque: %s): resynchroniser avec "
|
|
.. "'drone maj <url>'"):format(fichier,
|
|
table.concat(manquantes, ", ")), 0)
|
|
end
|
|
end
|
|
exigerInterface(materiel, "lib/materiel.lua", {
|
|
"lireAssiette", "vitesseGlobale", "lireJoystick", "reglerMoteur",
|
|
"rafraichirAffectations", "relaisValides",
|
|
})
|
|
exigerInterface(regulation, "lib/regulation.lua", {
|
|
"reguler", "plaquer", "rpmHover", "reglerInjection",
|
|
"gainsModifies", "vitesseVerticale", "gelerBoite",
|
|
})
|
|
exigerInterface(ecran, "lib/ecran.lua", {
|
|
"rafraichirMoniteur", "choisirRole", "message",
|
|
})
|
|
|
|
--------------------------------------------------------------------
|
|
-- ETAT DE VOL
|
|
--------------------------------------------------------------------
|
|
local mode = etat.mode or "off"
|
|
local consigneY = etat.consigneY or materiel.lireAltitude()
|
|
local enCalibration = false
|
|
local calibEnCours, calibProgres, calibTexte = nil, nil, nil
|
|
local rscViolet = nil
|
|
local carburantPct, autonomieMin = nil, nil
|
|
local alerteMoteurA = 0
|
|
local reidentificationApres = 0
|
|
local DT = 0.1
|
|
local DT_REEL = 0.1
|
|
|
|
local function sauverEtat()
|
|
etat.mode = mode
|
|
etat.consigneY = consigneY
|
|
Etat.sauver(etat)
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- VERROUS DE MODES (calibrations requises)
|
|
--------------------------------------------------------------------
|
|
local function verrouDe(m)
|
|
if m == "off" or m == "sol" then return nil end
|
|
if not etat.gimbal then return "calib gimbal requise" end
|
|
if #materiel.helicesManquantes() > 0 then
|
|
return "calib rsc requise"
|
|
end
|
|
if m == "vol" and not etat.calibAltitude then
|
|
return "calib altitude requise"
|
|
end
|
|
if (m == "vol" or m == "atterrissage" or m == "stationnement")
|
|
and not materiel.relaisValides() then
|
|
return "relays renumerotes: passer en mode sol (reident. auto)"
|
|
end
|
|
if m == "stationnement" then
|
|
if not materiel.auSol() then return "pas au sol" end
|
|
local t, r = materiel.lireAssiette()
|
|
if math.max(math.abs(t), math.abs(r)) > conf.ANGLE_MAX then
|
|
return "pas horizontal"
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
local function verrous()
|
|
local v = {}
|
|
for _, m in ipairs({ "off", "sol", "stationnement", "vol",
|
|
"atterrissage" }) do
|
|
v[m] = verrouDe(m)
|
|
end
|
|
return v
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- MACHINE D'ETATS
|
|
--------------------------------------------------------------------
|
|
local function changerMode(nouveau, raison)
|
|
if nouveau == mode then return end
|
|
local verrou = verrouDe(nouveau)
|
|
if verrou then
|
|
ecran.message(nouveau .. ": " .. verrou)
|
|
journal.info(("mode %s refuse: %s"):format(nouveau, verrou))
|
|
return
|
|
end
|
|
journal.info(("mode: %s (%s)"):format(nouveau, raison or "?"))
|
|
local etaitAuSol = mode == "off" or mode == "sol"
|
|
or mode == "stationnement"
|
|
mode = nouveau
|
|
regulation.raz()
|
|
if etaitAuSol and (mode == "vol" or mode == "atterrissage") then
|
|
regulation.razAdaptation()
|
|
end
|
|
if mode == "vol" then
|
|
consigneY = materiel.lireAltitude()
|
|
elseif mode == "atterrissage" then
|
|
consigneY = materiel.lireAltitude()
|
|
elseif mode == "off" then
|
|
materiel.toutArreter()
|
|
materiel.reglerMoteur(0)
|
|
else
|
|
materiel.toutArreter()
|
|
end
|
|
if mode ~= "off" and etat.modeMoteur == "onoff" then
|
|
materiel.reglerMoteur(15)
|
|
end
|
|
-- reassertion du signal des boites (rapport fixe, jamais change
|
|
-- en vol; on s'assure qu'il est bien applique avant de voler)
|
|
materiel.appliquerBoite()
|
|
sauverEtat()
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- SURVEILLANCE DES BOITES (vol): la vitesse reelle des helices
|
|
-- (speedometers) doit suivre commande * rapport; un ecart > 25%
|
|
-- persistant 2 s declenche une alerte (cablage / signal perdu)
|
|
--------------------------------------------------------------------
|
|
local ecartBoiteDepuis = nil
|
|
local alerteBoiteA = 0
|
|
local function surveillerBoites()
|
|
if not (etat.boite and etat.speedoParRole) then return end
|
|
local rapport = materiel.rapportBoite()
|
|
local nb, ecarts = 0, 0
|
|
for _, role in ipairs({ "lb", "rb", "lf", "rf" }) do
|
|
local commande = materiel.rpm[role] and materiel.rpm[role].v
|
|
local reel = materiel.lireVitesseHelice(role)
|
|
if commande and reel and math.abs(commande) > 8 then
|
|
local attendu = math.abs(commande) * rapport
|
|
if math.abs(math.abs(reel) - attendu) > attendu * 0.25 then
|
|
ecarts = ecarts + 1
|
|
end
|
|
nb = nb + 1
|
|
end
|
|
end
|
|
if nb > 0 and ecarts >= math.max(1, nb - 1) then
|
|
ecartBoiteDepuis = ecartBoiteDepuis or os.clock()
|
|
if os.clock() - ecartBoiteDepuis > 2
|
|
and os.clock() - alerteBoiteA > 10 then
|
|
alerteBoiteA = os.clock()
|
|
journal.alerte("boites de vitesse incoherentes (vitesse "
|
|
.. "helices != commande * rapport): verifier le signal")
|
|
ecran.message("BOITES INCOHERENTES", 6)
|
|
materiel.appliquerBoite() -- reassertion du signal
|
|
end
|
|
else
|
|
ecartBoiteDepuis = nil
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- UN PAS DE CONTROLE
|
|
--------------------------------------------------------------------
|
|
local function pasControle()
|
|
if mode ~= "off" and not materiel.moteurTourne()
|
|
and os.clock() - alerteMoteurA > 5 then
|
|
alerteMoteurA = os.clock()
|
|
journal.erreur("le moteur ne tourne pas alors qu'il le devrait")
|
|
ecran.message("MOTEUR ARRETE", 5)
|
|
end
|
|
|
|
if mode == "off" then
|
|
-- tout est deja coupe
|
|
elseif mode == "sol" then
|
|
-- moteur allume, RSC a zero; reidentification AUTOMATIQUE des
|
|
-- relays si les noms stockes ne correspondent plus au reseau
|
|
if not materiel.relaisValides()
|
|
and os.clock() > reidentificationApres then
|
|
reidentificationApres = os.clock() + 30
|
|
journal.alerte("relays renumerotes: reidentification "
|
|
.. "automatique en cours")
|
|
ecran.message("REIDENTIFICATION RELAYS", 5)
|
|
pcall(Calib.reidentifierRelais, conf, etat, materiel, journal,
|
|
Etat)
|
|
end
|
|
elseif mode == "stationnement" then
|
|
-- plaquage; sortie AUTO vers vol si les conditions sont perdues
|
|
if not materiel.auSol() then
|
|
changerMode("vol", "conditions de stationnement perdues")
|
|
return
|
|
end
|
|
local t, r = materiel.lireAssiette()
|
|
if math.max(math.abs(t), math.abs(r)) > conf.ANGLE_MAX * 2 then
|
|
changerMode("vol", "assiette perdue au stationnement")
|
|
return
|
|
end
|
|
regulation.plaquer()
|
|
elseif mode == "vol" then
|
|
local avance, virage = materiel.lireJoystick()
|
|
regulation.reguler(consigneY, avance, virage, DT_REEL)
|
|
surveillerBoites()
|
|
elseif mode == "atterrissage" then
|
|
consigneY = consigneY - conf.VITESSE_ATTERRISSAGE * DT_REEL
|
|
regulation.reguler(consigneY, 0, 0, DT_REEL)
|
|
if materiel.auSol() then
|
|
changerMode("stationnement", "sol atteint")
|
|
end
|
|
end
|
|
|
|
-- persistance du rapport de boite (bascules automatiques en vol)
|
|
if regulation.boiteModifiee and regulation.boiteModifiee() then
|
|
Etat.sauver(etat)
|
|
end
|
|
|
|
-- persistance des reductions du superviseur d'oscillation
|
|
if regulation.gainsModifies() then
|
|
for _, axe in ipairs({ "vitesse", "tangage", "roulis" }) do
|
|
local g = conf.PID[axe]
|
|
etat.surcharges["PID." .. axe .. ".kp"] = g.kp
|
|
etat.surcharges["PID." .. axe .. ".ki"] = g.ki
|
|
etat.surcharges["PID." .. axe .. ".kd"] = g.kd
|
|
end
|
|
Etat.sauver(etat)
|
|
end
|
|
end
|
|
|
|
local function tacheControle()
|
|
local precedent = os.clock()
|
|
while true do
|
|
if not enCalibration then
|
|
-- dt REEL (le pas peut deriver du DT nominal): borne 0.05-0.3
|
|
local maintenant = os.clock()
|
|
DT_REEL = math.max(0.05, math.min(0.3, maintenant - precedent))
|
|
precedent = maintenant
|
|
local ok, err = pcall(pasControle)
|
|
if not ok then journal.erreur("controle: " .. tostring(err)) end
|
|
else
|
|
precedent = os.clock()
|
|
end
|
|
sleep(DT)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- CARBURANT (autonomie apprise par EMA, mode off exclu)
|
|
--------------------------------------------------------------------
|
|
local function tacheCarburant()
|
|
local quantitePrec, tPrec, conso = nil, nil, nil
|
|
local alerte = false
|
|
while true do
|
|
local ok, pct, quantite = pcall(materiel.lireCarburant)
|
|
if ok and pct then
|
|
carburantPct = pct
|
|
local t = os.clock()
|
|
if quantitePrec and t > tPrec and mode ~= "off" then
|
|
local instantanee = (quantitePrec - quantite) / (t - tPrec)
|
|
if instantanee >= 0 then
|
|
conso = conso
|
|
and (conso + conf.CARBURANT.LISSAGE
|
|
* (instantanee - conso))
|
|
or instantanee
|
|
end
|
|
end
|
|
quantitePrec, tPrec = quantite, t
|
|
autonomieMin = (conso and conso > 0.001)
|
|
and (quantite / conso / 60) or nil
|
|
if pct < conf.CARBURANT.SEUIL_ALERTE and not alerte then
|
|
alerte = true
|
|
journal.alerte("carburant sous "
|
|
.. math.floor(conf.CARBURANT.SEUIL_ALERTE * 100) .. "%")
|
|
ecran.message("CARBURANT BAS", 10)
|
|
elseif pct > conf.CARBURANT.SEUIL_ALERTE + 0.05 then
|
|
alerte = false
|
|
end
|
|
end
|
|
sleep(conf.CARBURANT.PERIODE)
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- CALIBRATIONS
|
|
--------------------------------------------------------------------
|
|
local rafraichirCalib = nil -- affecte apres contexteEcran
|
|
|
|
local ui = {
|
|
inviter = function(contenu)
|
|
ecran.message(contenu, 3600)
|
|
calibTexte = contenu
|
|
pcall(ecran.rafraichirConduite,
|
|
{ mode = mode, consigneY = consigneY })
|
|
if rafraichirCalib then rafraichirCalib() end
|
|
journal.info("[calib] " .. contenu)
|
|
end,
|
|
progres = function(pct, contenu)
|
|
if pct then calibProgres = pct end
|
|
if contenu then calibTexte = contenu end
|
|
if rafraichirCalib then rafraichirCalib() end
|
|
end,
|
|
rscViolet = function(role) rscViolet = role end,
|
|
attendreToucher = ecran.attendreToucher,
|
|
choisirRole = ecran.choisirRole,
|
|
}
|
|
|
|
local function purgerEvenements()
|
|
os.queueEvent("purge_evenements")
|
|
while true do
|
|
if os.pullEvent() == "purge_evenements" then return end
|
|
end
|
|
end
|
|
|
|
local function lancerCalibration(quoi)
|
|
enCalibration = true
|
|
calibEnCours = quoi
|
|
calibProgres, calibTexte = 0, quoi
|
|
ecran.reglerPage("calib")
|
|
-- la boite ne change JAMAIS de rapport pendant une calibration
|
|
regulation.gelerBoite(true)
|
|
local ok, err = pcall(function()
|
|
if quoi == "inclinaison" then
|
|
if mode ~= "vol" then
|
|
journal.alerte("calib inclinaison: passer en mode vol "
|
|
.. "(stationnaire)")
|
|
ecran.message("passer en mode vol")
|
|
return
|
|
end
|
|
Calib.inclinaison(conf, etat, materiel, regulation, journal,
|
|
Etat, ui)
|
|
elseif mode ~= "sol" and mode ~= "stationnement" then
|
|
journal.alerte("calib " .. quoi .. ": passer en mode sol")
|
|
ecran.message("passer en mode sol")
|
|
elseif quoi == "gimbal" then
|
|
Calib.gimbal(conf, etat, materiel, journal, Etat, ui)
|
|
elseif quoi == "joystick" then
|
|
Calib.joystick(conf, etat, materiel, journal, Etat, ui)
|
|
elseif quoi == "rsc" then
|
|
Calib.rsc(conf, etat, materiel, journal, Etat, ui)
|
|
elseif quoi == "boite" then
|
|
Calib.boite(conf, etat, materiel, journal, Etat, ui)
|
|
elseif quoi == "altitude" then
|
|
Calib.altitude(conf, etat, materiel, regulation, journal,
|
|
Etat, ui)
|
|
end
|
|
end)
|
|
if not ok then journal.erreur("calibration: " .. tostring(err)) end
|
|
regulation.gelerBoite(false)
|
|
ecran.message("", 0)
|
|
calibEnCours, rscViolet = nil, nil
|
|
enCalibration = false
|
|
materiel.toutArreter()
|
|
if mode ~= "off" and etat.modeMoteur == "onoff" then
|
|
materiel.reglerMoteur(15)
|
|
end
|
|
purgerEvenements()
|
|
end
|
|
|
|
local function calibStatuts()
|
|
local faits = {
|
|
gimbal = etat.gimbal ~= nil,
|
|
joystick = etat.joystick ~= nil,
|
|
rsc = #materiel.helicesManquantes() == 0,
|
|
boite = etat.boite ~= nil,
|
|
altitude = etat.calibAltitude == true,
|
|
inclinaison = etat.calibInclinaison == true,
|
|
}
|
|
local statuts = {}
|
|
for nom, fait in pairs(faits) do
|
|
if calibEnCours == nom then statuts[nom] = "encours"
|
|
elseif fait then statuts[nom] = "fait" end
|
|
end
|
|
return statuts
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- ECRANS
|
|
--------------------------------------------------------------------
|
|
local function listeParams()
|
|
local liste = {}
|
|
for _, p in ipairs(PARAMS) do
|
|
table.insert(liste,
|
|
{ label = p.label, valeur = lireChemin(p.chemin) })
|
|
end
|
|
return liste
|
|
end
|
|
|
|
local function ajusterParam(idx, sens)
|
|
local p = PARAMS[idx]
|
|
if not p then return end
|
|
local valeur = (lireChemin(p.chemin) or 0) + sens * p.pas
|
|
if p.mini and valeur < p.mini then valeur = p.mini end
|
|
if p.maxi and valeur > p.maxi then valeur = p.maxi end
|
|
valeur = math.floor(valeur * 100 + 0.5) / 100
|
|
ecrireChemin(p.chemin, valeur)
|
|
etat.surcharges[p.chemin] = valeur
|
|
Etat.sauver(etat)
|
|
journal.info(("param %s = %s"):format(p.chemin, tostring(valeur)))
|
|
end
|
|
|
|
local function contexteEcran()
|
|
return {
|
|
mode = mode,
|
|
consigneY = consigneY,
|
|
moteurOk = mode == "off" or materiel.moteurTourne(),
|
|
carburantPct = carburantPct,
|
|
minutes = autonomieMin,
|
|
modeMoteur = etat.modeMoteur,
|
|
verrous = verrous(),
|
|
calibStatuts = calibStatuts(),
|
|
calibProgres = calibProgres,
|
|
calibTexte = calibTexte,
|
|
rscViolet = rscViolet,
|
|
params = listeParams(),
|
|
rapportBoite = etat.boite
|
|
and (tostring(math.floor(etat.boite.rapport * 16)) .. "/16")
|
|
or nil,
|
|
}
|
|
end
|
|
|
|
rafraichirCalib = function()
|
|
pcall(ecran.rafraichirMoniteur, contexteEcran())
|
|
end
|
|
|
|
local function tacheEcran()
|
|
local prochainDessin = 0
|
|
local redessiner = false
|
|
while true do
|
|
if os.clock() >= prochainDessin or redessiner then
|
|
redessiner = false
|
|
pcall(ecran.rafraichirConduite,
|
|
{ mode = mode, consigneY = consigneY })
|
|
pcall(ecran.rafraichirCarburant, carburantPct)
|
|
pcall(ecran.rafraichirMoniteur, contexteEcran())
|
|
prochainDessin = os.clock() + 1.0
|
|
end
|
|
local minuteur = os.startTimer(0.25)
|
|
local ev, a, b, c = os.pullEvent()
|
|
if ev == "monitor_touch" and not enCalibration then
|
|
local action = ecran.traiterToucher(b, c)
|
|
if action then
|
|
redessiner = true
|
|
if action.type == "mode" then
|
|
if action.verrou then
|
|
ecran.message(action.valeur .. ": " .. action.verrou)
|
|
else
|
|
changerMode(action.valeur, "moniteur")
|
|
end
|
|
elseif action.type == "delta" then
|
|
consigneY = consigneY + action.valeur
|
|
sauverEtat()
|
|
elseif action.type == "modemoteur" then
|
|
etat.modeMoteur = action.valeur
|
|
Etat.sauver(etat)
|
|
if mode ~= "off" and etat.modeMoteur == "onoff" then
|
|
materiel.reglerMoteur(15)
|
|
end
|
|
journal.info("regime moteur: " .. action.valeur)
|
|
elseif action.type == "calib" then
|
|
lancerCalibration(action.valeur)
|
|
end
|
|
end
|
|
end
|
|
if ev ~= "timer" or a ~= minuteur then
|
|
os.cancelTimer(minuteur)
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- CLAVIER (minimal)
|
|
--------------------------------------------------------------------
|
|
local function tacheClavier()
|
|
while true do
|
|
write("> ")
|
|
local ligne = read()
|
|
local mots = {}
|
|
for mot in ligne:gmatch("%S+") do table.insert(mots, mot) end
|
|
if mots[1] == "mode" and mots[2] then
|
|
changerMode(mots[2], "clavier")
|
|
elseif mots[1] == "consigne" and tonumber(mots[2]) then
|
|
consigneY = tonumber(mots[2])
|
|
sauverEtat()
|
|
else
|
|
print("mode <off|sol|stationnement|vol|atterrissage> | "
|
|
.. "consigne <y>")
|
|
end
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------------------
|
|
-- DEMARRAGE
|
|
--------------------------------------------------------------------
|
|
journal.info(("drone V2: demarrage en mode %s (consigne %.0f)")
|
|
:format(mode, consigneY))
|
|
if mode == "off" then
|
|
materiel.toutArreter()
|
|
materiel.reglerMoteur(0)
|
|
else
|
|
materiel.toutArreter()
|
|
if etat.modeMoteur == "onoff" then materiel.reglerMoteur(15) end
|
|
if mode == "vol" or mode == "atterrissage" then
|
|
consigneY = materiel.lireAltitude()
|
|
end
|
|
end
|
|
|
|
parallel.waitForAny(tacheControle, tacheCarburant, tacheEcran,
|
|
tacheClavier)
|