Basics of Design CC Blog Design Solutions Research & Design Hub

Backend Web Development for MCU Clients

Part 2: Querying a Database in PHP

Proficiency with servers, HTTP, and backend technologies are valuable skills for the embedded systems professional. In Part 2 of this three-part article series, Raul steps us through creating a MariaDB database, how to use SQL queries to store data in the database with a slightly modified PHP script, and how to use a second PHP script to extract data from the database and send it back to a web client.

  • How can I query a database in PHP?
  • What is a MariaDB database?
  • How can I use SQL queries to store data in a database?
  • PHP

In Part 1 of this article series I discussed basic concepts regarding full-stack web development and backend/front-end web development. I also discussed a basic backend workflow for working with microcontroller (MCU)-based web clients. I explained how to set up a basic Linux web server with a database by installing the LAMP (Linux, Apache, MySQL/MariaDB and PHP) backend technology stack on a Raspberry Pi board.

I presented an Espressif ESP8266 MCU-based data logger with a Bosch Sensortec BME688 Environmental Sensor, as an example of an MCU-based web client. This data logger periodically sends sensor readings via Hyper Text Transfer Protocol (HTTP) POST requests to the web server. I explained as well a basic PHP script that runs on the server to attend the POST requests from the MCU web client. The script retrieves the sensor data that comes in the HTTP request’s body and prepares a String Query Language (SQL) query that can be used store the values in a database.

If you are not familiar with the concepts described above, please refer to Part 1 of this article series (“Backend Web Development for MCU Clients,” Circuit Cellar 399, October, 2023) so you can follow the topics presented here [1]. Here, in Part 2 of this article series, I discuss the creation of a MariaDB database on the server to store the remote sensor readings. I explain basic SQL queries to perform diverse operations with the database, and I also discuss a second PHP script to query the database to retrieve previously stored data.


MariaDB is a SQL-based relational database, so to be able to interact with it, you must have a basic understanding of SQL. What is SQL? SQL is a standard language for storing, manipulating and retrieving data from databases. With SQL you execute queries against the database to store and retrieve data, update and delete records, create new databases and new tables, create new users, set access permissions, and so on. The SQL language is intuitive and easy to understand. Once you get acquainted with the most simple queries, using a database server becomes a straightforward activity.

Listing 1 shows the procedure to create a database, a table, and a user with all the necessary access privileges. From Part 1, you should have already set up your Linux-based web server with a MariaDB/MySQL database. On your Linux server, open a terminal window and run the command from line 5 to access MariaDB. Note that you can execute “sudo mysql” instead, to the same end. Next, run the SQL query in line 8 to list all currently available databases. From now on, remember to end all SQL queries with a semicolon (“;”). MariaDB won’t execute the query until you type the semicolon.

SQL queries to create a database, a table, and a user.

1 # Creating a MariaDB/MySQL Database, Table and User2 3 ## Create a Database and a Table4 ### Start MariaDB:5     sudo mariadb6 7 ### List all available databases:8     SHOW databases;9 10 ### Create a database named ‘logger_db’:11     CREATE DATABASE logger_db; 12 13 ### Select the created database:14     USE logger_db;15 16 ### In the database, create a table named ‘sensors’:17     CREATE TABLE sensors (18         unix_t INT(11),19         gas_res DECIMAL(8,2),20         pressure DECIMAL(8,2),21         temperature DECIMAL(5,2),22         rel_hum DECIMAL(5,2),23         id INT UNSIGNED NOT NULL AUTO_INCREMENT KEY);24     25 ### As a test, insert manually a row in the table26     INSERT INTO sensors (unix_t, gas_res, pressure, temperature, rel_hum)27     VALUES(‘1688160823’, ‘50178.01’, ‘749.45’, ‘25.74’, ‘45.59’);28 29 ### Show all rows in the table30     SELECT * FROM sensors; 31     32 ### Empty the table (delete all rows without erasing the table). 33     TRUNCATE TABLE sensors;34     35 ## Create a New MariaDB User. With the user name ‘user1’ and password ‘password1’:36     CREATE USER ‘user1’@localhost IDENTIFIED BY ‘password1’;37 38 ### Check user status:39     SELECT User FROM mysql.user;40 41 ### Grant Privileges to the new MariaDB User42     GRANT ALL PRIVILEGES ON logger_db.sensors TO ‘user1’@localhost IDENTIFIED BY ‘password1’;43 44 ### Refresh privileges:45     FLUSH PRIVILEGES;46 47 ### Verify permissions for the new user:48     SHOW GRANTS FOR ‘user1’@localhost;49 50 ### Remove MariaDB User Account:51     DROP USER ‘user1’@localhost;52 53 ### Exit MariaDB:54     exit

