wiki:Docs/Prog/Manual/DeviceSupport/DIO

Version 13 (modified by Don Wilson, 19 months ago) ( diff )

--

DIO

The 825 main board is equipped with four digital input and four digital output ports. DIO option cards may be used for additional I/O options. Option cards contain eight ports which may be used as a combination of inputs and outputs.

Digital I/O

The console command prompt may be used for simple DIO testing.

echo “L000000020000000F” > /dev/mnbd

This sets the state of the mainboard digital outputs. The “L” is the command, the following 8 characters or four hexadecimal bytes represent the state desired. The final 8 characters or four hexadecimal bytes represent a mask of which outputs are to be affected. In this example “F” is used as the mask to set the state of all four on-board outputs.

# echo “I” > /dev/mnbd

This requests the status of the mainboard digital I/O.

# cat < /dev/mnbd

response:

# IA000000000

The last 8 character of the response are hexadecimal digits. Of these the first 4 digits are the state of the digital inputs. The final 4 digits are the state of the outputs. If the input 1 only is active the response is:

# IA000010000

If inputs one and two are active the response is:

# IA000030000

If inputs one, two, three, and four are active the response is:

# IA0000F0000

Only a single hexadecimal digit is needed to represent the state of the four mainboard inputs.

ResponseInput 1Input 2Input 3Input 4
0OffOffOffOff
1OnOffOffOff
2OffOnOffOff
3OnOnOffOff
4OffOffOnOff
5OnOffOnOff
6OffOnOnOff
7OnOnOnOff
8OffOffOffOn
9OnOffOffOn
AOffOnOffOn
BOnOnOffOn
COffOffOnOn
DOnOffOnOn
EOffOnOnOn
FOnOnOnOn

For additional structure formats refer to MainboardProtocol

The lib825 library provides functions to facilitate applications performing digital I/O tasks.

To perform these tests with DIO option cards replace /dev/mnbd with /dev/wt1 (for the first DIO option card), /dev/wt2 (for the second installed DIO option card), etc...

The following example shows program code to read and set DIO ports.

extern uint32 g_nRepIOIntv;

extern struct set_dio_struct mnbd_set_dio;
extern struct mnbd_dio_status_struct mnbd_dio_status;

// Read I/O status every 100 ms
g_nRepIOIntv = 100;
MnBdRequest(MNBD_DEV, MNBD_REQ_REP_IO_STATUS, NO_WAIT_ACK);

sleep(1);

while(1)
{
   if(CheckIORcv(MNBD_DEV))
   {
      if((mnbd_dio_status.inputs & 1) != 0)
      {
           // Input 1 active -- Set output 1 and break out of loop

           mnbd_set_dio.output = 0x01;
           mnbd_set_dio.mask = 0x0F;
           MnBdRequest(MNBD_DEV, MNBD_REQ_SET_IO_STATUS, NO_WAIT_ACK);
           break;
      }
   }
}

// Stop repeating I/O status
g_nRepIOIntv = 0;
MnBdRequest(MNBD_DEV, MNBD_REQ_REP_IO_STATUS, NO_WAIT_ACK);

To use this example with a DIO option card replace MNBD_DEV with the number of the installed DIO option card such "1" for the first DIO option card, or "2" for the second installed DIO option card.

If MNBD_REQ_REP_IO_STATUS is used for repeat status on multiple DIO cards or the mainboard and another DIO card at the same time it will be impossible to mnbd_dio_status structure and determine which card is providing the input. However, an array of structures is provided dio_status[x] where x = 0 mainboard, x = 1 first DIO card, x = 2 second DIO card, etc...

For digital I/O event operations refer to the DioEvent class.

DIO Events

About

This document will guide the programmer through the process of creating and using a simple DIO Event using the DioEvent class provided in the standard library (lib825). DIO Events are processed by the mainboard in order to allow a level of redundancy. Should the OPI board kernel crash the mainboard will continue to provide relay functionality and will disable events when their thresholds are reached.

The Code

To use a DIO event follow the example code below.

// required include file from lib825
#include "DioEvent.h"

int main() {
  // indicator startup (open mainboard, etc)

  // dio example
  DioEvent event;

  int scale = 1;
  int board = 0;
  int pin = 0x01;
  float fTarget = 250.00;

  // set up the event
  int myEvent = event.addEvent(scale,EVENT_GROSS,EVENT_LESS,fTarget,board,pin);

  // optionally add a conditional statement to it
  event.addCondition(myEvent,scale,EVENT_GROSS,EVENT_GREATER,0,EVENT_AND);

  // start the individual event 
  event.startEvent(myEvent);

  // OR you can start all events
  event.startAll();

  // indicator shutdown (close mainboard, etc)
  return 0;
}

The above code would create an event that would enable board 0 (mainboard) pin 0 when the gross weight of scale 1 is less than 250.00 and greater than 0.00.

DIO Counting

Description

Mainboard software 1.15 is required for counting feature. Kernel 2009-10-07 or later is required. All four inputs of the mainboard may be used for counting. The DIO cards allow any one of inputs 1 - 7 to be used for counting. Input 8 may also be used for counting. This allows for up to two inputs per DIO card to be used for counting.

Example

#include <stdio.h>
#include <stdlib.h>

