Voltage Measurement DAQ HAT for Raspberry Pi®

The MCC 118 DAQ HAT provides eight channels of analog voltage measurement for Raspberry Pi based data acquisition / data logger systems. The MCC 118 maximum data rate is 100 kS/s per board for taking single point or waveform voltage measurements. Up to eight MCC 118 devices can be stacked - providing up to 64 channels of data and a maximum throughput of 320 kS/s.

https://www.mccdaq.com/DAQ-HAT/MCC-118.aspx

This manual and the finished data acquisition system were developed together with the electronics laboratory of the Fritz-Haber-Institute and are used there.

http://www.fhi-berlin.mpg.de/elab/pub/index_e.html

In particular, this project was accompanied by Abdulrhman Moshantaf as a working student.

moshantaf@fhi-berlin.mpg.de

First download the Daqhat library from the Github page and build it.

Built the IOC

  • Built an example IOC
  • Database iocmcc118App
    • Makefile
    • mcc118.db
      • record(ai, "MCC:HA$(HA):$(CH)"){
        field(DTYP, "devMcc118")
        field(INP, "#C$(HA) S$(CH) @whatever")
        field(SCAN, "$(SCAN)")
        field(PREC, "2")
        }
  • source
    • The source files from the Daqhat library are inserted here.
    • Build DEV-files
      • devMcc118.c
      • #include <stdio.h>
        #include <stdlib.h>
        #include <dbAccess.h>
        #include <devSup.h>
        #include <recGbl.h>
        #include <alarm.h>
        #include "daqhats_utils.h"

        #include <aiRecord.h>

        #include <epicsExport.h>

        struct mcc118State {
        unsigned int address;
        unsigned int channel;
        uint8_t hat_address;
        };

        static long init_record(aiRecord *prec)
        {
        struct mcc118State* priv;
        // char configString = {0};

        priv=malloc(sizeof(struct mcc118State));
        if(!priv){
        recGblRecordError(S_db_noMemory, (void*)prec,
        "devAiMcc118 failed to allocate private struct");
        return S_db_noMemory;
        }

        if (VME_IO != prec->inp.type){
        return(S_dev_badBus);
        }
        priv->address = prec->inp.value.vmeio.card;
        priv->channel = prec->inp.value.vmeio.signal;

        // Determine the address of the device to be used
        if (select_hat_device(priv->address, &(priv->hat_address)) != 0)
        {
        return -1;
        }

        // printf("%d", priv->hat_address);

        prec->dpvt=priv;
        return 0;
        }

        static long read_ai(aiRecord *prec)
        {
        struct mcc118State* priv=prec->dpvt;
        if(!priv) {
        (void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM);
        return 0;
        }

        // mcc118_a_in_read() variables
        uint32_t options = OPTS_DEFAULT;
        double value;

        int result;
        result = mcc118_open(priv->hat_address);
        result = mcc118_a_in_read(priv->hat_address, priv->channel, options, &value);
        //printf("val: %f\n", value);
        value = floorf(value * 100) / 100;
        prec->val=value;

        result = mcc118_close(priv->hat_address);
        return 2;
        }

        struct {
        long num;
        DEVSUPFUN report;
        DEVSUPFUN init;
        DEVSUPFUN init_record;
        DEVSUPFUN get_ioint_info;
        DEVSUPFUN read_ai;
        DEVSUPFUN special_linconv;
        } devMcc118 = {
        6, /* space for 6 functions */
        NULL,
        NULL,
        init_record,
        NULL,
        read_ai,
        NULL
        };
        epicsExportAddress(dset,devMcc118);
      • mcc118dev.dbd
      • device(ai, VME_IO, devMcc118, "devMcc118")
    • Makefile
      • Add the following lines:
      • iocmcc118_DBD += mcc118dev.dbd
        iocmcc18_SRCS += devMcc118.c
        USR_SYS_LIBS += daqhats
  • st.cmd
    • dbLoadRecords("db/mcc118.db","HA=0, CH=0, SCAN=9")
      dbLoadRecords("db/mcc118.db","HA=0, CH=1, SCAN=9")
      dbLoadRecords("db/mcc118.db","HA=0, CH=2, SCAN=9")
      dbLoadRecords("db/mcc118.db","HA=0, CH=3, SCAN=9")
      dbLoadRecords("db/mcc118.db","HA=0, CH=4, SCAN=9")
      dbLoadRecords("db/mcc118.db","HA=0, CH=5, SCAN=9")
      dbLoadRecords("db/mcc118.db","HA=0, CH=6, SCAN=9")
      dbLoadRecords("db/mcc118.db","HA=0, CH=7, SCAN=9")

Voltage Output and DIO DAQ HAT for Raspberry Pi®

The MCC 152 Voltage Output and DIO HAT provides two channels of analog voltage output and eight digital I/O for Raspberry Pi based systems. The 12-bit voltage outputs feature a 0-5 V range and can be updated at up to 5 kS/s. Up to eight MCC DAQ HAT devices can be stacked onto one Raspberry Pi.

https://www.mccdaq.com/DAQ-HAT/MCC-152.aspx