Run line 11 to create a new database named “logger_db.” You could use any other name for your database, but it is advisable to use the same names described here, to follow all procedures avoiding potential confusion. Run line 14 to select the newly created database. From now on, all issued SQL queries will apply to the selected database.

Now, we need to create a table in the database to store the data. To do so, in the command line write and run the query shown in lines 17-23. The indentation tabs are optional. To break the query in many lines, as it is shown in the listing, just hit <Enter> to break each line. Remember that SQL queries only execute when they are ended with a semicolon; thus, this query will execute only after you type the semicolon in the last line and hit <Enter>.

What does this SQL query do? It creates a new table named “sensors” in the currently selected database (“logger_db”). This table has six columns: “unix_t,” “gas_res,” “pressure,” “temperature,” “rel_hum,” and “id.” The first column (“unix_t”) is of type INT (integer) with 11 digits. The second column (“gas_res”) is of type DECIMAL with a precision of 8 significant digits and a scale of 2 decimal digits. This means that this column can store a maximum value up to 999999.99. The same logic applies to the next columns, except for the last one (“id”). The last column (line 23) serves as the primary key that will help to uniquely identify each data row in the table. This column is of type INT UNSIGNED. It can never be null, and it auto-increments with each new row that’s inserted in the table.

After the database table is created, run the SQL query from lines 26-27 to insert your first data row manually in the newly created table. The first parenthesis in this query contains the table column names, and the second parenthesis contains the corresponding values to be inserted in each column. Repeat if you want the same query many times, changing values to store additional rows. Next, run line 30 to display all data rows already stored in the table. The asterisk (*) in this last query simply means “all.” So, the query can be interpreted as follows: “Select and display all available rows from table sensors.” After running this query, in the terminal you will see listed all rows previously inserted in the table (Figure 1). If you want to get a fresh start with your database table, purge all data from the table by running line 33. The “TRUNCATE” query will empty the database table without erasing its structure. Now if you run line 30 again, you will get an empty table.

Listing all data from the "sensors" table.
Listing all data from the “sensors” table.

Next, we need to create a database user with all the necessary privileges to perform operations in the table. We accomplish this with the query from line 36. Before running this query, replace “user1” with your own user name, and “password1” with its corresponding password. After running line 36, run line 39 to get all available users in the MariaDB database. You should see in that listing the user you just created. Going forward, run line 42 to grant all privileges that will allow the new user full control over the “sensors” table in the “logger_db” database. Here too, you must replace your own user name and password.

Run line 45 to reload the granted privileges, and run line 48 to verify that the user has received them. If for some reason you need to erase a user, run line 51 to do so. However, we need to keep the user we just created to access the database in the following examples. Finally, type “exit” to exit MariaDB (line 54). If you want to delve deeper into SQL, a suggested online tutorial [2] is available on the Circuit Cellar Article Materials and Resources webpage.

If you are new to the Linux terminal, interacting with a database from the command line can be a bit awkward at first, but it pays off in the long run. When working with servers, sometimes the only way to access them is by using a remote SSH connection from a terminal window. There is, however, some Graphical User Interface (GUI) software to interact with databases. Arguably the most popular for MySQL/MariaDB databases is “phpMyAdmin” [3] (written in PHP). It allows you to interact with MariaDB/MySQL from a web browser window.


Now that we have a working database in our server, let’s store data in it using PHP. How we do this? Listing 2 shows the same PHP code I discussed in Part 1 of this article series [1], but this new version includes code lines 20-29. These additional lines open a connection to the database, insert the received data in the database table, and check for possible errors. Let’s see how this works.

Line 20 acts in similar way to the “#include” C language preprocessor directive. It includes the “login.php” script, which defines four variables containing database login information, as shown in Listing 3. “$host” contains the host name or IP address of the database server. This will be usually “localhost” if the web server (where the PHP script is running) and the database server, both are running on the same computer. This is our case, and it generally is for most small to medium size web applications. “$database” contains the name of the database you want to access (“logger_db”), which is the database we created previously (see line 11 in Listing 1). “$user” and “$password” contain, respectively, the user name and password for the database user with the required access privileges. In this script, change the user name and password you chose when creating your database user (see lines 36, 42 from Listing 1).

