Opentx 2.1 DLG telemetry LUA-script (Taranis)

Allen,

Zonder enig verstand van LUA coding (...) heb ik een project overgenomen van RC-settings.com (met medeweten en goedkeuring van de originele eigenaar).

Het betreft een script voor de Taranis dat als telemetry pagina de hoogte plot over de tijd. Erg leuk om te kijken en te oefenen met zwevers en met name voor DLG's en het oefenen van werpen en identificeren van fouten in de techniek en ontdekken van thermiek.
Nu kan er vast heel veel verbeterd worden aan het scrip (al vind ik de simpelheid wel erg leuk) en ik vroeg me af of er mensen "in de zaal" zijn die eens met me mee willen kijken.

Ik heb een github pagina geopend (mijn eerste...)
https://github.com/Red-Devil74/DLG-F3K-script

1 van de dingen die ik zou willen bereiken is dat dit script wordt omgezet naar een OpenTX 2.2 Widget,... Ook hier is alle hulp welkom!

Ik hoop dat er iemand kan aanhaken en dat ik zo ook iets kan leren over Github!

grt,
Arthur
 
Bekijk mijn Graph widget eens als voorbeeld. Zit al een hele hoop in wat je kan gebruiken :)

Grote probleem wat ik zo zie is dat alle variabelen local zijn in de lua. Die werken voor alle widget instanties dan gelijk. Ik plaats alle data binnen de context van de widget. Bij meerdere dezelfde widgets behouden ze allemaal hun eigen set data.
 
@Tadango, ik ben bezig om stukje bij beetje de code om te zetten tot widget, maar omdat ik er geen snars verstand van heb zijn er een aantal zaken waar ik niet verder me kom.
Ik heb me ingelezen in "Local Variables" and Local Functions. Dit heb ik aangepast naar Global (en ik snap ook een beetje waarom...).
Nu zijn er twee variabelen die er voor zorgen dat het script niet in de Horus simulator wordt herkend als Widget (en dus vastloopt).
Code:
alt_id = getFieldInfo("Alt").id
a1_id  = getFieldInfo("RxBt").id
In de simulator heb ik allebei de sensoren herkent, maar toch werkt het niet. I heb ze in de code nu even er uit "gecomment" (regel 42 en 45) en dan loopt de code wel door...

Tweede vraag die ik heb is over de volgende code:
Code:
lcd.drawLine
Volgens https://opentx.gitbooks.io/opentx-lua-reference-guide/content/lcd/drawLine.html kan je patterns and flags toevoegen. Ik heb het idee dat bij pattern SOLID de code vast loopt (error number expected, got nil in de debug window van de simulator). Hoe kom ik er nu achter welke Patterns en welke flags er zijn en welke ik kan gebruiken?
DOTTED lijkt wel te werken. Ik neem ook aan dat de flags de lijnkleuren zijn?

Alle hulp wordt gewaardeerd!
https://github.com/Red-Devil74/DLG-F3K-script/blob/Red-Devil74-patch-1/Telem1-2.lua
 
Bij een widget zou ik geen variabelen in de widget opslaan (local / global) want dat is een probleem als je meer dan 1 x je widget toevoegt. Goed idee om dat af te leren vanaf het begin. Plaats alles op de context om het te scheiden per widget.

Wat betreft de functies is er van alles veranderd en is de documentatie niet meer bruikbaar. De beste bron voor de mogelijkheden is de code https://github.com/opentx/opentx/tree/next

getFieldInfo werkt maar als je geen sensor hebt met die naam krijg je nil terug. Dat moet je controleren. Je probeert nu altijd .id op te halen maar dat kan alleen als de sensor gevonden wordt.

Qua flags moet je hier eens zoeken: https://github.com/opentx/opentx/blob/next/radio/src/lua/api_general.cpp SOLID zou moeten werken. Komt die nil error niet van de getFieldInfo fout? Je kan ook een color flag meegeven waarbij je de CUSTOM_COLOR flag (en anderen) kan zetten via lcd.setColor
 
Wat betreft de functies is er van alles veranderd en is de documentatie niet meer bruikbaar. De beste bron voor de mogelijkheden is de code https://github.com/opentx/opentx/tree/next
https://github.com/opentx/opentx/tree/next
Wow! dit is goud waard! hier ga ik een paar dagen op broeden!
getFieldInfo werkt maar als je geen sensor hebt met die naam krijg je nil terug. Dat moet je controleren. Je probeert nu altijd .id op te halen maar dat kan alleen als de sensor gevonden wordt.
Heb je hints hoe dit te controleren?

Komt die nil error niet van de getFieldInfo fout?
Ga ik uitzoeken!
Je kan ook een color flag meegeven waarbij je de CUSTOM_COLOR flag (en anderen) kan zetten via lcd.setColor
Ga ik ook uitzoeken!

