Environmental monitoring with uChip

By on June 27, 2022
Pin It


Equipped with an SD card and RTC, it detects and stores temperature, humidity and barometric pressure using a combined sensor, showing the data graphically on a touch display.


Nowadays, also and above all in environmental monitoring, we are moving towards connected solutions and more and more integrated into the IoT concept, but not in all applications it is possible or convenient to have the necessary Internet connection. In such cases, it is possible to save the data obtained from the sensors and the relative measurements on non-volatile support such as an SD card, and then read and process them on a Personal Computer. The project proposed here responds to this application need, but it is not simply a data logger of environmental data, but a complete local monitoring system with graphical outputs that can make us understand the trend of the observed variables, which, in this case, are temperature, atmospheric pressure and relative humidity. The graphical representation is typical of the monitors used in a medical environment, scrolling from right to left so as to always display the latest measurements.

For our project, we use a hardware configuration described in the block diagram shown in Fig. 1. The core of the system is uChip, a module little larger than a 16-pin DIP IC, equipped with a 32-bit microcontroller. The TFT display, touch controller, and SD card are connected via SPI bus, while the sensor uses the I²C-Bus interface. A serial interface, two digital I/Os or three analogue inputs or one analogue output is also available for future applications. Thus, this system lends itself to developing numerous other applications.

On the SD card built into the display, the samples of the three variables are saved together with the timestamp, or timestamp, which allows the data to be easily processed on the computer. The system hardware, with modest software modifications, also lends itself to monitoring analogue signals.


Fig. 1


The uChip system

This tiny board, visible in Fig. 2, with dimensions of only 28.5×10.16 mm, including the USB connector, is produced in Italy and marketed by Open Electronics.

It is based on the Cortex M0 SAMD21-E18A MCU, 32 bit with 256 kB Flash memory (248 kB useful, the rest occupied by the integrated bootloader) and 32 kB static RAM and is compatible with Arduino Zero. It has two 8-pin strip connectors with an identical pitch to a DIL16 chip. Both sides of the board are visible in Fig. 2.


Fig. 2


Uchip can be powered from 3.3V to 5V on pin 16 (VEXT) or 5V from the micro USB socket and has a very sophisticated power system, as seen in the functional diagram in Fig. 3.


Fig. 3


There is a 500 mA switching Boost (Step-Up: converts 3.3V from VEXT to 5V on USB) and a 1 A Buck converter (Step-Down: from 5V USB to 3.3V on VEXT), it also has a linear regulator LDO (Low Drop-Out: low voltage input-output).

The latter regulator, a 3.3V NCP114 with a dropout voltage of 135 mV at 300 mA, powers the MCU and makes 3.3V 100 mA available on pin 15 via a solder jumper.

The VEXT voltage must not exceed 5.5V, which is the limit value of the LDO regulator.

You can power the board from the USB port at 5V, using a normal cell phone power supply, or apply a voltage from 3.3V to 5V on pin 16 (VEXT). In the first case, enabling the Buck regulator by setting VEXT_SELECT (PA15), uChip supplies other external devices at 3.3V up to 1A from pin 16 which becomes a power output. In the second case, you can connect a 3.3V to 5V power supply on VEXT or a lithium battery of appropriate capacity to pin 16 which now becomes an input. An ideal diode, made of a MOSFET P with low conduction resistance, isolates the output of the Buck. In case the USB port is used as a host, it is powered by the Boost, which is automatically activated by the pin ID of the OTG connector. The Boost is also activated or deactivated with the BOOST_ENABLE (PA14).

In case you want to reduce the noise generated by switching power supplies, you have to disable both Boost and Buck converters in this case, the MPU is no longer powered by USB but by pin 16 (VEXT), the voltage that must not exceed +5,5V. During software development, the Buck is enabled by the presence of the USB voltage. The two switching power supplies are controlled by software using the specific library or by intervening on the control pins. Fig. 4 shows the pin-out of the board.


Fig. 4


Table 1 shows the available pins of uChip and those used by the project.


