Skip to content

4. Software Design & Implementation

Hayatu Abdullahi edited this page Apr 20, 2022 · 6 revisions

Overview and Architecture

The idea behind the software aspect of this project is to follow proper C++ conducts. This includes utilizing 'SOLID' principles and data encapsulation. By abiding these rules, we can prevent merge conflicts and ultimately provide a readable and testable code to current and future collaborators.

The objective of this project is to read continuous data acquired from turbidity and PH sensors through an ADC with the aim of computing Water Quality levels dependent on the values returned. The main processes of the program were split between three phases. The purpose of this is to allow the CPU to simultaneously access different aspects of the program for a more efficient outcome. The ADS1115 comes equipped with a call-back/data ready function which gets called when a float value from the sensors is acquired. Four threads were used to access the call-back function which transfers each individual sensor data into a queue, the data then gets extracted from the queue to get computed based on the threshold values for Water quality. Finally, in the last stage, fastCGI thread was used to transmit the computed output to a Web Interface by displaying the Quality level of the water.

Software Architecture

image

Low Level Driver Class/ADC Call-back

The Raspberry pi can only recognise digitalised data; hence, an ADC was used to convert the continuous sensor data to a discrete signal. The ADC that was used for this project was the ADS1115. This specific ADC makes use of call-backs to notify the raspberry pi when the sensor data is ready. This procedure is more efficient than getters due to how unprecise they tend to be. The ADS1115 also includes a PGA with fully programmable sampling rate. This grants the developers more control towards manipulating the sensor data.

The integration of the ADS1115 with the raspberry pi was a straight forward process as Bernd Porr provided a nice class to describe the architecture and functionality of the ADS1115.

Main/Support Classes

Most of the features implemented for this project are described by C++ classes. This ensures that the SOLID principle rule is followed; additionally, it makes it easier to change functions and isolate data without heavy consequences. The ADS1115 class was inherited into the main function to access the call-back feature which returns a float value of the sensor data depending on the pin/address selected. The idea is to use the first four thread to loop through all the pin addresses when the sensor data is ready. This technique prevents polling and only allow data acquisition when the call-back is triggered (data ready). Classes were also created for each implementation of the threads. For example, the four threads inherits a thread class and calls a queue to store the sensor data it reads from the ADC and then ultimately extracts the data to send to the interface. For the purpose of following the 'Single Responsibility' rule, separate classes were created for each of the sensors. These classes inherit from the main Sensor classes that implements threads to store and extract the data from the queue.

Threads

Multi-threading allows simultaneous execution of processes within the Raspberry pi micro-processor. This feature benefits this project because it significantly increases the responsiveness and performance of the software tasks. Good response speed is paramount for a Real-time system such as the smart bottle designed for this project. Instead of using the default C++ threads which only calls static functions, a thread wrapper developed by Bernd Porr was inherited and implemented on the main sensor classes. This thread class makes use of an abstract method called run() which behaves as the thread and overloads current processes. Since the main attributes of this project are Reading sensor data, extracting sensor data and transmitting the outcome, all three of these classes inherited the thread wrapper. The stop() function was defined to stop the thread once data acquisition is complete. start() is called on the main to initialise the thread and join() activates the worker and overloads the run() function.

Sensor Data Classes

The sensor classes are responsible for acquiring, processing and transmitting the sensor data by inheriting the wrapper thread.

Web Interface

The web interface is used to display the graphs of the values taken out from different sensors. For this purpose, communication is established between jQuery and C++ via nginx web server. The webpage is designed using HTML and CSS. The JSON version of FastCGI is used to form the gateway. The request for fetching data is sent from the webpage. This request is then forwarded to the JSON CGI handler via the nginx server. From here the C++ code takes over. The JSON CGI handler's POSTCallBack receives the request from the JSON CGI handler. After this, the data is fetched from the ADC. This data is then pushed by the call-back handler in the C++ code to the JSON CGI handler, which is then displayed in the form of graphs on the webpage. To plot the graphs, dygraph charting library is used.