Dank voor je info! hier heb ik wel een paar dagen werk aan om te verwerken!

grt,
Arthur
 
--Get field info value
value = getFieldInfo('Alt')

--Get .id from result table only if value is not equal to nil
if value ~= nil then
alt_id = getFieldInfo("Alt").id
end
 
Of de betere versie:

--Get field info value
value = getFieldInfo('Alt')

--Get .id from result table only if value is not equal to nil
if value ~= nil then
alt_id = value.id
end



was nog vroeg vanochtend :)
 
Ik kan wel wat hulp gebruiken met mn scriptje.
Ik ben al best wel ver (vind ik...), maar de data waar het echt om gaat krijg ik niet op het scherm. Mijn script wil maar niet de de data van de "Alt" sensor uitlezen.
Ik heb een tweede scriptje " geschreven" om de controleren wat de ID van de Hoogte sensor is.
Code:
function maincode(context)
    fieldinfo = getFieldInfo("Alt")
    lcd.drawText(50,55,"getFieldInfo() example",0+INVERS)
    if fieldinfo then
        lcd.drawText(50,75,"id: ", 0)
        lcd.drawText(100,75,fieldinfo['id'],0)
        lcd.drawText(50,95,"name: ", 0)
        lcd.drawText(100,95,fieldinfo['name'],0)
        lcd.drawText(50,115,"desc: ", 0)
        lcd.drawText(100,115,fieldinfo['desc'],0)
        else
        lcd.drawText(50,75,"Requested field not available!",SMLSIZE+INVERS)   
    end

Dit geeft me in de simulator de volgende info en ID = 258
upload_2016-11-25_22-49-1.png


Ik vind dit raar, want het sensor overzicht laat een ID van 1 zien:
upload_2016-11-25_22-51-13.png


Binnen het zelfde model in de sim heb ik in de code die ik aan het ontwikkelen ben de volgende code:
Code:
value = getFieldInfo("Alt")            -- Get field info value
    if value ~= nil then
    vario = value.id                 -- Get .id from field index only if value is not equal to nil
    end

Nu loopt de code vast in de simulator met de melding:
Error in widget Test refresh() function: /WIDGETS/TST/main.lua:142: bad argument #1 to 'getValue' (string expected, got nil)

Regel 142 is de regel waar voor het eerst de waarde van de Alt sensor wordt aangeroepen.
Code:
    nowAlt = getValue(vario)

Het rare is dat wanneer ik de variabele in het begin aanpas naar:
Code:
value = getFieldInfo("Alt")            -- Get field info value
    if value ~= nil then
    vario = value.id                 -- Get .id from field index only if value is not equal to nil
    else
    vario=258       --Unable to get this to work. temp hardcode current ID in.... fix later
    end
Ofwel gewoon de ID vast in coderen, dan werkt het wel.

Nu is dus de vraag waarom het opzoeken van de variablen in het ene script wel werkt en in het andere niet?
Overigens heb ik de code in Github staan:
https://github.com/Red-Devil74/DLG-F3K-script/edit/Change-to-Opentx-Widget/Telem1-2.lua

Alle hulp is welkom!
grt,
Arthur
 
Gek, werkt hier zoals verwacht in de simulator:

local options = {
}

function create(zone, options)
local context = { zone=zone }
return context
end

function refresh(context)
x = context.zone.x + 5
y = context.zone.y + 5

value = getFieldInfo("Alt")

if value == nil then
lcd.drawText(x, y, "No Alt", TEXT_COLOR)
else
lcd.drawText(x, y, "Alt id: " .. value.id , TEXT_COLOR)
end
end

return { name="Tst", options=options, create=create, refresh=refresh }


Geeft mooi ID 249 terug. Staat als ID 1 in de lijst.... (0100 1)
 
Als ik de ID's in het telemetry scherm aanpas veranderd 249 niet. Pas ik de naam aan wordt hij niet gevonden.
 
Gek, werkt hier zoals verwacht in de simulator:

local options = {
}

function create(zone, options)
local context = { zone=zone }
return context
end

function refresh(context)
x = context.zone.x + 5
y = context.zone.y + 5

value = getFieldInfo("Alt")

if value == nil then
lcd.drawText(x, y, "No Alt", TEXT_COLOR)
else
lcd.drawText(x, y, "Alt id: " .. value.id , TEXT_COLOR)
end
end

return { name="Tst", options=options, create=create, refresh=refresh }


Geeft mooi ID 249 terug. Staat als ID 1 in de lijst.... (0100 1)
Zoals ik in bovenstaande schreef, heb ook ik een soort test scriptje geschreven (gejat van internet...) en die doet het inderdaad wel. Ik heb dus het idee dat er ergens een typefout o.i.d inzit. Gister avond heb ik de code herschreven met als voorbeeld hoe jij de value gelijk uit de sensor haalt (in je Graph widget) en dus niet eerst de ID probeert te vinden. Dit gaat veel beter...(goede raad is duur...)
 