The display 2.4 inch 320×240 pixel

The display is a 2.4 inch 320×240 pixel TFT touch with 18-bit by 262k colours with 6-bit per colour encoding. The control chip used for this display is an ILI9341 while the Touch Screen Controller is an XPT2046. The pictures in Fig. 5 show the display board used; as you can see, on one side it has a 14 pin connector for the display and the touch controller, on the opposite side a 4 pin one for the SD-Card. Fig. 6 shows the schematic of this board, while Table 2 shows the connections with uChip made in this project. The signals on the board are TTL at 3.3V and this is not a problem for uChip working at this voltage. The display can still be powered at 5V thanks to an LDO regulator that provides the exact voltage to power the TFT and SD. To reduce the I/O pins and to optimize the interface, the display graphics controller, the SD, and the touch controller were merged into a single SPI bus.  To save pins, the MCU-driven reset was also dispensed with by connecting it to an RC (47kΩ and 100nF) on pin 4 of the TFT.


Fig. 5

Fig. 6


To learn more about the touch display used you can consult the document “a-Si TFT LCD Single Chip Driver 240RGBx320 Resolution and 262K colour Specification” of ILI TECHNOLOGY CORP, available on the Net on various sites and possibly on www.ilitek.com.

Table 2


The BME280 sensor

The BME280 is a combined temperature, barometric pressure and relative humidity sensor from Bosch, encapsulated in a tiny metal case measuring just 2.5×2.5×0.93mm. It also consumes very little power, so it is particularly suitable for cell phones, GPS receivers or watches.

It has a pressure accuracy of ±0.12 hPa which is equivalent to about ±1 m altitude difference, with a temperature drift of only 12.6 cm/°C. The temperature sensor has a resolution of 0.01 °C and an accuracy of ±0.5 °C at 25 °C; as for the relative humidity sensor, accuracy of ±3 %RH at 25 °C is claimed.

The sensor has the same pinout as the popular BMP280 but lacks the humidity sensor.

It can be powered with a DC voltage between 1.7 and 3.6V; in our case, it is powered at 3.3V by the LDO (low drop-out) regulator inside the module (to the breakout board on which the sensor is commercially available). Fig. 7 shows the functional diagram of the sensor. All details on the Bosch sensor can be found in the technical document BME280 “Combined humidity and pressure sensor” available on the Web.


Fig. 7


The component has two distinct power supply pins: Vdd, the main power supply for the analogue and digital circuits, and Vdd the power supply for the digital I/O interface. In most cases, they are connected together, as in the case of the breadboard we used in the project, visible in Fig. 8.


Fig. 8


A schematic of this board has been derived in Fig. 9. It incorporates a 3.3V LDO regulator and a level adapter, necessary to connect it to an Arduino Uno or other microcontrollers powered at 5V, in the case of uChip the signals must be at 3.3V and these components are completely unnecessary. This board, having only 4 pins, provides only the I²C interface (CSB=1).

SDO pin allows changing the address (LSB) that by default is SDO=0 (jumper to ground) so the address is 1110110 (0x76). If SDO =1, an operation that requires cutting the jumper and connecting to Vdd, the address becomes 0x77, an operation that is not necessary in this case.

The Adafruit BME280 library with software I²C interface requires the assignment of the pins used for the bus with the Wire.begin (SDA, SCL) function.


Fig. 9


The schematic

Well, now that we have analyzed the individual modules that make up the system, let’s see the wiring diagram of the complex, that is the board we planned to host the display board, the sensor breakout board and the uChip board. There is also a serial interface and an analogue I/O on pin A6.

To turn off the display is used a PNP transistor with low saturation VCE, the board already has a limiting resistor R6= 3.9Ω (see Fig. 6) for the four backlight LEDs and, to further reduce power consumption, we added another resistor in series. So the backlight is controlled by an I/O signal (ON = LOW).

You can enable the Buck power supply using the function in the uChipPowerManagement.h library:


For this system, we recommend the power supply from a micro USB connector, in order to reduce the consumption: using the uChip Buck switching you get a lower consumption, further reduced by turning off the backlight of the display in normal operation to turn it on only when it must interact with the operator.

On pin 4 of connector J1 of the serial interface, it is possible to power the system also with a VEXT voltage from 3,3V to 5V. For voltages higher than 3.3V the display will appear brighter. You can also use a lithium-ion battery (3.7V typical). The power consumption increases significantly because the Buck regulator is not used and the display consumes more power, so the resistance of R3 should be increased. Powering from USB, the average consumption of the system is very low: about 12 mA without a backlight and 38 mA when it is turned on, i.e. when you intervene on the touch display to enter parameters or read measurements. The display is automatically turned off at each sampling and after 5 seconds of inactivity.

For future applications there is the J1 connector to use Serial1 to connect to other devices, such as a GPS receiver or other; and also the J2 connector, that2 allows to use of the 12-bit analogue input A6 or the 10 bit DAC output. These two connectors, with proper I/O initialization and subsequent program changes, also allow you to monitor three analogue signals A6 (J2), A3 and A5 (J1).


The RTC (Real Time Clock)

The MCU SAMD21 has incorporated a valid RTC (Real Time Clock) and uChip uses a very precise 32.768 Hz quartz (FK135EIHM0.032768) with a tolerance of ±20 ppm and frequency stability of -0.04 ppm/∆°C. The only drawback is that removing the power will cause the set time to be lost, but this can be overcome with some artifice, as will be seen later.


System power supply

To power it all you can turn to a battery or a mains power supply; the simplest method and ability to provide operational autonomy to the system is the use of a 12V lead-acid battery with a car charger that contains a 12/24V to 5V step-down switching with micro USB connector for uChip.

By using a switching power supply, which has high efficiency, the already low consumption can be further reduced and the autonomy can be greatly increased.

Alternatively, a lithium-ion battery (3.7V) could be used on the VEXT pin, accessible on connectors J1 and J2. In this case, as already mentioned, consumption increases.

Where mains voltage is available, a normal 5V power supply for cell phones with a micro USB connector can be used; however, this has the disadvantage of losing the clock in case of even brief blackouts. The system can be improved using two simple 1.5V batteries connected with a diode in series on the VEXT. In the case of a power failure, the batteries maintain a voltage of about 2.4V, low for the display but sufficient to operate the MCU.

A more complex power supply system could be to hold the lead-acid battery in a buffer, with a stabilized 13.5V power supply. The battery could also be of modest capacity (1.2 Ah) ensuring continuity of operation even for a few days of blackouts.


The libraries used to manage the uchip

Let’s move now on the firmware aspects, starting from the description of the libraries used and, specifically, from the one for the display, whose controller is an ILI9341; for it are available several Arduino libraries and we have used the Adafruit_GFX, together with Adafruit_ILI9341  written by the talented Limor Fried (Lady Ada). The first one contains all the graphics primitives and the second one the specifications of the controller used by the display. Also very useful is the GFX manual (adafruit-gfx-graphics-library.pdf).

For the xpt2046 touch controller, we used the xpt2046touchscreen library by Pual Stoffregen exploiting the hardware SPI bus.

Adafruit libraries were also used for the BME280 sensor.: Adafruit_Sensor.h  and Adafruit_BME280.h.

As for the uChip, you must download the library from the manufacturer of the board (www.itaca-innovation.com), to load the library on the Arduino IDE just follow the instructions (in English) of the manual. For Windows 10 it is not necessary to download the driver, which is necessary for previous versions.

For installation instructions see the guide “uChip quick start manual”, Itaca Innovation (the latest version available at the time of this writing is uChip1.0.11).


System operation

Let’s now look at the overall operation of the environmental monitoring system, with which we are going to record temperature, pressure and relative humidity on the SD card. The RTC clock is very important not only to indicate the exact time at each measurement but also to scan the sampling period.


The indication of time: the timestamp

