1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 <2012> 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 | Index | 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 <2012> 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 |
<== Date ==> | <== Thread ==> |
---|
Subject: | Re: aiRecord conversion |
From: | Dirk Zimoch <[email protected]> |
To: | Bruno Seiva Martins <[email protected]> |
Cc: | EPICS Tech Talk <[email protected]> |
Date: | Tue, 28 Aug 2012 17:31:53 +0200 |
Hi Bruno,Your device support should have a function specialLinconv() or similar, which is function number 6 in the device support structure:
struct { long number; DEVSUPFUN report; DEVSUPFUN init; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read; DEVSUPFUN special_linconv; } myAi = { 6, NULL, NULL, initRecordAi, getInIntInfoAi, readAi, specialLinconv }; That function may look like this: STATIC long specialLinconv(aiRecord *record, int after) { epicsUInt32 hwSpan; myPrivate_t *priv = (myPrivate_t *)record->dpvt; if (after) { hwSpan = (priv->type == LCN12BMP || priv->type == LCN12BBP) ? 4095 : 65535; record->eslo = (record->eguf - record->egul) / hwSpan; record->eoff = record->egul; } return 0; }Call specialLinconv() from initRecordAi(). Additionally, the record will call it automatically when anyone changes EGUL or EGUF.
In initRecordAi(), malloc a private data structure (I called it myPrivate_t) with a field "type" (and anything else you need to store and use later, for example in readAi). Set type and then store the pointer to the structure in record->dpvt before calling specialLinconv().
In the record database, set EGUF to the user value that corresponds to the maximum ADC value (4095 or 65535 depending on your ADC type) and EGUL to the value that corresponds to the minimum ACC value (0). For example 10 and -10 (Volts). You may change that later on the fly and specialLinconv will adjust ESLO and EOFF.
Dirk Bruno Seiva Martins wrote:
Hi Ralph,Thanks for your advice! I'm still learning EPICS, so I'm using those A/D's just for experimenting. When it comes to the real deal, I'll keep in mind what you said.Best regards, Bruno Seiva MartinsOn Tue, Aug 28, 2012 at 11:05 AM, Ralph Lange <[email protected] <mailto:[email protected]>> wrote:On Tue Aug 28 2012 15:28:34 GMT+0200 (CEST), Bruno Seiva Martins <[email protected]> <mailto:[email protected]> wrote:
Rectifying: epicsFloat64 div; pao->eguf = 10.0; pao->egul = (type == LCN12BMP || type == LCN16BMP) ? 0.0 : -10.0; div = (type == LCN12BMP || type == LCN12BBP) ? 4095.0 : 65535.0;pao->hopr = pao->eguf; pao->lopr = pao->egul; pao->eslo = ((pao->eguf) - (pao->egul)) / div;Bruno Seiva MartinsAnother comment: The linear conversion mechanism is intended to convert the digitized value into the final engineering units. You might want to use your A/D converter for signals that correspond to positions [mm], pressures [mbar], or temperatures [C]. In those cases, the database designer will set EGU, EGUL and EGUF to e.g. "mm", -5 and 25, meaning that -10V are equivalent to -5mm, and +10V are equivalent to +25mm. To limit the range that is shown in the GUI, the designer might also want to set e.g. LOPR to -2 and HOPR to +2, so that graphs and meters show the "interesting" range, -2mm to +2mm. To have this work correctly, setting EGUF, EGUL, HOPR and LOPR in your device support may actually not be a good idea. Normally, I would just set ESLO and EOFF. Cheers, ~Ralph