@Tadango: Op dit moment probeer ik wat programmeren te leren met de methode: "Het is altijd Feest, met Copy & Paste", maar dit werk niet altijd.
Kan jij mischien in Jip en Janneke taal uitleggen waarom je bij functies Context tussen de haakjes zet? Wat is hiervan de functie of waar kan ik daar wat info over vinden?
Tevens gebruik jij "Zone". Ik vermoed dat dit te maken heeft met de dimensies van de widget, e.e.a. afhakelijk van welke screen layout je gebruikt, maar eigenlijk heb ik geen flauw idee. Zou jij hier iets meer over kunnen vertellen?

grt,
Arthur
 
Eens kijken kijken of ik dat op papier krijg :)

Wanneer je in code een functie (methode) aan roept dan kan je argumenten (parameters) mee geven. De functie refresh bv wordt aangeroepen vanuit OpenTX en het argument context wordt meegegeven. De parser (applicatie die de code leest) moet jouw text analyseren om te begrijpen wat je bedoeld. Als je begint met function weet hij dat je begint met een functie. Hij verwacht dan de naam van de functie en vervolgens tussen () de argumenten gescheiden door een komma. Dat is de afspraak (syntax) in Lua (en veel andere talen). Wanneer je een functie wil gebruiken in code geef je de naam op van de functie en dan tussen () de argumenten die je mee wil geven naar de functie. Het formaat van naam(..) wordt herkend door de parser als het aanroepen van een functie.

Bij de functie create krijg je van OpenTX een zone parameter mee. Deze zone bevat informatie over de plek waar je widget staat op het scherm. Dit is onder andere de x / y positie en de hoogte en breedte. Ik sla deze zone op in de context die ik maak in de create functie. Deze context geef ik terug aan OpenTX via het return statement. OpenTX geeft deze context weer terug bij het aanroepen van refresh edg. De context is als het ware een papiertje waar je alles op zet om te onthouden. Als je 2 dezelfde widgets hebt heb je 2 versies van het papiertje. Door alleen gebruik te maken van de informatie op het papiertje weet je wat je aan het doen bent en gebruik je geen gegevens door elkaar. Je weet anders niet wat je moet doen voor welke widget. Je weet niet eens dat er meerdere zijn :) Door alles op de context op te slaan weet je waar je mee bezig bent.

Die context (een object) wordt gemaakt via local context = { zone = zone } in de functie create. Uitleg:
- local geeft aan dat deze variabele alleen binnen de functie beschikbaar is.
- context is de naam van de variabele. Kan je zelf bedenken zolang het maar logisch is en zonder spaties
- = {} maakt het een object. Een object kan meerdere variabelen bevatten. Er is geen vast formaat in Lua en dat noemen we een dynamisch object.
- zone = zone geeft aan dat ik een variable zone maak op het object met de waarde van zone (functie argument)

Ander voorbeeld:
local user = { name = "Tadango", age = 36 }

Je kan de variabelen van user weer gebruiken via user.name bv. lcd.drawText(x, y, "User name: " .. user.name, TEXT_COLOR)

Je ziet hier dat ik 2 stukken tekst (de vaste "User name: " en de variabele user.name) aan elkaar koppel via .. De volledige parameter voor de functie lcd.drawText wordt dan "User name: Tadango".

Variabelen als lcd, model en system edg zijn standaard beschikbaar in OpenTX.
 
Eens kijken kijken of ik dat op papier krijg :)

Wanneer je in code een functie (methode) aan roept dan kan je argumenten (parameters) mee geven. De functie refresh bv wordt aangeroepen vanuit OpenTX en het argument context wordt meegegeven. De parser (applicatie die de code leest) moet jouw text analyseren om te begrijpen wat je bedoeld. Als je begint met function weet hij dat je begint met een functie. Hij verwacht dan de naam van de functie en vervolgens tussen () de argumenten gescheiden door een komma. Dat is de afspraak (syntax) in Lua (en veel andere talen). Wanneer je een functie wil gebruiken in code geef je de naam op van de functie en dan tussen () de argumenten die je mee wil geven naar de functie. Het formaat van naam(..) wordt herkend door de parser als het aanroepen van een functie.

Bij de functie create krijg je van OpenTX een zone parameter mee. Deze zone bevat informatie over de plek waar je widget staat op het scherm. Dit is onder andere de x / y positie en de hoogte en breedte. Ik sla deze zone op in de context die ik maak in de create functie. Deze context geef ik terug aan OpenTX via het return statement. OpenTX geeft deze context weer terug bij het aanroepen van refresh edg. De context is als het ware een papiertje waar je alles op zet om te onthouden. Als je 2 dezelfde widgets hebt heb je 2 versies van het papiertje. Door alleen gebruik te maken van de informatie op het papiertje weet je wat je aan het doen bent en gebruik je geen gegevens door elkaar. Je weet anders niet wat je moet doen voor welke widget. Je weet niet eens dat er meerdere zijn :) Door alles op de context op te slaan weet je waar je mee bezig bent.