Receiving CSV data in the server and storing them in the database.

1 <?php 2     // Get the body (CSV string) from the incoming request3     $csv = file_get_contents(‘php://input’); 4 5     $data_array = str_getcsv($csv); //Convert CSV to array6 7     if($data_array != null) {8         $unix_t =   time(); //Read unix time (GMT) from server9         10         // Extract received remote values from array11         $gas_res = $data_array[0]; 12         $pressure = $data_array[1];13         $temperature = $data_array[2];14         $rel_hum = $data_array[3];15 16         // Build SQL query string for the database17         $query = “INSERT INTO sensors(unix_t, gas_res, pressure, temperature, rel_hum) VALUES” . “(‘$unix_t’, ‘$gas_res’, ‘$pressure’, ‘$temperature’, ‘$rel_hum’)”;18 19         // Connect to the database20         require_once ‘login.php’; // Include login information21         $conn = new mysqli($server, $user, $password, $database);22         if ($conn->connect_error) die($conn->connect_error);    23 24         // Query the database25         $result = $conn->query($query);26 27         // If the query was unsuccessful...28         if (!$result) echo “Query error: $query\n” . $conn->error . “\n”;29         else echo “Data inserted into DB!\n”; // Send success message30     }   31 ?>
PHP script containing database login information.

1 <?php // login.php2   $host = ‘localhost’;  //Server host name or IP addres3   $database = ‘logger_db’; // Database name4   $user = ‘user1’; // Change for your own user name5   $password = ‘password1’; //Change for your own password6 ?>

Now let’s go back to Listing 2. Line 21 opens a connection to the database using the login credentials from the “login.php” script. Next, line 22 checks for any errors from the previous step. If an error has occurred, the die() function will terminate the script execution and display an error message. If the connection was opened successfully, line 25 will submit to the database the SQL query prepared in line 17. If the query is unsuccessful, line 28 sends back to the web client an error message containing the query string (“$query”) and the connection error (“$conn->error”). Otherwise, a success message is sent instead.

To test the backend so far, follow these steps: First, in your web server’s root directory, create a subdirectory called “backend” and copy into it the “receive_csv.php” and “login.php” files. We will be putting all server files inside this subdirectory. The root directory for Raspberry Pi servers or any other Debian/Ubuntu-based servers will be typically: “/var/www/html/”. So, the full path to our web application will be: “/var/www/html/backend/”. Next, connect the ESP8266 board to your PC, and upload the new version of the “esp8266_http_post_client.ino” Arduino sketch provided for Part 2 of this article series. This file and all other source code files are available on the Circuit Cellar Article Materials and Resources webpage.

In the first version of this Arduino sketch (given in Part 1) [1], I used the “ESP8266WiFi” library to manually build and send the HTTP POST requests to the server. By doing it that way, it was clearer how the HTTP requests are structured, protocol-wise. In this second version, however, I’m using the “ESP8266HTTPClient” library that makes the sending and receiving of HTTP requests more straightforward, because of its additional abstraction layer. By comparing the two versions, you will see that the second one is more compact. Besides, in this new version, now we are reading real values from the BME688 sensor, instead of using random values to simulate sensor readings.

Remember to change your Wi-Fi credentials and your server’s IP address before flashing the code. After flashing the code, open the Arduino IDE’s serial monitor to see debug information. Once the board is connected to your Wi-Fi router, it will automatically start to send data periodically to the web server. Responses from the server will be printed on the serial monitor (Figure 2). Now, access MariaDB from the command line on your server by opening a terminal window and executing “sudo mariadb”. Run the query, “USE logger_db;” and then “SELECT * from sensors;” to display the contents of the “sensors” database table. You should see listed all data received from the ESP8266 data logger that are stored in the database, similarly to what we saw previously in Figure 1.

Server response to a POST request.
Server response to a POST request.

