Remotely displaying 8 Analog inputs
Reading and displaying
This is apparently a simple project: its purpose is to display analog data coming from a remote unit that has eight
analog inputs.
Remotely means that the two devices, the Display unit and the Reader unit, are apart at a distance that could be as far
as almost a mile: 1200 m. I've said apparently because indeed it is rather complex as a system, as it is potentially able
to transfer data over a network of 127 devices on a RS485 data bus. Also each unit runs a program that works in
cooperation with an operating system that provides all the necessary support for network communication, event management
and task management, antibouncing, and more.
This use case is a relatively simple application as it's actual purpose is to just display the voltage and current and analog settings of a power supply (so not even trasmitting data at a significative distance). But it comes as an handy example that may help showcase the potentials of the system.
Building the whole thing
This article is just an introduction. The code is written in C. To compile the code AVR GCC can be used. It can also be used also ICCAVR though unfortunately this compiler is no longer developed by the manufacturer. The physical devices can be purchased or you can build yourself, however I'll present them in more detail in a future article.
Description of the devices
Both units are powered by an Atmel/Microchip ATmega32a microcontroller. From now on, in the article I refer to the Reader unit simply as "Reader" and the Display unit simply as "Display". The Reader has four buffered logic inputs, four OC outputs, and eight analog inputs ...and more (see functional schematic below). Its core part is the ATmega32 microcontroller, a LM7805 voltage regulator, some transistors to buffer the inputs and outputs, a transceiver to send and receive data from the RS485 line, a yellow LED to provide basic status information, and some opamps to buffer the analog inputs and a noise generator as explained better later on.
The Display has three+four buffered inputs (four of them used to attach an optional keyboard), and two open-collector outputs, a one-wire input with a DS18S20 thermo sensor on board, voltage regulator, RS485 transceiver and of course a display.
Looking at the picture on top of the article you may notice that the Reader is kind of a prototype. I modified an existing board that has similar characteristics to carry the ADC inputs that otherwise were not used in the original board.
Cross device processing
With reference to the drawing below, the Reader cyclically sends to the Display the values read from its analog inputs.
This is accomplished through a timer that fires an event after half a second, and inside this event routine remote procedures
are called to drive an event inside the Display bringing there the respective analog values.
In the drawing these remote procedure calls (RPC) are shown with the violet and orange arrows, where the named RPCs are listed
next to the arrows.
Inside the Display the public event (an event fired from a remote device through a remote procedure call) there is the code used to print the data on screen.
Here a code example shows how it is implemented:
The following code is located inside the Reader.
The following code is an abstract from what is located inside the Display.
Bidirectional calls
Because the Simple Field Bus Protocl (SFBP) allows multimaster networking, each device can transmit data to any other device at any
time, provided no collision happens. SFBP specifications state that in case of collision up to five attempt should be made each one
delayed by an increasing time.
So the Display can call back the Reader, or just send messages at any time. For example to drive Reader's outputs.
Changing remote outputs can be accomplished without even requiring to impement any code inside the recipient by simply using the
OS's function setOut:
Creating the project
To create the required code stubs the NSC AppWizard can be used. Within this application (see image below) the device model is
first selected. One can also define his/her own device. A name is given and the device is added to the project. Now options can
be selected to include the required features, while not including unused features to reduce the final code size.
It is also possible select the desired events that should be implemented, and add public events the device will respond to.
DisplayMaker to design pages and strings
If the selected device has a display through DisplayMaker it is possible to design pages and strings. Clicking the
Edit strings... button on AppWizard, DisplayMaker pops up.
Simply entering the text and special commands and characters using the toolbar, strings and pages can be easily and
swiftly created.
One interesting point is you can enter number placeholders with specific decimal and fixed digit formats, and references
to other indexed strings.
Each string has an identifier name, in the image below it is possible to notice that some names are enclosed in brackets,
indicating that those are indexed strings that will be accessible through the gTextCollection[] global array.
While they can be directly used, usually they are used as indexed strings that are automatically selected given an index
argument to the function textOut. Similarly a command can be included to display indexed strings that are displayed as
selectors, useful to show a menu and the current selected item simply giving the index of the current item.
DisplayMaker also offer the possibility to hold the current screen, and even add further overlapped texts to precisely position strings with ease.
After all the selections has been done and entered the desired strings for the device, more devices can be added to the project.
Once all devices has been configured as desired the project can be generated via menu Generate.
AppWizard generates the folders and files with code stubs that can be completed.
A devicename.evt.c.h module has the code stubs for the events, the devicename.prv-ini.c.h provide a place where your
initialization code can go, devicename.prv.h for your global defines, function prototypes and declarations, and
devicename.prv.c.h for your function implementations.
In this case for the Display into the PSUdisplay.pvr-ini.c.h file the initialization code to clear screen, print the main page and start the timer is placed.
While into PSUdisplay.evt.c.h the code for the selected events and pubevents is added.
The same is done for the Reader (devicename: PSUreader).
For the whole project I added about fourty lines of code!
Summary of the NSC built-in Events and Functions
- Events: Click, Longclick, Input, net, outchange, button, timer0...timer7, analog0, zeroencoder, encoder, interrupt0...interrupt2, scheduler, powerdown, powerup, keydetected, TChange.
- Public events: as per user defined; function: RPC, setbusy, resetbusy, setsync, resetsync, wait, sendOK.
- Local and Remote Methods and Functions: getIn, getOut, setOut, ResetAll, dimmer.
- Local only Functions and Methods: read (eprom), write (eprom), yield, GLOWALARMLED, DARKALARMLED, OUT, setPWM, servo, setAnalogTrigger, encoder, setTimer, getTimer, setDatetime.
- Scheduler functions: getSchedRecord, getSchedException, insertSched, deleteSched, freezeScheduler, ResetSched, readSched, writeSched.
- Networking functions: send, SendCTRL, SendData.
- Graphic methods: appendbuf, flashRead, drawbar, drawpixels, movecur, GLgotoX, GLgotoY, GLbitmapOut, _putchar, textOut, convert10Bit2Decimal, putnum, clearline, cls, showicon, drawicon, cpybuf, SetUnderline, SetDotsUnderline, SetBold, SetInvert, SetNormal
- Error handling: try, catch, getErr, raiseException.
More to come
With this system all devices can communicate and call each other's public events. Complex distributed systems can be made, and have
been made for building automation, control of industrial machineries, and even a laser game.
The system has some limitation of course, in particular tasks are cooperative, so no loop should be used inside events or function.
The AppWizard can also generate some special modules to handle cyclical functions at level of main task loop or at a millisecond pace.
Furthermore a module can be generated for special settings before and after interrupts are enabled at startup, while interrupts, if
enabled are called as events.
Also it is possible to specify a private module for data communication replacing the included SFBP.
This is an evolution from an old project, as I designed the whole Network Shared Control operating system.
I'll put online the AppWizard setup that comes with the whole NSC SDK, though at the moment I writing this article it is not yet up.
If you are interested in this project, please let me know either contacting me through this site or on my page on Facebook or commenting
on my videos on my YouTube channel.
Thanks for your interest.
Don't miss next post
Subscribe to stay up to date when new articles, videos or other contents are available.
RELATED ARTICLES
RECENT ARTICLES