AI-driven IoT 3D Printer Motion & Status Tracker W/ Telegram

Track lateral and vertical movements of a 3D printer via AprilTags. Then, get informed of malfunctions related to motion via Telegram.

AI-driven IoT 3D Printer Motion & Status Tracker W Telegram

Supplies

1 x Raspberry Pi Pico

1 x WIZnet Ethernet HAT

1 x DFRobot HuskyLens AI Camera

1 x Raspberry Pi 3B+ or 4

1 x Creality CR-6 SE 3D Printer

1 x Keyes 10mm RGB LED Module (140C05)

1 x Buzzer

1 x LAN Ethernet Cable

1 x Xiaomi 20000 mAh 3 Pro Type-C Power Bank

1 x USB Buck-Boost Converter Board

2 x Mini Breadboard

1 x Jumper Wires

Step 1: Story

Story

As you may have seen in my previous projects, I am utilizing a Creality CR-6 SE to print the 3D models I designed. During some of my prints, I encountered malfunctions related to the movements of my 3D printer four times while I was outside or not observing my printer. Generally, a non-watertight model, a problematic STL file, or an unstable printed part jammed or shifted one of the printer axes. When an axis is jammed or shifted, it causes faulty prints or impedes the printing process for troubleshooting.

Since the Creality CR-6 SE does not have Wi-Fi or an early warning system to monitor the printer motions and status, I decided to create a device to track the printer's lateral and vertical motions while printing so as to get informed of potential malfunctions related to the printer movements:

  • X-Axis (the hot end)
  • Y-Axis (the printer or heated bed)
  • Z-Axis

To endow this device with the ability to track X-axis, Y-axis, and Z-axis movements, I decided to employ the HuskyLens AI camera to recognize tags (AprilTags) denoting the axis motion. Since I was trying to develop a budget-friendly IoT device, I decided to utilize Raspberry Pi Pico to obtain and transfer the detected printer movements by the HuskyLens AI camera. Although there are various methods to connect Raspberry Pi Pico to the Internet, I chose to use the Pico-compatible WIZnet Ethernet HAT utilizing W5100S Hardwired TCP/IP CHIP. Since my printer is very close to my router, I did not encounter any issues regarding connecting the Ethernet cable or positioning the device.

After connecting Raspberry Pi Pico to the Internet, I decided to utilize a Telegram bot to track the detected printer axis movements and get notified of malfunctions related to the printer motions. Since Telegram is a cross-platform cloud-based messaging service compatible with iOS and Android, the Telegram bot allows the user to monitor the printer movements and potential malfunctions on several devices. On Telegram, it is effortless to create bots with a command list unalike any other messaging application, which are special accounts that do not require an additional phone number to set up.

To be able to process the detected printer movements and send updates to the Telegram bot automatically, I developed a PHP web application. The web application obtains the printer movements from the Raspberry Pi Pico via HTTP POST requests, stores the received printer movements in the given MySQL database table, detects potential malfunctions related to the printer motions, and sends updates (also notifications) to the Telegram bot via the Telegram Bot API. After developing the web application, I employed a Raspberry Pi 3 to host a LAMP web server to run the application.

Lastly, to make the device as stylish and robust as possible while operating in my workshop, I designed a T-800 Terminator-inspired case with a removable top cover (3D printable).

🎁🎨 Huge thanks to DFRobot for sending me the HuskyLens AI Camera.

🎁🎨 Huge thanks to WIZnet for providing me with a WIZnet Ethernet HAT.

🎁🎨 Also, huge thanks to Creality3D for sponsoring a Creality CR-6 SE 3D Printer.

🎁🎨 If you want to purchase some products from Creality3D, you can use my 10% discount coupon (Aktar10) even for their new and most popular printers: CR-10 Smart, CR-30 3DPrintMill, Ender-3 Pro, and Ender-3 V2. You can also use the coupon for Creality filaments.

Step 2: Designing and Printing a T-800 Terminator-inspired Case

Designing and Printing a T-800 Terminator-inspired Case

Since I wanted to place the device towards my FDM 3D printer while printing 3D models in my workshop, I decided to design a complementing metallic case to create a robust and sturdy mechanism operating flawlessly. To make device connections more accessible, I added a removable top cover to the case. Then, I got inspired by The Terminator to add a T-800 replica to the device since it aims to track the movements of the printer and detect potential malfunctions to eliminate them πŸ™‚

I designed the main case and its removable top cover in Autodesk Fusion 360. You can download their STL files below.

For the T-800 replica affixed to the removable top cover, I utilized this model from Thingiverse:

Then, I sliced all 3D models (STL files) in Ultimaker Cura.

Since I wanted to create a solid structure for the metallic case with the removable top cover and emphasize the T-800 theme, I utilized this PLA filament:

  • eSilk Silver