Built the IOC

  • Built an example IOC
  • Database iocmccApp
    • Makefile
    • mcc152.db
      • record(ao,"MCC152:HA$(HA):$(CH)") {
        field(DESC,"set analog output")
        field(DTYP,"devMcc152")
        field(OUT, "#C$(HA) S$(CH) @whatever)
        field(OMSL, "supervisory")
        field(SCAN,"$(SCAN)")
        field(OROC,"0")
        field(PREC,"2")
        field(EGU,"VOLT")
        field(DRVH,"5")
        field(DRVL,"0")
        field(HOPR,"5")
        field(LOPR,"0") }
  • source
    • The source files from the Daqhat library are inserted here.
    • Build DEV-files
      • devMcc.c (include MCC118/152)
      • #include <stdio.h>
        #include <stdlib.h>
        #include <dbAccess.h>
        #include <devSup.h>
        #include <recGbl.h>
        #include <alarm.h>

        #include "daqhats_utils.h"

        #include <aoRecord.h>
        #include <aiRecord.h>

        #include <epicsExport.h>

        struct mcc118State {
        unsigned int address;
        unsigned int channel;
        uint8_t hat_address;
        };
        struct mcc152State {
        unsigned int address;
        unsigned int channel;
        uint8_t hat_address;
        };

        static long init_record_input(aiRecord *prec)
        {
        struct mcc118State* priv;
        // char configString = {0};

        priv=malloc(sizeof(struct mcc118State));
        if(!priv){
        recGblRecordError(S_db_noMemory, (void*)prec,
        "devAiMcc118 failed to allocate private struct");
        return S_db_noMemory;
        }

        if (VME_IO != prec->inp.type){
        return(S_dev_badBus);
        }
        priv->address = prec->inp.value.vmeio.card;
        priv->channel = prec->inp.value.vmeio.signal;

        // Determine the address of the device to be used
        //if (select_hat_device(priv->address, &(priv->hat_address)) != 0)
        //{
        //return -1;
        //}

        priv->hat_address= priv->address;
        // printf("%d", priv->hat_address);

        prec->dpvt=priv;
        return 0;
        }

        static long init_record_output(aoRecord *prec)
        {
        struct mcc152State* priv;
        // char configString = {0};

        priv=malloc(sizeof(struct mcc152State));
        if(!priv){
        recGblRecordError(S_db_noMemory, (void*)prec,
        "devAiMcc152 failed to allocate private struct");
        return S_db_noMemory;
        }

        if (VME_IO != prec->out.type){
        return(S_dev_badBus);
        }
        priv->address = prec->out.value.vmeio.card;
        priv->channel = prec->out.value.vmeio.signal;

        //printf("%d", priv->address);
        // Determine the address of the device to be used
        //if (select_hat_device(priv->address, &(priv->hat_address)) != 0)
        //{
        //return -1;
        //}
        priv->hat_address = priv->address;

        // printf("%d", priv->hat_address);

        prec->dpvt=priv;
        return 0;
        }


        static long read_ai(aiRecord *prec)
        {
        struct mcc118State* priv=prec->dpvt;
        if(!priv) {
        (void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM);
        return 0;
        }

        // mcc118_a_in_read() variables
        uint32_t options = OPTS_DEFAULT;
        double value;

        int result;
        result = mcc118_open(priv->hat_address);
        result = mcc118_a_in_read(priv->hat_address, priv->channel, options, &value);
        //printf("val: %f\n", value);
        value = floorf(value * 100) / 100;
        prec->val=value;

        result = mcc118_close(priv->hat_address);
        return 2;
        }

        static long write_ao(aoRecord *prec)
        {
        struct mcc152State* priv=prec->dpvt;
        if(!priv) {
        (void)recGblSetSevr(prec, COMM_ALARM, INVALID_ALARM);
        return 0;
        }

        // mcc152_a_out_write() variables
        uint32_t options = OPTS_DEFAULT;
        double value = prec->oval ;
        //value = floorf(value * 100) / 100;
        int result;
        result = mcc152_open(priv->hat_address);
        result = mcc152_a_out_write(priv->hat_address, priv->channel, options, value);
        //printf("val: %f\n", value);


        result = mcc152_close(priv->hat_address);
        return 2;
        }



        struct {
        long num;
        DEVSUPFUN report;
        DEVSUPFUN init;
        DEVSUPFUN init_record_output;
        DEVSUPFUN get_ioint_info;
        DEVSUPFUN write_ao;
        DEVSUPFUN special_linconv;
        } devMcc152 = {
        6, /* space for 6 functions */
        NULL,
        NULL,
        init_record_output,
        NULL,
        write_ao,
        NULL
        };
        epicsExportAddress(dset,devMcc152);



        struct {
        long num;
        DEVSUPFUN report;
        DEVSUPFUN init;
        DEVSUPFUN init_record_input;
        DEVSUPFUN get_ioint_info;
        DEVSUPFUN read_ai;
        DEVSUPFUN special_linconv;
        } devMcc118 = {
        6, /* space for 6 functions */
        NULL,
        NULL,
        init_record_input,
        NULL,
        read_ai,
        NULL
        };
        epicsExportAddress(dset,devMcc118);
      • mcc152dev.dbd
      • device(ai, VME_IO, devMcc152, "devMcc152")
    • Makefile
      • Add the following lines:
      • iocmcc152_DBD += mcc152dev.dbd
        iocmcc152_SRCS += devMcc152.c
        USR_SYS_LIBS += daqhats
  • st.cmd
    • dbLoadRecords("db/mcc152.db","HA=1, CH=0, SCAN=0")
Page last modified on October 15, 2020, at 09:44 AM
Powered by PmWiki