Now that we know how to store sensor data, let’s see how to retrieve data from the database and put them in a suitable transfer format for sending them back to the web client. We will consider basically two types of web clients requesting data from our server: a regular web browser, and an embedded, MCU-based web client, such as our ESP8266-based data logger. For web browsers, XML and JSON formats are generally preferred. For MCU-based clients, however, CSV will be generally more suitable. JSON can also be used for MCU-based clients, but it is less efficient than CSV in terms of memory usage.

In Part 1 of this article series [1], I described CSV as a lightweight format that is appropriate to use with low-memory devices such as MCUs. Listing 4 shows the PHP script that fetches data from the database, formats them as a CSV string, and sends them back to the requesting web client. Let’s see how it works.

Fetching data from the database and sending them back to web clients.

1 <?php2     // If ‘from’ and ‘to’ dates arrived as key:value pairs3     if (isset($_GET[‘from_date’]) && isset($_GET[‘to_date’])) {4         $from_date = $_GET[“from_date”]; //Read date into local var.   5         $to_date   = $_GET[“to_date”]; //Read date into local var.6 7         require_once ‘login.php’; // Include DB login info8         $conn = new mysqli($server, $user, $password, $database);9 10         if ($conn->connect_error)11             die(“Connection failed: “ . $conn->connect_error);12 13         //Add begin/end hours to dates. Ex: “2023-08-08 00:00:00”14         $from_date_hour = strtotime($from_date . “ 00:00:00”); 15         $to_date_hour = strtotime($to_date . “ 23:59:59”);16 17         // Fetch data and send it back as CSV    18         Fetch_Db_Csv($conn, $from_date_hour, $to_date_hour);19         $conn->close(); // Close DB connection20     }21 22     // Fetch data and send them back as CSV23     function Fetch_Db_Csv($conn, $from_date_hour, $to_date_hour) {24         // Build the SQL query25         $query = “SELECT * FROM sensors WHERE unix_t BETWEEN ‘$from_date_hour’ AND ‘$to_date_hour’ ORDER BY unix_t”;26         27         $result = $conn->query($query); // Query the DB28 29         // If there’s at least one row, build the CSV string30         if ($result->num_rows > 0) {31             echo “unix_t,gas_res,pressure,temperature,rel_hum\n”;                        32             $csv_row = “”;33             // Read data from row into local variables34             while($row = $result->fetch_assoc()) {35                 $unix_t = $row[“unix_t”];36                 $gas_res = $row[“gas_res”];37                 $pressure = $row[“pressure”];38                 $temperature = $row[“temperature”];39                 $rel_hum = $row[“rel_hum”];40                 // Build CSV string41                 $csv_row = “’$unix_t’,’$gas_res’,’$pressure’,’ $temperature’,’$rel_hum’\n”;42                 echo $csv_row; // Send CSV string row to HTTP client43             }44         } else { // No results that match the fetch criteria...45           echo “0 results”; // Send feedback to web client46         }47     }48 ?>

Line 3 verifies that the “from_date” and “to_date” key:value pairs arrived in the incoming HTTP GET request. Only if both keys are set, the script will query the database on the client’s behalf. Lines 4-5 store both dates into local variables.

Line 7 includes the “login.php” script with the database login information, and line 8 opens a connection to the database. Line 10 checks for any connection error; if there’s any, it aborts the script execution (line 11). Line 14 concatenates the “ 00:00:00” string to the “from_date”, because to search the database we need to specify the begin-hour along with the begin-date. The result will be a string like this: “2023-08-08 00:00:00”. Similarly, with line 15, we specify “ 23:59:59” as the end-hour for the “to_date”. This includes in the search all available readings until the last second of that day. Next, line 18 calls the Fetch_Db_Csv() function defined in lines 23-47. This function queries the database, prepares the retrieved data as a CSV string, and sends them back to the HTTP client. Finally, line 19 closes the database connection.

Let’s look at how the Fetch_Db_Csv() function works. The function receives as input parameters the database connection, the “from-date-hour” and the “to-date-hour” (see line 23). In line 25, it builds the SQL query that will be used to fetch data from the database. The “*” in that query means “all,” “sensors” is the table name, and “unix_t” is the column that stores the Unix time for each row in the table (Figure 1). So, in plain English, the full query can be read as follows: Select all rows from the “sensors” table where the Unix time column has a value between “from_date_hour” and “to_date_hour”. Arrange the results by Unix time in ascending order.