Finally, I printed all parts (models) with my Creality CR-6 SE 3D Printer. Although I am a novice in 3D printing, and it is my first FDM 3D printer, I got incredible results effortlessly with the CR-6 SE πŸ™‚

Step 3: Assembling the Case and Making Connections & Adjustments

First of all, I soldered female pin headers (11mm long legs) to the WIZnet Ethernet HAT and male pin headers to the Raspberry Pi Pico in order to connect them to the mini breadboard as shown below.

To recognize the learned tags (AprilTags) so as to track the printer motions (X-axis, Y-axis, and Z-axis), I connectedΒ the HuskyLens AI cameraΒ to the Raspberry Pi Pico by utilizing the I2C protocol. Also, I added a 10mm common anode RGB LED module (Keyes) and a buzzer to indicate the outcomes of operating functions.

Since the Raspberry Pi Pico operates at 3.3V, it is not able to power the HuskyLens AI camera and the RGB LED at the same time sufficiently. Therefore, I employed an external power source to supply the mentioned components: To elicit stable supply voltage, I connected a USB buck-boost converter board to a Xiaomi power bank.

After completing sensor connections and adjustments on mini breadboards successfully, I made the breadboard connection points rigid by utilizing a hot glue gun.

Then, after printing all 3D parts (models), I fastened all components to the main case and connected the LAN Ethernet cable from my router to the WIZnet Ethernet HAT.

Finally, I inserted the removable top cover in its slot on the main case and affixed the T-800 replica to the top of it via a hot glue gun. Also, I attached the HuskyLens AI camera to the case via a screw.

Step 4: Building a Telegram Bot With BotFather

Building a Telegram Bot With BotFather

I utilizedΒ BotFatherΒ to create a Telegram bot for this project. BotFather is an official Telegram bot that lets the user create and manage bots on Telegram without any coding required.

#️⃣ First of all, open BotFather on Telegram and enterΒ /startΒ to view the available command list and manuals.

#️⃣ Use theΒ /newbotΒ command to create a new bot. Enter the name of your bot when BotFather asks you for a name. It is displayed in contact details and elsewhere.

IoT 3D Printer Movement and Status Tracker

#️⃣ Then, enter the username of your bot. Usernames are 5-32 characters long and are case insensitive but may only include Latin characters, numbers, and underscores. They must end in β€˜bot', e.g. β€˜tetris_bot' or β€˜TetrisBot'.

IoT_3D_printer_tracker_bot

#️⃣ After completing the steps above, BotFather generates an authorization token for your new bot. The authorization token is a string along the lines ofΒ 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11Β that is required to authorize the bot and send requests to the Telegram Bot API. Keep your token secure and store it safely.

#️⃣ Also, you can change your bot's profile picture by using theΒ /setuserpicΒ command.

#️⃣ Finally, to add a description to your bot to be displayed when the chat is initialized, use theΒ /setdescriptionΒ command.

Since I wanted to get only printer movements updates from the Raspberry Pi Pico, I did not need to establish an SSL connection to set a webhook for the Telegram Bot API to send information back to the web application.

However, I needed to obtain the chat id to be able to send updates to the Telegram bot via the Telegram Bot API directly without establishing an SSL connection or setting up a webhook.

To get the chat id, I utilized theΒ getUpdatesΒ method, which shows incoming updates using long polling and returns an array ofΒ UpdateΒ objects.

#️⃣ Navigate to this web page by using your bot's authorization token:

https://api.telegram.org/bot<_token_>/getUpdates

#️⃣ Then, send a message to your bot and refresh the page. It will display an object list, including the chat id:

chat ➑ id ➑ 1496498083

Step 5: Developing a Web Application in PHP to Send Updates to the Bot Via the Telegram Bot API

Developing a Web Application in PHP to Send Updates to the Bot Via the Telegram Bot API

After creating my Telegram bot successfully, I decided to develop a web application in PHP, namedΒ telegram_3D_printer_bot, so as to receive printer movements from the Raspberry Pi Pico, process them to detect malfunctions, and send updates to the Telegram bot.

As shown below, the web application consists of one file and has four parameters to create the required database table and obtain printer movements:

  • index.php

Parameters:

  • x_axis
  • y_axis
  • z_axis
  • create_table

To run all functions successfully, I created a class namedΒ IoT_3D_printer_tracker. You can download and inspect theΒ index.phpΒ file below.

⭐ In the __init__ function, define the required variables to execute the functions:

  • token ➑ authorization token of the given Telegram bot
  • web_path ➑ Telegram Bot API request server
  • conn ➑ MySQL database connection settings
  • table ➑ MySQL database table name

⭐ In the send_message function, the application sends the given text to the given bot via the Telegram Bot API by employing the bot's authorization token.

Syntax:Β https://api.telegram.org/bot<token>/sendMessage?chat_id=<chat_id>&text=<string>