Tjemig, voor de verkapte Visual Basic programeur (macrotjes in Excel....) is dit wel heavy shit. Ik denk dat ik het een beetje snap, maar of ik zelf ook zou kunnen...?

Die context (een object) wordt gemaakt via local context = { zone = zone } in de functie create. Uitleg:
- local geeft aan dat deze variabele alleen binnen de functie beschikbaar is.
- context is de naam van de variabele. Kan je zelf bedenken zolang het maar logisch is en zonder spaties
- = {} maakt het een object. Een object kan meerdere variabelen bevatten. Er is geen vast formaat in Lua en dat noemen we een dynamisch object.
- zone = zone geeft aan dat ik een variable zone maak op het object met de waarde van zone (functie argument)

Ander voorbeeld:
local user = { name = "Tadango", age = 36 }

Je kan de variabelen van user weer gebruiken via user.name bv. lcd.drawText(x, y, "User name: " .. user.name, TEXT_COLOR)

Je ziet hier dat ik 2 stukken tekst (de vaste "User name: " en de variabele user.name) aan elkaar koppel via .. De volledige parameter voor de functie lcd.drawText wordt dan "User name: Tadango".

Variabelen als lcd, model en system edg zijn standaard beschikbaar in OpenTX.
Dit is helder, Dank!
 
Zo, volgens mij is de eerste draft klaar. In de simulator lijkt het te werken zoals het hoort, met uitzondering van de Flighttimer. Die loopt langzamer dan de echte tijd (en dat heeft niets te maken met Einsteins Relativiteit...
Ik heb het vermoeden dat het script te zwaar of te ingewikkeld is... Als iemand verbeteringen kan doorvoeren dan hoor ik het graag!
https://github.com/Red-Devil74/DLG-F3K-script/blob/Change-to-Opentx-Widget/main.lua

@Tadango Weet jij of er een manier is om de data (Launch height, flight time, max altitude) op te slaan in een logfile zodat die later is terug te vinden?
 
Ik dacht dat je wel bestanden kon wegschrijven in lua maar heb daar geen voorbeeld van gezien nog.
 
Als alternatief op het wegschrijven van waarden naar een file ben ik aan het proberen of ik de data van de laatste launch kan laten zien in het scherm. Ik heb hiervoor 4 tabels aangemaakt en die vul ik als volgt:
Code:
        elseif state > 1 and nowAlt < floorAlt then        -- if "in flight" and altitude drops below X
        maxHeightHistory[lnchnr]    = maxAlt            -- Add launch data to history file
        launchHeightHistory[lnchnr]    = lnchAlt        
        launchNrHistory[lnchnr]        = lnchnr        
        durationHistory[lnchnr]        = fltTime
        state = -1                                    -- change state to "stop" but keep graph on screen

Als ik de data teken op het scherm doe ik dat als volgt:
Code:
if lnchnr > 1 then
        lcd.drawText (gRight+5,menuBar+85, "last flight #"..lnchnr-1 ,SMLSIZE+INVERS)        -- Show flight history
        lcd.drawText ( gRight+5,menuBar+105, "Max hght:",SMLSIZE)
        lcd.drawNumber ( gRight+80,menuBar+105, maxHeightHistory[lnchnr-1], SMLSIZE)
        lcd.drawText (gRight+100, menuBar+105, "m", SMLSIZE)

        lcd.drawText ( gRight+5,menuBar+125, "Launched:",SMLSIZE)   
        lcd.drawNumber ( gRight+80,menuBar+125, launchHeightHistory[lnchnr-1], SMLSIZE)
        lcd.drawText (gRight+100, menuBar+125, "m", SMLSIZE)   
        --launchNrHistory[lnchnr]
        lcd.drawText ( gRight+5,menuBar+145, "Duration:",SMLSIZE)
        lcd.drawText ( gRight+75,menuBar+145, SecondsToClock (durationHistory[lnchnr-1]), SMLSIZE)
    --    lcd.drawText (gRight+100, menuBar+145, "s", SMLSIZE)       
    end

Nu komt de vraag:
Kan dit niet allemaal in 1 tabel of array? Ofwel één array of matrix waarin alle waarden staan? Zo ja, hoe vul je die dan en hoe roep je die aan?

grt,
Arthur
 
Een matrix kan een array van arrays zijn (meer is het niet :)) dus dat moet kunnen. Denk dat je ook een array van structs kan maken, nog mooier. Zoek maar eens op structs.
 
Back
Top