Line 27 submits the query to the database, and line 30 checks if there’s at least one row as a result. If so, line 31 sends as a first text row in the CSV file the column names. Lines 34-43 iterate over all available rows, extracting column values and storing them into local variables. For each table row, it then builds a CSV row containing sensor readings (line 41), and sends it back to the HTTP client (line 42). After processing and “echoing” all rows, the client will get a CSV file with all the sensor readings that match the request criteria.

Let’s test the “fetch_csv.php” script from a web browser. First, download the aforementioned PHP script from the Circuit Cellar Article Materials and Resources webpage, and copy it to the “/var/www/html/backend/” folder in your server. Next, in the URI below, replace the IP address for your web server’s. Replace as well the start and end dates with dates you know for sure you have sensor readings stored in your database:

Open the URI in a web browser. An HTTP GET request will be sent automatically to the web server, which, in response, will send back the CSV file containing the sensor readings, as shown in Figure 3. Don’t mind the rows don’t show broken down properly; that’s just because the browser doesn’t recognize the “\n” character as a new line.

Fetching the CSV file using a web browser.
Fetching the CSV file using a web browser.

To get regular dates from the Unix timestamps in your database, convert them using an online Unix time converter. For instance, I took the first Unix time from Figure 1 (“1691526851”), and after converting it, I got “Tue Aug 08 2023 16:34:11 GMT-0400.” So, I used “2023-08-08” as start and end dates in the URI example above. You can use, however, different start and end dates; the server will send whatever data it finds in that time period.

You can also test the backend from a terminal window using the “cURL” library on a Linux machine. After changing relevant details, run the following command to get the CSV file:

curl “”

In a Windows 10/11 machine, open the Windows PowerShell and run:

Invoke-WebRequest -URI “” -UseBasicParsing

Figure 4 shows the output from the PowerShell on Windows 10. cURL on Linux will show something similar. If you are not familiar with these command line tools, don’t worry. Just use the web browser instead, as explained above. After receiving the CSV file, the HTTP client needs to parse it to get the individual values. There are available CSV parser libraries for virtually every programming language.

Fetching the CSV file from the command line.
Fetching the CSV file from the command line.

Now let’s see how to fetch the same CSV data using the ESP8266 MCU. To achieve this, we have to send practically the same HTTP GET request sent above, using the command line tools or the web browser. Listing 5 shows an excerpt of the “esp8266_http_get_client.ino” Arduino sketch that sends the required GET request to the web server. Before trying the sketch, remember to change the Wi-Fi credentials and PHP script URI in lines 1-3. The setup() function contains the same Wi-Fi initialization procedure as in the Arduino sketch that sends POST requests.

Code for the esp8266 HTTP GET client.

1 #define SSID “MyWiFi”2 #define PASSWORD  “MyCatKnowsAssembly”3 #define PHP_SCRIPT_URI “”4 String get_query_string; // ‘GET’ query string with key value pairs5 6 void setup() { // Regular Wi-Fi initialization... }7 8 void loop() {9   static long prev_millis; // Stores time of the last publication10   long elapsed_time = millis() - prev_millis;11   if (elapsed_time >= READ_INTERVAL) { // Check time interval12     String from_date = “2023-08-08”;13     String to_date = “2023-08-08”;14     get_query_string = “?from_date=” + from_date + “&to_date=” + to_date;15     Send_Get_Request(); // Send the HTTP request16     prev_millis = millis();  // Take current time17   }18 }19 20 void Send_Get_Request() {21   if ((WiFi.status() == WL_CONNECTED)) {22     WiFiClient client;23     HTTPClient http;24 25     if (http.begin(client, PHP_SCRIPT_URI + get_query_string)) { 26       int httpCode = http.GET();27       if (httpCode > 0) {28         Serial.printf(“GET code: %d\n”, httpCode);29         if (httpCode == HTTP_CODE_OK) {30           String payload = http.getString(); Serial.println(payload);31           // Parse CSV data here...32         }33       } else { Serial.printf(“GET error: %s\n”, http.errorToString(httpCode).c_str());}34       http.end();35     } else { Serial.printf(“Unable to connect\n”); }36   }37 }

Inside the loop() function, there’s also a non-blocking delay to send requests periodically on a time interval defined by the “READ_INTERVAL” constant. Inside the “if” statement (lines 11-17), the GET query string is built and the request is sent to the server. Lines 12-13 define the start and end dates for the data we are interested in to query the database. These dates must be generated dynamically, depending on the specific application. Here, for simplicity, we are defining them statically in the code.