⭐ In the send_photo function, the application sends the given picture to the given bot via the Telegram Bot API by employing the bot's authorization token.

Syntax:Β https://api.telegram.org/bot<token>/sendPhoto?chat_id=<chat_id>&photo=<link>&caption=<string>

	public function __init__($token, $server, $conn, $table){
		$this->token = $token;
		$this->web_path = $server.$token;
		$this->conn = $conn;
		$this->table = $table;
	}
	
	// Telegram:
	public function send_message($chat_id, $string){
		$new_message = $this->web_path."/sendMessage?chat_id=".$chat_id."&text=".urlencode($string);
		file_get_contents($new_message);
	}
	
	public function send_photo($chat_id, $photo, $caption){
	    $new_photo = $this->web_path."/sendPhoto?chat_id=".$chat_id."&photo=".$photo."&caption=".$caption;
	    file_get_contents($new_photo);
	}

⭐ In the insert_new_data function, append the given printer movement information to the given database table.

⭐ In the get_data_from_database function, retrieve the latest row stored in the given database table.

⭐ In the database_create_table function, create the required database table and insert the default data items as the first row into the recently created table.

    // Database -> Insert Data:
	public function insert_new_data($x_axis, $y_axis, $z_axis, $date){
		$sql = "INSERT INTO `$this->table`(`x_axis`, `y_axis`, `z_axis`, `date`) VALUES ('$x_axis', '$y_axis', '$z_axis', '$date')";
		mysqli_query($this->conn, $sql);
	}

	// Database -> Retrieve Data:
	public function get_data_from_database(){
		$sql = "SELECT * FROM `$this->table` ORDER BY id DESC LIMIT 1";
		$result = mysqli_query($this->conn, $sql);
		if($row = mysqli_fetch_assoc($result)){
			return $row;
		}
	}
	
	// Database -> Create Table
	public function database_create_table(){
		// Create a new database table.
		$sql_create = "CREATE TABLE `$this->table`(
						id int AUTO_INCREMENT PRIMARY KEY NOT NULL,
						x_axis varchar(255) NOT NULL,
					    y_axis varchar(255) NOT NULL,
						z_axis varchar(255) NOT NULL,
						`date` varchar(255) NOT NULL
					   );";
		if(mysqli_query($this->conn, $sql_create)) echo("<br><br>Database Table Created Successfully!");
		// Insert the default data items as the first row into the given database table.
		$sql_insert = "INSERT INTO `$this->table`(`x_axis`, `y_axis`, `z_axis`, `date`) VALUES ('0,0', '0,0', '0,0', 'default')";
		if(mysqli_query($this->conn, $sql_insert)) echo("<br><br>Default Data Items Inserted Successfully!");
	}

⭐ Define the required MySQL database connection settings for Raspberry Pi and the printer_tracker object with its required parameters.

$server = array(
	"name" => "localhost",
	"username" => "root",
	"password" => "bot",
	"database" => "telegram3dprinter",
	"table" => "entries"

);

$conn = mysqli_connect($server["name"], $server["username"], $server["password"], $server["database"]);

// Define the new 'printer_tracker' object:
$printer_tracker = new IoT_3D_printer_tracker();
$bot_token = "<_____________________>"; // e.g., 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
$printer_tracker->__init__($bot_token, "https://api.telegram.org/bot", $conn, $server["table"]); 

⭐ If the 3D printer's lateral and vertical motions (X-axis, Y-axis, and Z-axis) are transferred by the Raspberry Pi Pico via an HTTP POST request:

⭐ Obtain the latest printer motions stored in the given database table.

⭐ Get the current printer motions transferred by the Raspberry Pi Pico.

⭐ Send the current printer motions to the Telegram bot, including the date and time, with the given chat id.

Go to Step 2 to learn how to elicit the chat id.

⭐ Compare the latest (previous) and current printer motions to detect potential malfunctions related to the printer's lateral or vertical motion.

⭐ Then, inform the user of detected malfunctions, if any.

⭐ After every new update, send a schematic describing 3D printer motions to the Telegram bot.

⭐ Finally, append the current printer motions to the given database table.