#include "kypdbeep.h"
#include "lcd.h"
#include "mnbdcomm.h"

extern uint16 g_dio_count;

extern int g_keycnt;

extern uint8 g_keybuf[KEYBUF_SIZE];
extern struct set_dio_struct mnbd_set_dio;

int main() {

        char szCnt[41];

        struct timespec delaytm;
        delaytm.tv_sec = 0;
        delaytm.tv_nsec = 1000000;  // 1 ms

        InitLCD();
        ClearLCD();

        OpenBeeper();

        PrintLCD("DIO Counter Test\r");
        PrintLCD("Press '1' - '4' to toggle outputs");

        int input;

        // Note - all four input pins of mainboard may be used for counting, options card may use only one of inputs 1 - 7 for
        // counting and input 8 may always be used for counting.

        OpenMnBd(MNBD_DEV);

        struct {
                int init_cnt;
                int prescaler;
                DIOSetReg up_or_down;
                DIOSetReg low_or_high;
        } test[4] = {
                        // Experiment with different options to observe different counter behavior
                        //  Count  Prescaler    Count Up or down    Count on low to high, or high to low
                        {               0,      1,              dioSetCountUp,          dioSetCountLowToHigh },
                        {          10,          1,              dioSetCountDown,        dioSetCountLowToHigh },
                        {               0,              1,              dioSetCountUp,          dioSetCountHighToLow },
                        {         100,          2,              dioSetCountDown,        dioSetCountLowToHigh }
        };

        for(input = 1; input <= 4; input++)
        {
                if(SetDIOCounter(MNBD_DEV, input, dioSetCount, test[input-1].init_cnt, WAIT_ACK) != MNBD_REQ_ACK_RCVD)
                {
                        PrintLCD("Cannot set count\r");
                }

                if(SetDIOCounter(MNBD_DEV, input, dioSetPrescaler, test[input-1].prescaler, WAIT_ACK) != MNBD_REQ_ACK_RCVD)
                {
                        PrintLCD("Cannot set prescaler\r");
                }

                if(SetDIOCounter(MNBD_DEV, input, test[input-1].up_or_down, 0, WAIT_ACK) != MNBD_REQ_ACK_RCVD)
                {
                        PrintLCD("Cannot set count up\r");
                }

                if(SetDIOCounter(MNBD_DEV, input, test[input-1].low_or_high, 0, WAIT_ACK) != MNBD_REQ_ACK_RCVD)
                {
                        PrintLCD("Cannot set count low to high\r");
                }

                if(SetDIOCounter(MNBD_DEV, input, dioEnableCounter, 0, WAIT_ACK) != MNBD_REQ_ACK_RCVD)
                {
                        PrintLCD("Cannot enable counter\r");
                }
        }

        input = 1;

        mnbd_set_dio.output = 0;

        int req_cnt = 3000;
        int n;
        GetDIOCounter(MNBD_DEV, input, dioGetCount, NO_WAIT_ACK);

        while(1)
        {
                ReadKeypad();
                if(g_keycnt > 0)
                {
                        g_keycnt = 0;
                        if(g_keybuf[0] == ESC)
                                break;
                        // Keypad keys "1" through "4" will toggle state of output which is looped back to input
                        // so that we can observe operation of counter
                        if(g_keybuf[0] >= '1' && g_keybuf[0] <= '4')
                        {
                                mnbd_set_dio.mask = 0x000F;
                                n = g_keybuf[0] - '1';
                                if(mnbd_set_dio.output & (1 << n))
                                {
                                        mnbd_set_dio.output &= ~(1 << n);
                                        LocateLCD(n * FONT_WIDTH * 10, FONT_HEIGHT * 3);
                                        PrintLCD("  ");
                                }
                                else
                                {
                                        mnbd_set_dio.output |= (1 << n);
                                        LocateLCD(n * FONT_WIDTH * 10, FONT_HEIGHT * 3);
                                        PrintLCD("on");
                                }

                                MnBdRequest(MNBD_DEV, MNBD_REQ_SET_IO_STATUS, WAIT_ACK);
                                nanosleep(&delaytm, NULL);

                                input = n + 1;
                                req_cnt = 1;
                        }
                }

                req_cnt--;
                if(req_cnt == 0)
                {
                        GetDIOCounter(MNBD_DEV, input, dioGetCount, NO_WAIT_ACK);
                        req_cnt = 3000;
                }

                nanosleep(&delaytm, NULL);

                if(CheckDIOCountRcv(MNBD_DEV))
                {
                        sprintf(szCnt, "%6d", g_dio_count);
                        LocateLCD((input - 1) * FONT_WIDTH * 10, FONT_HEIGHT * 2);
                        PrintLCD(szCnt);

                        if(input == 4)
                                input = 1;
                        else
                                input++;

                        req_cnt = 5;
                }
        }

        // Done - disable the counters
        for(input = 1; input <= 4; input++)
        {
                if(SetDIOCounter(MNBD_DEV, input, dioDisableCounter, 0, WAIT_ACK) != MNBD_REQ_ACK_RCVD)
                {
                        PrintLCD("Cannot disable counter\r");
                }
        }

        CloseMnBd(MNBD_DEV);

        ClearLCD();

        return 0;
}


Note: See TracWiki for help on using the wiki.