Table of Contents
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.
Response | Input 1 | Input 2 | Input 3 | Input 4 |
0 | Off | Off | Off | Off |
1 | On | Off | Off | Off |
2 | Off | On | Off | Off |
3 | On | On | Off | Off |
4 | Off | Off | On | Off |
5 | On | Off | On | Off |
6 | Off | On | On | Off |
7 | On | On | On | Off |
8 | Off | Off | Off | On |
9 | On | Off | Off | On |
A | Off | On | Off | On |
B | On | On | Off | On |
C | Off | Off | On | On |
D | On | Off | On | On |
E | Off | On | On | On |
F | On | On | On | On |
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; }