if(isset($_POST["x_axis"]) && isset($_POST["y_axis"]) && isset($_POST["z_axis"])){
	// Obtain the latest printer motions stored in the given database table.
	$row = $printer_tracker->get_data_from_database();
	$previous_motions = [
		"x_axis" => [intval(explode(",", $row["x_axis"])[0]), intval(explode(",", $row["x_axis"])[1])],
		"y_axis" => [intval(explode(",", $row["y_axis"])[0]), intval(explode(",", $row["y_axis"])[1])],
		"z_axis" => [intval(explode(",", $row["z_axis"])[0]), intval(explode(",", $row["z_axis"])[1])]
	];
	// Obtain the current printer motions transferred by Raspberry Pi Pico.
	$motions = [
		"x_axis" => [intval(explode(",", $_POST["x_axis"])[0]), intval(explode(",", $_POST["x_axis"])[1])],
		"y_axis" => [intval(explode(",", $_POST["y_axis"])[0]), intval(explode(",", $_POST["y_axis"])[1])],
		"z_axis" => [intval(explode(",", $_POST["z_axis"])[0]), intval(explode(",", $_POST["z_axis"])[1])]
	];
	
	// Send the current printer motions to the given Telegram bot. 
	$chat_id = ""; // 1496498083
	$date = date("Y/m/d__h:i:s A");
	$printer_tracker->send_message($chat_id, "πŸ“Œ Recent Printer Movements:\n\n βŒ› $date\n\n ➑️ X-Axis: ".$_POST["x_axis"]."\n\n ⬇️ Y-Axis: ".$_POST["y_axis"]."\n\n ⬆️ Z-Axis: ".$_POST["z_axis"]);
	// Check for potential malfunctions related to the printer's lateral or vertical motion.
	if($previous_motions["x_axis"][0] == $motions["x_axis"][0] && $previous_motions["x_axis"][1] == $motions["x_axis"][1] && $previous_motions["y_axis"][0] == $motions["y_axis"][0] && $previous_motions["y_axis"][1] == $motions["y_axis"][1] && $previous_motions["z_axis"][0] == $motions["z_axis"][0] && $previous_motions["z_axis"][1] == $motions["z_axis"][1]){
		$printer_tracker->send_message($chat_id, "β›” 3D Printer is not working!");
	}else{
		if($previous_motions["x_axis"][0] == $motions["x_axis"][0] && $previous_motions["x_axis"][1] == $motions["x_axis"][1]){
			$printer_tracker->send_message($chat_id, "⚠️ X-Axis: Potential Malfunction Detected!");
		}
		if($previous_motions["y_axis"][0] == $motions["y_axis"][0] && $previous_motions["y_axis"][1] == $motions["y_axis"][1]){
			$printer_tracker->send_message($chat_id, "⚠️ Y-Axis: Potential Malfunction Detected!");
		}
		if($previous_motions["z_axis"][0] == $motions["z_axis"][0] && $previous_motions["z_axis"][1] == $motions["z_axis"][1]){
			$printer_tracker->send_message($chat_id, "⚠️ Z-Axis: Potential Malfunction Detected!");
		}
	}
	
	// Send a schematic describing 3D printer motions.
	$printer_tracker->send_photo($chat_id, "https://ars.els-cdn.com/content/image/3-s2.0-B9780128145647000031-f03-03-9780128145647.jpg", "3D Printer Motions");
	
	// Save the current printer motions to the given database table.
	$printer_tracker->insert_new_data($_POST["x_axis"], $_POST["y_axis"], $_POST["z_axis"], $date);
	echo("Data Saved and Transferred to the Telegram Bot Successfully!");
	
}else{
	echo("Waiting for new data...");
}

⭐ If requested, create the required database table (entries), including the default data items in the first row.

if(isset($_GET["create_table"]) && $_GET["create_table"] == "OK") $printer_tracker->database_create_table();

Step 6: Setting Up a LAMP Web Server on Raspberry Pi

Setting Up a LAMP Web Server on Raspberry Pi

Since I decided to host my web application on a Raspberry Pi 3, I needed to set up a LAMP web server.

#️⃣ First of all, open a terminal window by selectingΒ Accessories ➑ TerminalΒ from the menu.

#️⃣ Then, install theΒ apache2Β package by typing the following command into the terminal and pressing Enter:

sudo apt-get install apache2 -y

#️⃣ After installing theΒ apache2Β package successfully, open Chromium Web Browser and navigate toΒ localhostΒ so as to test the web server.

#️⃣ Then, enter the command below to the terminal to obtain the Raspberry Pi's IP address:

hostname -I

#️⃣ To install the latest package versions successfully, update the Pi. Then, download theΒ PHPΒ package by entering these commands below to the terminal:

sudo apt-get update

sudo apt-get install php -y

#️⃣ To be able to send requests from the web server to the Telegram Bot API, install theΒ php-curlΒ package:

sudo apt-get install php-curl

#️⃣ Then, restart theΒ apacheΒ server to activate the installed packages on the web server:

sudo service apache2 restart

Step 7: Creating a MySQL Database in MariaDB

Creating a MySQL Database in MariaDB

Since I needed to log previous printer movements so as to detect potential malfunctions related to the printer's lateral and vertical motions, I also set up a MariaDB server on the Raspberry Pi 3.

#️⃣ First of all, install the MariaDB (MySQL) server andΒ PHP-MySQLΒ packages by entering the following command into the terminal:

sudo apt-get install mariadb-server php-mysql -y

#️⃣ To create a new user, run the MySQL secure installation command in the terminal window:

sudo mysql_secure_installation

#️⃣ When requested, type the current password for the root user (enter for none). Then, press Enter.

#️⃣ Type in Y and press Enter to set the root password.

#️⃣ Type inΒ botΒ at theΒ New password:Β prompt, and press Enter.

#️⃣ Type in Y to remove anonymous users.

#️⃣ Type in Y to disallow root login remotely.

#️⃣ Type in Y to remove the test database and its access permissions.

#️⃣ Type in Y to reload privilege tables.

#️⃣ After successfully setting the MariaDB server, the terminal prints:Β All done! Thanks for using MariaDB!

#️⃣ Finally, to create a new database in the MariaDB server, run the MySQL interface in the terminal:

sudo mysql -uroot -p

#️⃣ Then, enter the recently changed root password – bot.

#️⃣ When the terminal shows theΒ MariaDB [(none)]>Β prompt, create the new databaseΒ (telegram3dprinter)Β by utilizing these commands below:

create database telegram3dprinter;

GRANT ALL PRIVILEGES ON telegram3dprinter.* TO 'root'@'localhost' IDENTIFIED BY 'bot';

FLUSH PRIVILEGES;

#️⃣ Press Ctrl + D to exit theΒ MariaDB [(none)]>Β prompt.

Step 8: Setting and Running the Web Application on Raspberry Pi

Setting and Running the Web Application on Raspberry Pi

As discussed above, I set up a LAMP web server on my Raspberry Pi 3 to run the web application, but you can run it on any server as long as it is a PHP server.

#️⃣ First of all, install and extract theΒ telegram_3D_printer_bot.zipΒ folder.

#️⃣ Then, move the application folderΒ (telegram_3D_printer_bot)Β to the Apache serverΒ (/var/www/html)Β by using the terminal since the Apache server is a protected location.

sudo mv /home/pi/Downloads/telegram_3D_printer_bot /var/www/html/

⭐ If the web application did not receive the printer movements from the Raspberry Pi Pico via an HTTP POST request, it prints:Β Waiting for new data…

⭐ Otherwise, the web application prints: Data Saved and Transferred to the Telegram Bot Successfully!

localhost/telegram_3D_printer_bot/

⭐ If the create_table parameter is set as OK, the web application creates the requested database table and inserts the default data items as the first row into the recently created table. Then, it prints:

Database Table Created Successfully!

Default Data Items Inserted Successfully!

localhost/telegram_3D_printer_bot/?create_table=OK

Step 9: Updating and Setting Up the HuskyLens AI Camera

Updating and Setting Up the HuskyLens AI Camera

HuskyLens AI camera is capable of transferring the detection results of itsΒ built-in functionsΒ via the UART (serial) or I2C protocol. I decided to utilize the I2C protocol since it is much easier to get information with the I2C protocol on the Raspberry Pi Pico.

However, before proceeding with the following steps, I needed to update the HuskyLens firmware with the latest version to get more accurate results.

#️⃣ After connecting the HuskyLens AI camera to the computer (Windows) via a micro USB cable, click theΒ General SettingsΒ to view the version number.

#️⃣ Then, install the HuskyLens Uploader for Windows fromΒ here. If requested, you may need to install the CP2102N chip driver fromΒ here.

#️⃣ Search for the latest firmware versionΒ here, currentlyΒ V0.5.3Alpha1, and download it.

#️⃣ Run the HuskyLens Uploader, a small black CMD window will pop up first, and after a while, the interface window will appear: Then, click theΒ Select FileΒ button to upload the latest firmware file.

#️⃣ Finally, click theΒ UploadΒ button and wait about 5 minutes until the firmware is upgraded successfully.

After following the steps above, HuskyLens should display the upgraded version number on the settings menu.

Step 10: Detecting Tags (AprilTags) W/ HuskyLens

Detecting Tags (AprilTags)

After upgrading the firmware, I trained HuskyLens to learn three different AprilTags from the figure below for each printer axis (X-axis, Y-axis, and Z-axis) so as to track the printer's lateral and vertical motions.

#️⃣ First of all, switch to theΒ Tag RecognitionΒ mode.

#️⃣ Since the default setting is to learn a single tag, long press the function button to open the parameter setting interface.

#️⃣ Then, switch to theΒ Learn MultipleΒ parameter and activate it.

#️⃣ Finally, save the settings and return to theΒ Tag RecognitionΒ mode.

#️⃣ To learn a new tag (AprilTag), point the yellow + symbol to the selected tag and press the learning button. Then, release the learning button to complete learning the given tag.

#️⃣ To continue learning tags, short press the learning button before the countdown ends.