In order to have a correct temporal location, it is necessary to accompany the events with a mark that takes the name of the timestamp.

We, humans, are accustomed to marking time as date and time, expressed in a non-decimal way and also differently expressed in many areas of the world.

This time-stamping is difficult to manage if we need to evaluate time differences between events or create graphs of sample time series.

In Unix and Unix-like operating systems, time is represented as seconds elapsed from zero hours on January 1, 1970, and is called an epoch.

The Unix epoch is a 32-bit number with a sign, and on January 19, 2038, the counter overflow will be reached with problems for many computers using a 32-bit counter.

The RTClib library has the getEpoch() function that returns the epoch as unsigned long, whose overflow is instead 07 Feb 2106 06:28:15.

Also for easier readability, in this project, we preferred to indicate the timestamp with two integers (long) of a maximum of five digits. The first number represents the days elapsed since January 1, 1900, of course, it takes into account the leap years, and the second number indicates the seconds from midnight. This makes it easy to plot the time series of environmental measurements.

This method is also used by spreadsheets such as Excel, which has as initial reference the 1st January 1900 and not 1970 while Matlab has the 1st January of year zero, to switch from one system to another just add the days of difference.

With the library RTClib, the serial day is easily calculated from the epoch, dividing it by the seconds in the day (86400) and taking the integer part. To have as reference 1 January 1900 you must add the days corresponding to the years 1900 to 1970:


days1900= long(epoch/86400)+ 25569;//days elapsed since 1/1/1900


As for the seconds of the day, just transform hours, minutes and seconds into seconds representing the fraction of the day:


secondspd= ho*3600 + mi*60 + se;//seconds elapsed in the day


The program transfers these two integers (long) to the SD along with the temperature in [°C], the barometric pressure in hectopascals [1 hP = 1 millibar] and the relative humidity in [%].

These five numbers are separated by commas. The file has a fixed name and the measurements are gradually appended to the queue.

This is what the ASCII file looks like:






In the PC processing program, the seconds were expressed as a fraction of a day = seconds/86400 then added to the days.

The data was processed in Matlab, but it can also be processed with a spreadsheet. In Excel the function DATA.VALUE(“11/09/2020”) returns the serial number 44085, the date is passed as a string. Given the serial number, the inverse function DAY(44085) returns the number 11, MONTH(44085) the number 9 and YEAR(44085) the number 2020. If you also enter the fraction of a day, you can also get the hour, minutes, and seconds. Table 3 is an example of this:

Table 3


Just import them as a text file with the comma as separator, then calculate the serial number and from that derive day, month, year, hour, minutes and seconds with the Exel functions that have the same name.


Generating the file for sd card

The epoch was used to generate data file names with a resolution of only 10 seconds. Starting with a very close reference, i.e. the first of November 2020, with four digits one can indicate the days for another 27 years and with another four digits, one can identify the 10 seconds of the day (8640/day), assuming no file is created for times less than ten seconds.

So an 8-character long file name is generated. It is generated at each acquisition start and printed on the “MEASUREMENTS” window.

Below is the generation program:


  // days since 01 Nov 2020 00:00:00 

  ng= int((epoch-1604188800)/86400); 

  // seconds/10 from midnight

  nm= int(secondspd/10);

  // file name

  String fn=Conv4digits(ng)+Conv4digits(nm)+ “.TXT”;

  // String to char array conversion