Line 14 builds the GET query string by concatenating the “from_date” and “to_date” key:value pairs. This string will be appended to the base PHP script URI from line 3. Line 15 invokes the Send_Get_Request() function to send the request. Inside the aforementioned function (lines 20-37), a connection to the web server is opened, and the HTTP GET request is sent (line 25). The second argument to the function in line 25 is the string concatenation (“+”) of the base PHP script URI and the GET request string. The resulting string will look this:


Line 26 retrieves the HTTP response code from the server. It will have a positive value if the server received and processed the request. It will be negative if a communication error occurred. If the code is 200 (“HTTP_CODE_OK”), the server has acknowledged our request and sent a response. So, we retrieve the payload from the HTTP response’s body and print it to the serial monitor (line 30). This payload contains the CSV string with the sensor readings fetched from the database. Figure 5 is a screen capture of the Arduino IDE’s serial monitor showing the received CSV string. The first text row shows the HTTP response code. The CSV string begins in the second row, which shows the column names, followed by ten rows of sensor data.

Fetching the CSV file using the ESP8266.
Fetching the CSV file using the ESP8266.

After retrieving the payload, the CSV string must be parsed to obtain all individual sensor values. To keep the focus on the scope of this article, I will not describe here how to do the parsing. Nevertheless, the full source for this example contains parsing code using the “CSV_Parser” Arduino library. You can download it from the Circuit Cellar Article Materials and Resources webpage.

It is worth noting, however, that receiving and parsing CSV strings can consume a great amount of the MCU’s RAM, depending on the size of the incoming payload. This limits in practice the amount of data you can receive and process with an MCU. The ESP8266-based board I used for my prototype (the “NodeMCU”) has 80KB of RAM. After compiling my code with a 5,000-byte buffer for storing the payload, I still had around 46.8KB of free RAM. So, with the provided Arduino sketch, you are limited to 5,000 characters (around 120 rows of sensors data). If you want to receive more data, you must allocate more bytes to the “payload_buf” buffer in the code. But to avoid buffer overflows, it is advisable to start your tests with less data in your database, say around 10-20 rows.


Building backends with PHP and MariaDB is a straightforward process once you understand the basics of attending HTTP request with PHP scripts and storing/retrieving data from the database. Up to this point, we used unsecure HTTP instead of secure HTTPS. Thus, because of security concerns, the examples shown here are only suitable for private Local Area Networks. But adding a security layer on top of what we have done already is not difficult. There are HTTPS libraries for Arduino; and the Raspberry Pi server can be equipped with a “self-signed” SSL certificate to enable HTTPS traffic.

We also set aside concerns regarding one of the most infamous web security vulnerabilities, known as “SQL injection.” This is also not very complicated to address in PHP, by following very simple guidelines when building the SQL queries.

Next month, in Part 3 of this article series, I will address some of these concerns, and also will explain how to get data from the server in JSON and XML formats. I will also briefly discuss some workflow guidelines for front-end web development regarding IoT data visualization on a web browser. 


Advertise Here

[1] Raul Alvarez-Torrico. “Backend Web Development for MCU Clients. Part 1: Handling HTTP Requests in PHP.” Circuit Cellar 399, September, 2023.[2] SQL Tutorial.[3] phpMyAdmin: Bringing MySQL to the Web.

ESP8266 NodeMCU CP2102 ESP-12E Development Board:

Adafruit BME688 – Temperature, Humidity, Pressure and Gas Sensor – STEMMA QT:

SQL Tutorial:

Unix Time Converter:

Installing ESP8266 Board in Arduino IDE:

What is HTTP? Protocol Overview for Beginners:

Arduino |
Espressif |

Code and Supporting Files


Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article
| + posts

Raul Alvarez Torrico has a B.E. in electronics engineering and is the founder of TecBolivia, a company offering services in physical computing and educational robotics in Bolivia. In his spare time, he likes to experiment with wireless sensor networks, robotics and artificial intelligence. He also publishes articles and video tutorials about embedded systems and programming in his native language (Spanish), at his company’s web site You may contact him at

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Backend Web Development for MCU Clients

by Raul Alvarez Torrico time to read: 19 min