After training HuskyLens to learn tags (AprilTags) for each printer axis, I fastened each learned tag to my Creality CR-6 SE 3D printer's X-axis, Y-axis, and Z-axis without blocking its fans, sensors, or belts.

Step 11: Setting Up Raspberry Pi Pico

Setting Up Raspberry Pi Pico

Since I decided to program the Raspberry Pi Pico on Thonny, I needed to configure some settings and install MicroPython for Raspberry Pi Pico on Thonny.

#️⃣ First of all, downloadΒ the latest Thonny IDEΒ version, compatible with Windows, macOS, and Linux. If you are programming the Pico on Raspberry Pi, Thonny is already installed on the Raspberry Pi OS.

#️⃣ Then, find theΒ BOOTSELΒ button on your Raspberry Pi Pico.

#️⃣ Press theΒ BOOTSELΒ button and hold it while connecting the other end of the micro USB cable to your computer.

#️⃣ This puts the Raspberry Pi Pico into the USB mass storage device mode (Bootloader Mode).

#️⃣ Thonny should automatically open the installation screen. If not, at the bottom right-hand corner of the window, click on the Python version, chooseΒ Configure interpreter…, and selectΒ MicroPython (Raspberry Pi Pico).

#️⃣ Then, on theΒ Interpreter TabΒ screen, click theΒ Install or update firmwareΒ link.

#️⃣ When the dialog box pops up, click theΒ InstallΒ button to copy the latest version of the MicroPython firmware to the Raspberry Pi Pico.

#️⃣ Wait for the installation to complete and clickΒ Close.

After completing the steps above, Thonny should recognize the board and firmware automatically when plugging the Raspberry Pi Pico to the computer without pressing theΒ BOOTSELΒ button.

Step 12: Modifying CircuitPython Libraries for Raspberry Pi Pico and the WIZnet Ethernet HAT

Modifying CircuitPython Libraries for Raspberry Pi Pico and the WIZnet Ethernet HAT

Since the WIZnet Ethernet HAT requires Adafruit CircuitPython libraries, I needed to set and configure CircuitPython on Thonny. Plausibly, Thonny has a built-in file transfer feature that makes copying files and libraries to the Raspberry Pi Pico very easy.

However, while working on this project, I encountered many bugs, errors, and incompatibilities regarding CircuitPython libraries. Therefore, I had to modify nearly all libraries and files to rectify the occurring issues and bugs.

Below, I will explain how to set CircuitPython and fix the mentioned issues and bugs step by step. But, you can download theΒ lib.zipΒ folder and copy theΒ libΒ folder directly to your Raspberry Pi Pico without replicating the steps below.

#️⃣ First of all, download the latest versions ofΒ BlinkaΒ andΒ PlatformDetectΒ modules to run CircuitPython libraries on MicroPython.

#️⃣ To install theΒ PlatformDetectΒ module to the Raspberry Pi Pico, copy theΒ adafruit_platformdetectΒ folder and upload it to the Pico under theΒ libΒ folder.

#️⃣ To install theΒ BlinkaΒ module to the Raspberry Pi Pico, copy everything inside theΒ srcΒ folder and upload those files to the Pico under theΒ libΒ folder.

#️⃣ To free up some space, remove the unnecessary files under theΒ adafruit_blinkaΒ folder before uploading modules to the Pico.

#️⃣ To run the WIZnet Ethernet HAT, download theΒ adafruit_bus_deviceΒ andΒ adafruit_wiznet5kΒ libraries. Then, upload these libraries to the Pico under theΒ libΒ folder.

#️⃣ If Thonny throws attribute errors like below, change theΒ monotonicΒ function with theΒ ticks_cpuΒ function in all files under theΒ adafruit_wiznet5kΒ folder.

Traceback (most recent call last):
  File "", line 49, in 
  File "/lib/adafruit_wiznet5k/adafruit_wiznet5k.py", line 188, in __init__
AttributeError: 'module' object has no attribute 'monotonic'

Traceback (most recent call last):
  File "<stdin>", line 55, in <module>
  File "/lib/adafruit_wiznet5k/adafruit_wiznet5k.py", line 199, in __init__
  File "/lib/adafruit_wiznet5k/adafruit_wiznet5k.py", line 219, in set_dhcp
  File "/lib/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py", line 491, in request_dhcp_lease
  File "/lib/adafruit_wiznet5k/adafruit_wiznet5k_dhcp.py", line 363, in _dhcp_state_machine
AttributeError: 'module' object has no attribute 'monotonic'

#️⃣ If Thonny throws an error regarding allocation, set theΒ MAX_PACKETΒ bytes to 3500 or lower in theΒ adafruit_wiznet5k.pyΒ file under theΒ adafruit_wiznet5kΒ folder.

Traceback (most recent call last):
  File "<stdin>", line 50, in <module>
  File "/lib/adafruit_wiznet5k/adafruit_wiznet5k.py", line 176, in __init__