String Conv4digits(int n) {

  if (n < 10) return “000” + String(n);

  else if (n < 100) return “00” + String(n);

  else if (n < 1000) return “0” + String(n);

  else return String(n);



The name of the files generated by Arduino must not exceed eight characters, as in the old DOS, so the program checks that the number of days does not exceed four characters, that is, that it is between 0000 and 9999, with these instructions:


 // check the lower limit of days

if (ng < 0) ng = 0;

// days must be 4 characters long

if (ng > 9999) ng= 9999;


Fig. 10


How to show the environmental data graphics

To represent the historical diagrams of the three quantities measured with the BME280 sensor, it is necessary to store the measurements in a buffer of appropriate size.

The TFT display has a definition of 320×240 pixels, which can be arranged as 240 points on the X-axis and 320 on the Y axis.

If you want to use all 240 pixels to represent the measurements over the twenty-four hours, you have to sample every 1440/240 = 6 minutes (= 360 s), which is more than fine for environmental measurements.

With uChip’s SAMD21 MCU there are not the memory issues that there would be with an Arduino Uno and a 3×240 integer (1440 byte) matrix is not critical. A matrix of floats (2880 bytes) could also be used, but it’s best not to waste too much time on conversions during graphics while having high times between measurements.

We chose to have a single GBuff buffer organized as a three-row by 240 column array of integer elements:


int GBuff [3][240];// data buffer for graphics


The three lines represent temperature, barometric pressure, and relative humidity. The measurements are in float and, keeping in mind the accuracy of the sensor and the best detail of the graphs, the integers representing temperature in tenths of a degree, pressure in tenths of hP and humidity in per thousand transformed into the vector GVal[3] are transferred to the buffer.

At each sampling, the maximum and minimum of each variable GVal[j] are calculated:


      for (int j=0; j <= 2; j++){

        if (GVal[j] > ValMax[j]) ValMax[j] = GVal[j];

        if (GVal[j] < ValMin[j]) ValMin[j] = GVal[j];



These values are used to create auto scale graphs, plotting the curves between these values will give a more detailed representation. The maximum and minimum are calculated from system startup. The transfer of data into the buffer has two modes of operation.

At the beginning (first_buffer = true) the register fills up starting from the left, from the column index BuffInd =0 until BuffInd =239, last point on the right:


      if (first_buffer){

        for (int j=0; j <= 2; j++){

          GBuff[j][BuffInd]= GVal[j];



        if (BuffInd == 240) first_buffer = false;     


Once the buffer is filled, change the fill mode, all elements minus the last one, scroll one position to the left:


         for (int j=0; j <= 2; j++){

           for (int i=0; i <= 238; i++){

                          // shift left previous values

             GBuff[j][i]= GBuff [j][i+1];                                                    }



Then the measurements from the last sampling are transferred to the last location (BuffInd = 239):


     for (int j=0; j <= 2; j++){

                        // update buffer with last values

           GBuff[j][239]= GVal[j];



The PlotMeasures(int k) function will plot all three measurements in three separate 240×100 plots.

Shifting the data to the left creates a scrolling of the plot with an effect similar to that of the old paper recorders and you get a historical trend of the measurements over the last 24 hours, very useful for weather forecasting.


The menu on display

Pressing the touch display, at any time, a menu appears with four possible options, corresponding to four buttons, as seen in Fig. 11.


Fig. 11


The first time it is necessary to press the last button, “SETTINGS” in blue colour, to set the sampling period in seconds, then a year (the last two digits), month, day, hour, minutes and seconds. To set these seven numeric parameters you use the GetNum(String prompt) function that activates the virtual numeric keyboard, as seen in Fig. 12.


Fig. 12


After entering the required parameter, you have to confirm with “ok” or cancel the entry with the “C” key. The setting finishes after entering the seconds. From the program, the setting option is not possible if the acquisition is in progress, i.e. if the display shows “Acquisition…”.

The second key, “MEASUREMENTS”, shows the date and time of the last sampling, the values of the measurements, the number of samples saved on SD, the minimum and maximum values of the measurements and the name of the file, as shown in Fig. 13.


Fig. 13


In this case, Nc=269 samples were acquired on SD. The last lines indicate the minimum and maximum values, which are also the extremes of the graphs.

In the latest version of the program, if the acquisition has been started, the name of the file to which the measurements are transferred is also indicated.

The yellow “GRAPHICS” button will show the time plots of the three variables, visible in Fig. 14.


Fig. 14


This sampling, as seen in Fig. 13, was done with 60 second period, so the physical variables varied little and the autoscale creates the typical steps.

The pink button, if the SD card is not inserted, remains without writing and is useless. If the SD card is present and we have not yet started the acquisition, the message “Acq. Start/Stop” appears. Pressing the button we start the acquisition and the button becomes temporarily red with the writing “Acquisition Start” and then turns pink with the writing “Acquisition…”. When you want to end the acquisition, press this key and it will briefly turn green with the message “End Acquisition”, after which you can remove the SD card.

Processing the measurements with Matlab, we obtain the following outputs:

Processing of uChip environmental measurements

Processed file name = 00583660.TXT

Recording start date = 29-Dec-2020 10:11:04

End date = 29-Dec-2020 11:33:04

Number of samples acquired = 83

Recording duration = 82.00 [minutes]


The corresponding graph is shown that in Fig. 15.

Comparing the graphs in Fig. 14 with those in Fig. 15, one can see that they are very similar, keeping in mind that Matlab joins the points with interpolated curves and that the horizontal scales are very different.


Fig. 15


The program written in Matlab to process the files is the one in Listing 1.

Those who don’t have Matlab can download for free the GNU Octave program which now also has a good graphical user interface. This program also works with Octave without modification.

Listing 1

% program TPHread.m reads data written by the UChip system
% of environmental measurements with date in Julian and time in seconds
% Giovanni Carrera 29 Oct 2020
files= dir(‘*.TXT’);
nfile=size(files,1);% number of files found
for indf=1:nfile,
fprintf(‘%d) %s\n’,indf,files(indf).name);
while true
nf = input(‘number of files to be read = ‘);
if (nf>=1) && (nf<=nfile), break, end
nomefile = files(nf).name;
fid = fopen(nomefile);
if fid==-1
error([nomefile ‘: the file does not exist’]);
% Import the file
Data = importdata(filename, DELIMITER, HEADERLINES);
Gd = Data(:,1);% day vector in Julian
t = Data(:,2);% vector time in seconds
julian = Gd+t/86400+693960;% adds the fraction day and adjusts the year
T = Date(:,3);% temperature in [°C].
P = Date(:,4);% pressure in [hP].
RH = Data(:,5);% relative humidity in [%].
Ns = size(Data,1);
clear Data;
disp('Processing uChip environmental measurements')
fprintf('Processed file name = %s\n',filename);
fprintf('Recording start date = %s\n', datestr(julian(1)));
fprintf('Recording end date = %s\n', datestr(julian(end)));
fprintf('Number of samples acquired = %d \n', Ns);
Rt = julian(end)-julian(1);
fprintf('Recording duration = %6.2f [minutes]\n', Rt*1440);
tz =julian-julian(1);
subplot(3,1,1), plot(tz,T,'r','LineWidth',2),grid,ylabel('T [C]'),title(['File: ' filename])
subplot(3,1,2), plot(tz,P,'g','LineWidth',2),grid,ylabel('P [hP]')
subplot(3,1,3), plot(tz,RH,'b','LineWidth',2),grid,ylabel('H [%]'),xlabel('days')


The uChip firmware is too bulky to fit in this article, but you can find it in the download section of our site along with the other project files.


List of Components:

R1: 47 Kohm

R2: 1 Kohm

R3: 6.8 ohm

C1,C3: 100 nF

C2: 100 nF 63V polyester

T1: BC547


U2: BME280

LCD1: 240×320 2.4″ touchscreen display

J1: 4-pole male strip

J2: male strip 3 poles



– 4 pole female strip

– 8 poles female strip

– 14 poles female strip

– Printed circuit board S1540 (96×54)



The project proposed here is the basis for realizing detection systems of various parameters, even not necessarily environmental: it is sufficient to choose suitable sensors and modify the firmware.





BME280 – Pressure, humidity, temperature sensor


About Boris Landoni

Boris Landoni is the technical manager of Open-Electronics.org. Skilled in the GSM field, embraces the Open Source philosophy and its projects are available to the community.

One Comment

Leave a Reply

Your email address will not be published.