About Channels and channel drivers
The central point of NutDAC is the definition of an abstract IO channel, a channel driver and channel transactions. In this context a channel is characterized simply by a numeric quantity that takes different values with time. The numeric quantity does not have any implicit meaning, and basically any information that can be represented by a number can be embodied in a channel. In this sense, we could think of a channel as a state variable. Let us note here that this definition of a channel does not make any distinction between input or output channels. We call the status of a channel the pair 'value of the quantity' - 'timestamp' that determines the state of a channel in a particular time.
Typical examples of channel values are measurements from sensors and set points for actuators. Other examples are state variables of more complex subsystems, intermediate variables in calculations, selectable thresholds, time measurements, etc.
Each channel has associated a channel driver, which is simply a function to be called when the channel has to be accessed. In the case of an input channel, the channel driver will do all the necessary operations to retrieve the channel value. In case of a channel output, the channel driver will do all the necessary operations to set the output according to the value of the channel. It is thus the functionality implemented in the channel driver the one that defines whether a particular channel is an input or output (or even both!). As an example, the channel driver of an input channel measuring voltage will typically read an ADC, and the channel driver of an output channel representing the position of a servo motor will typically send the commands to the servo in order to adjust its position. NutDAC specifies how a channel driver should be defined, that is, its arguments and return values (exit code). This way NutDAC knows how to call the channel driver of any channel whenever is necessary.
The channel drivers should not be called directly, instead the programmers should perform a channel transaction, which is the 'standardized' operation required to change the status of a channel. When a channel transaction is requested, NutDAC basically does 3 things: execution of the channel driver, addition of the time stamp and (optional) post processing. A channel transaction is therefore again independent of the nature of the channel and (possible) hardware associated to it, and is a generic operation valid for all channels.
The definition of the previous abstract channel, its channel driver and the IO operation to change the status of a channel (channel transaction) conform a simple abstraction layer that separates clearly the processes of handling data of the use of the data itself. We call this layer Channel Abstracion Layer (ChAL). In most cases channels are associated to hardware, like ADCs and DACs, and thus the ChAL layer separates the process of handling the data (low level communication with buses, reading and writing registers, etc.) of its use in the particular control application. This separation allows the reuse of code in two senses: channel drivers (and therefore the hardware associated to them, if any) are straightforward reusable for different control applications, and exactly the same control application can be implemented with different underlying hardware.
NutDAC provides channel drivers for some specific integrated circuits, but in a general case, when not available, the developer will have to implement the specific drivers for the channels required in its particular application.
NutDAC comes as a set of two libraries, one written in C to create applications running in the microcontroller (NutDAC_Micro) and the other written in Java to create applications running in an ordinary computer (NutDAC_GUI). The later includes all the necessary tools to create GUIs to remotely control the application running in the microcontroller side.
As we can see in the previous figure, a NutDAC based application normally consists of 4 layers of software. The first two layers are very close to the hardware and are only present in the microcontroller side. From lower to upper with respect the hardware abstraction the layers are:
- The first layer is the Nut/OS operating system and the resources of the microcontroller. Although they are strictly different layers, they are put together for simplicity.
- The I/O drivers layer contains the channel drivers as explained before. NutDAC provides ready available drivers for some ICs, which depend on the SPI drivers provided also by NutDAC (blue blocks).
- The third layer is NutDAC itself, represented in blue color in the figure. The microcontroller side (NutDAC_Micro) contains the ChAL module, that provides the channel abstraction explained before, as well as other useful modules for building generic control applications. In the PC side (NutDAC_GUI) there is a class describing the abstract channel defined in the ChAL module (NdChannel). Once initialized correctly, NutDAC keeps objects of this class automatically synchronized through the network with the channels configured in the microcontroller, so they can be seen as their remote representation. This way the user can program easily control logic in the PC if necessary. NutDAC_GUI also provides widgets and panels for building GUIs to control and monitor the application from the PC.
- The last layer is the user application. It relies on the channel abstraction and tools provided by NutDAC to build specific control applications. Thanks to the channel abstraction provided by NutDAC, it doesn't have to deal with low level I/O mechanisms, only with the data represented by the channels. Although these applications can be implemented partly in the microcontroller and partly in the PC side, usually the microcontroller has the low level control logic and automatic controls, and the PC the GUI with manual controls, displays and indicators. In the microcontroller side the NutDAC libraries and the NutOS operating system are used to create the desired application, and in the PC side the NutDAC_GUI libraries. As explained before, the communication between the two sides is handled by NutDAC, so the programmer of a user application does not have to take care of it.
As we can see, the blue blocks in the figure are provided by NutDAC, while the yellow ones are the ones that the programmer of a specific user application has to take care of. In the most general case this includes the user application and channel drivers, although NutDAC provides ready to use drivers for some specific chips in the chaldrivers module. (Note that the part of the PC is optional)
NutDAC_Micro is divided in a set of libraries each containing different modules. Only those modules used will be part of the final application, thus saving program space. The libraries are: (for detailed information, check the NutDAC_Micro API documentation)
- arc: contains architectural dependent modules
- chal: Channel Abstraction Layer.
- chaldrivers: drivers for some specific chips (like ADCs, DACs and expanders)
- cli: Command Line Interface. It provides a serial and telnet terminal interfaces from which commands can be executed to control the system, as well as commands for basic operations. The user can easily create and add his own commands.
- dms: Data Monitor Server, gathers data automatically according to some settings and stores it or sends it to remote hosts (i.e. a GUI, where it can also be stored)
- events: event notification to remote hosts
- net: provides functions to easily initialize the Ethernet drivers and start the http server
- slogger: log system to store logs locally or in remote hosts
- sp: some signal processing algorithms
- spi: SPI bus driver
The directory structure of the project is as follows
- NutDAC_Micro: contains a Makefile with some general tasks, plus the following directories
- include: contains all the source headers (.h files)
- src: directory for the source code. It is organized in sub-directories, one for each library, each one containing the modules (the .c files) that are part of the library and a documentation file.
- bld: directory where all the building process happens. It has one directory with its corresponding Makefile for each library to be compiled.
- lib: once compiled, all the libraries will be copied here.
- app: contains the sample applications.
- doc: contains the files required to create the documentation with doxygen
NutDAC_GUI contains dozens of classes that help to build the part of the user application running in a PC. The central one is NdChannel, which represents the abstract channels defined in NutDAC_Micro. NdChannel objects work as remote representations of the channels in the microcontroller, and both sides, channels in the microcontroller and PC, are kept synchronized by NutDAC. This means that changes in a channel in the microcontroller are updated automatically in the PC and vice versa without explicit user intervention. This allows the creation of applications running partially in a PC (typically some degree of high level control or monitoring). On top of NdChannel, NutDAC_GUI also provides other useful classes for building control and monitoring applications. The classes are designed to separate the functionality from the GUI components, so that applications without GUI are possible. Thus, GUI components are in general the "visual control" of the underlying class or classes. The library is structured in the following packages:
- nutdac.types: definition of classes containing basic data types
- nutdac.channel:contain the classes related to the abstract channel
- nutdac.converters: classes to convert the raw channel values (measurements read from sensors) into quantities with meaning (volts, degrees, amps, etc.)
- nutdac.dataserver: receives and handles the channel data sent from the microcontroller through a UDP socket.
- nutdac.eventsserver: handles events notified by the microcontroller (TCP socket)
- nutdac.net: handles the socket connections with the Ethernuts
- nutdac.gui: Contains all the GUI components organized in subpackages
- ctrl: Controls for ON/OFF and continuous valued channels
- display: classes with panels to display the values of channels, including a history chart.
- calibration: panel for easily manage the calibration parameters of the channels
- datarecorder: help-panel to easily store into files the channel data coming from the microcontroller.
- net: network related GUI components
- slogger: Panel to display log messages coming from the microcontroller
- terminal: A panel featuring a telnet client from which commands can be sent to the microcontroller.
- utils: special button and slider classes used in NutDAC_GUI
- nutdac.app: includes some example applications
Because NutDAC_GUI is written in java the user application can be programmed as an applet and embedded into a web page downloadable from the web server of the microcontroller. Thus the whole application can be kept in the microcontroller, and any computer with a java enabled browser can download and execute the PC part.
Basic steps for creating applications
Creating applications is easy. We suggest you to copy one of the examples provided with the source code and modify it to your needs (as explained in detail in the Creating New Applications tutorial). In essence, the basic steps are:
- In the microcontroller side:
- Declare and configure the channels that you are going to use, providing their channel drivers.
- Start the services that you want. If you are planning to create an application in the PC side, you will need the network and the telnet server, plus probably the dms for data sending and evserver for synchronization.
- In the PC side:
- Instantiate a socket for the connection to the Ethernut
- Instantiate as many channels as you are going to use in the PC, and register in the channels the socket to use for communications with the microcontroller. Of course, the Ethernut should have those channels configured correctly.
- Connect the socket to the Ethernut
- Start the servers that keep the synchronization.
Then you can also decide if you want to do some calibration, record the data, register callbacks for remote events, and many more things. You can also create fully featured GUIs to monitor and control your system. Simply instantiate control widgets for the outputs (sliders, buttons) and displays for the inputs (charts, numeric display, binary), and associate them with the right channels. That's it. As an example of a GUI, check the 16kW hybrid power source project, in which up to 188 I/O channels were handled.