MemoryError: memory allocation failed, allocating 4000 bytes

#️⃣ To make HTTP requests to a given web application with the WIZnet Ethernet HAT, download theΒ adafruit_requestsΒ library. Then, upload theΒ adafruit_requests.pyΒ file to the Pico under theΒ libΒ folder.

Since the latest versions of theΒ adafruit_requestsΒ library are not working with theΒ adafruit_wiznet5kΒ library, I utilized the 1.8.1 version in this project.

Also, I needed to modify theΒ adafruit_requests.pyΒ file to disable checking for the server response since it causes timeout errors on Thonny.

After configuring module folders and modifying library files, I saved all required folders and files under theΒ libΒ folder. Then, I uploaded theΒ libΒ folder to the Raspberry Pi Pico via the built-in file transfer feature on Thonny.

Step 13: Reading Results Generated by HuskyLens With Raspberry Pi Pico

Reading Results Generated by HuskyLens With Raspberry Pi Pico

Since HuskyLens does not provide an official library for the Raspberry Pi Pico, I modifiedΒ these functionsΒ to obtain tag recognition results from HuskyLens via the I2C protocol.

After modifying the functions, I uploaded them under theΒ huskylib.pyΒ file to the Pico.

Then, I was able to get the learned blocks with IDs generated by HuskyLens for each detected tag (AprilTag) and process them to derive tag coordinates (tag positions).

#️⃣ When saving code files to the Raspberry Pi Pico, click theΒ SaveΒ button and choose theΒ Raspberry Pi PicoΒ option on Thonny.

Step 14: Programming Raspberry Pi Pico

Programming Raspberry Pi Pico

After uploading all required modules and libraries, I saved the following code in theΒ main.pyΒ file to run it automatically when the Raspberry Pi Pico is powered up.

⭐ Include the required modules and libraries:

import board
import busio
import digitalio
import time
import adafruit_requests as requests
from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K
import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket
from huskylib import HuskyLensLibrary
from time import sleep
from machine import Pin, PWM

⭐ Define the IoT_3D_printer_tracker class and its functions.

⭐ In the __init__ function:

⭐ Define the PHP web application path.

⭐ Setup the network configuration settings with the WIZnet Ethernet HAT's default MAC address:

0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED

⭐ Define the WIZnet Ethernet HAT pin settings.

⭐ Reset the WIZnet Ethernet HAT.

⭐ Initialize the Ethernet interface without DHCP.

⭐ Set the network configuration.

⭐ Print the WIZnet Ethernet HAT information.

⭐ Define the HuskyLens AI camera settings to activate the I2C protocol.

    def __init__(self, SPI0_SCK, SPI0_TX, SPI0_RX, SPI0_CSn, W5x00_RSTn):
        # Define the PHP web application path.
        self.App = "http://192.168.1.20/telegram_3D_printer_bot/"
        # Setup the network configuration settings:
        MY_MAC = (0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED)
        IP_ADDRESS = (192, 168, 1, 24)
        SUBNET_MASK = (255, 255, 255, 0)
        GATEWAY_ADDRESS = (192, 168, 1, 1)
        DNS_SERVER = (8, 8, 8, 8)
        # Define the WIZnet Ethernet HAT pin settings:
        ethernetRst = digitalio.DigitalInOut(W5x00_RSTn)
        ethernetRst.direction = digitalio.Direction.OUTPUT
        cs = digitalio.DigitalInOut(SPI0_CSn)
        spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX)
        # Reset the WIZnet Ethernet HAT.
        ethernetRst.value = False
        sleep(1)
        ethernetRst.value = True    
        # Initialize the Ethernet interface without DHCP.
        self.eth = WIZNET5K(spi_bus, cs, is_dhcp=False, mac=MY_MAC, debug=False)
        # Set the network configuration.
        self.eth.ifconfig = (IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER)
        # Optional: Initialize the Ethernet interface with DHCP.
        #eth = WIZNET5K(spi_bus, cs, is_dhcp=True, mac=MY_MAC, debug=False)
        # Print the WIZnet Ethernet HAT information.
        print("Chip Version: ", self.eth.chip)
        print("\nMAC Address: ", [hex(i) for i in self.eth.mac_address])
        print()
        # Define HuskyLens settings.
        self.husky_lens = HuskyLensLibrary("I2C", Pin(4), Pin(5), 0x32)
        # Define the RGB LED settings:
        self.red = PWM(Pin(10))
        self.green = PWM(Pin(11))
        self.blue = PWM(Pin(12))
        self.red.freq(1000) 
        self.green.freq(1000)
        self.blue.freq(1000)
        # Define the buzzer:
        self.buzzer = PWM(Pin(13))
        self.buzzer.freq(450)
        self.adjust_color(0, 0, 65025)

⭐ In the detect_and_transfer_motions function:

⭐ If HuskyLens recognizes three tags (AprilTags) for each printer axis in the same frame, obtain tag coordinates (positions) for X-axis, Y-axis, and Z-axis.

⭐ Define the data parameters to transfer printer movements (detected tag positions) to the given web application.

⭐ Initialize a requests object with the Ethernet interface and a socket.

⭐ Then, make an HTTP POST request with the data parameters to the web application.

⭐ After sending the current printer motions successfully, notify the user via the RGB LED and the buzzer.

⭐ Maintain the DHCP lease.

    def detect_and_transfer_motions(self, rest):
            detected_tag = self.husky_lens.command_request_blocks_learned()
            tag_number = len(detected_tag)
            if (tag_number == 3):
                self.adjust_color(65025, 65025, 0)
                x_axis = str(detected_tag[0][0]) + "," + str(detected_tag[0][1])
                y_axis = str(detected_tag[1][0]) + "," + str(detected_tag[1][1])
                z_axis = str(detected_tag[2][0]) + "," + str(detected_tag[2][1])
                print()
                print("X-Axis: " + x_axis)
                print("Y-Axis: " + y_axis)
                print("Z-Axis: " + z_axis)
                # Define the parameters to transfer printer movements to the web application.
                parameters = {"x_axis" : x_axis, "y_axis" : y_axis, "z_axis" : z_axis}
                # Initialize a requests object with the Ethernet interface and a socket.
                requests.set_socket(socket, self.eth)
                print()
                # Make an HTTP POST request to the web application.
                r = requests.post(self.App, data=parameters)
                print("-" * 60)
                print("Data Saved and Transferred to the Telegram Bot Successfully!")
                print("-" * 60)
                r.close()
                # Notify the user after sending the current printer motions.
                self.adjust_color(0, 65025, 0)
                self.buzzer.duty_u16(65025)
                sleep(5)
                self.buzzer.duty_u16(0)
                self.adjust_color(65025, 0, 65025)
            else:
                print(detected_tag)
            # Maintain the DHCP lease.
            self.eth.maintain_dhcp_lease()
            sleep(rest)

⭐ In theΒ adjust_colorΒ function, change the RGB LED color by using the PWM frequency (0 – 65025).

    def adjust_color(self, red_x, green_x, blue_x):
        self.red.duty_u16(65025-red_x)
        self.green.duty_u16(65025-green_x)
        self.blue.duty_u16(65025-blue_x)

⭐ Define the tracker class object with the WIZnet Ethernet HAT pins.

tracker = IoT_3D_printer_tracker(board.GP18, board.GP19, board.GP16, board.GP17, board.GP15)
        
while True:
    tracker.detect_and_transfer_motions(30)

Step 15: Modes and Features

Modes and Features

πŸŒπŸ€– If the WIZnet Ethernet HAT connects to the router via the Ethernet interface without DHCP, the device turns the RGB LED to blue.

πŸŒπŸ€– If HuskyLens recognizes three tags (AprilTags) for each printer axis in the same frame, the device turns the RGB LED to yellow.

πŸŒπŸ€– Then, if the WIZnet Ethernet HAT transfers tag coordinates (positions) for X-axis, Y-axis, and Z-axis to the PHP web application via an HTTP POST request successfully, the device turns the RGB LED to green and activates the buzzer to notify the user.

πŸŒπŸ€– After completing the first HTTP POST request successfully, the device turns the RGB LED to magenta as the default color.

πŸŒπŸ€– When the web application receives the current printer movements (tag positions), it compares them to the previous printer movements stored in the database table to detect potential malfunctions related to the printer motions.

πŸŒπŸ€– Then, the application sends the current printer movements with a schematic describing 3D printer motions to the given Telegram bot via the Telegram Bot API.

πŸŒπŸ€– If the web application detects potential malfunctions on X-axis, Y-axis, or Z-axis, it adds notification messages to the transferred update up to two axes.

⚠️ X-Axis: Potential Malfunction Detected!

⚠️ Y-Axis: Potential Malfunction Detected!

⚠️ Z-Axis: Potential Malfunction Detected!

πŸŒπŸ€– If the web application detects malfunctions on three axes, it adds this notification message to the transferred update:

β›” 3D Printer is not working!

πŸŒπŸ€– Also, the device prints notifications and the detected printer movements (tag positions) on the shell for debugging.

As far as my experiments go, the device works impeccably while tracking the printer movements and informing me of potential malfunctions related to the printer motions πŸ™‚

Step 16: Videos and Conclusion


About The Author

Muhammad Bilal

I am highly skilled and motivated individual with a Master's degree in Computer Science. I have extensive experience in technical writing and a deep understanding of SEO practices.

Scroll to Top