There are a bunch of articles and videos on how to use Kotlin on a Raspberry Pi, but they all are focused on using Kotlin/Native to compile code directly to the Pi. What if you want to use Kotlin on the Raspberry Pi, while not worrying about cross-compiling? Kotlin on the good old JVM is your answer!
TLDR: All of my code has been uploaded to this github repository.
Why JVM?
The JVM is a great piece of engineering, it’s fast, battle tested, and it runs pretty much everywhere. You also get the benefit of a huge ecosystem of tools and libraries.
That all sounds pretty great, now how do we do it?
Setting up the Raspberry Pi Itself
If you’ve already got a Raspberry Pi setup, you can skip to Adding Java, otherwise, let’s start at the very beginning.
Downloading the OS
The first step is download the OS from the Raspberry Pi website. There are a bunch of options, but the easiest way is to use the Raspberry Pi Imager tool that is linked at the top of that page. If you’d rather, you can download OS image directly, and flash it onto your SD card with your tool of choice.
Setting up Wifi on the Raspberry Pi
Once you have the OS flashed onto your SD card, the next step will be to get your Raspberry Pi connected to your local network. This is really easy if you have a monitor with a keyboard and mouse connected it (you can just set it up using it’s GUI like any other computer), but what if you don’t have either of those, or what if you flashed the “lite” version of the OS that doesn’t include a GUI by default? Luckily for us, there’s a way to get the Raspberry Pi connected to wifi without any of those things.
- Plug your Raspberry Pi’s SD card into your computer
- Create a
wpa_supplicant.conf
file in the Raspberry Pi’s boot folder, it’s contents should be the same as below:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=<Insert 2 letter country code here>
network={
ssid="<Name of your wireless LAN>"
psk="<Password for your wireless LAN>"
}
Remember to set the name of your network, its password, and your 2 letter country code.
The next time your Raspberry Pi boots, it’ll connect to your wifi! Now since you have the Pi’s SD plugged into your computer already, let’s enable SSH too.
Enabling SSH
Enabling SSH will allow us to control the Raspberry Pi remotely. It allows us to easily deploy files and debug our code, without needing direct access to the Raspberry Pi itself. It’s super important to enable.
There are a few ways of enabling SSH, but the easiest is by creating a blank file in the root of the Raspberry Pi’s SD card named SSH
(note the file doesn’t have an extension). If you are using Linux, or a Mac, the easiest way to do this is by typing the following command into your terminal: touch /PATH_TO_RASPBERRY_PIS_SD_CARD/SSH
. The touch command will create a blank file for you. If you’re using Windows, you can open the SD card in Explorer, right click and choose New, then choose text file, enter the name SSH, and finally delete the .txt file extension.
Connecting to the Raspberry Pi for the first time
At this point, your Raspberry Pi should be setup and ready for its first boot. You can take your SD card out of your computer and plug it into your Raspberry Pi. Plug in your power cable and give it a few minutes to start up, some of the lights onboard should start to light up and blink. After waiting a few minutes, it’s now time to test out and see if everything you did so far worked. We are going to try and remotely connect to the Raspberry Pi for the first time.
To connect to the Raspberry Pi, we need to first figure out its name on our local network. The easiest test is by typing the following command into your terminal: ping raspberrypi.local
. If it’s successful, it’ll result in something like this filling your terminal:
$ ping raspberrypi.local
PING raspberrypi.local (192.168.1.131): 56 data bytes
64 bytes from 192.168.1.131: icmp_seq=0 ttl=255 time=2.618 ms
If the results look like this instead:
$ ping raspberrypi.local
ping: cannot resolve raspberrypi.local: Unknown host
You’ll need to do a little more work to figure out what the Raspberry Pi is called. There are a few more suggestions here to help. Most likely you’ll need to call the Pi by its IP address, rather than raspberrypi.local.
The ping command will keep repeating until you stop it. Pressing CTRL + c
on your keyboard will put an end to it. Now that we know the Raspberry Pi’s name, we can connect to it.
Still in your terminal, type: ssh pi@raspberrypi.local
or ssh pi@192.168.x.x
(if you’re using its IP address). Your computer will now connect and “SSH into” your Raspberry Pi. It should prompt you to enter in a password, which by default is raspberry
. If it asks you a yes/no question about “finger prints”, you can just type out “yes”, and you’ll see that it’s connected. You can now use your terminal to move around your Raspberry Pi, as if it was your personal computer.
Changing the root Password
While not needed, it’s good practice to change your Raspberry Pi’s root password away from the default. While not likely, this will make it more difficult to hack.
While logged into your Raspberry Pi’s pi
account, type the command passwd
. This will ask you to enter in the current password, then your new password, then to confirm your new password.
Adding Java
We have one final thing to set up on the Raspberry Pi itself: making sure Java is installed. If you have the standard “full” version of Raspberry OS, Java is probably already installed. To test, in the terminal where you’ve SSH’d into your Raspberry Pi, type java -version
. If it outputs something like the following, you’re good to go and can skip to the next section:
$ java -version
java version "11.0.1" 2018-10-16 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.1+13-LTS)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.1+13-LTS, mixed mode)
Otherwise, you’ll need to install Java. Luckily for you, this is actually pretty easy. All you need to do is run the following two commands to install it:
$ sudo apt update
$ sudo apt install default-jdk
Once this is finished, you can check that Java was install properly by running the java -version
command again, it should now output something similar to what I outlined above.
Awesome! That takes care of setting up the Raspberry Pi, now onto the good stuff! You can now log out of your SSH session by entering the command exit
into your terminal, we are going to focus on your host computer for a bit.
Getting Your Environment Ready
You can write Kotlin using pretty much any text editor, but IntelliJ is an awesome IDE (and it’s free) and a great tool for Kotlin development. Both IntelliJ and Kotlin were created by the same company, so its Kotlin support is first rate.
Installing IntelliJ
You can download and install IntelliJ directly from their website. We will only need the free Community edition, and not the Ultimate one. Once it’s downloaded and installed, open it up and work through the “first time setup wizard”. You should eventually come IntelliJ’s start screen, where you can choose to start a new project/open an existing one.
Installing the Embedded Linux JVM Debugger Plugin
Now that we have IntelliJ all setup, we are going to install a plugin that will make running and testing our Kotlin code on our actually Raspberry Pi way easier. It’s called the Embedded Linux JVM Debugger plugin and it allows you to run, deploy and debug Kotlin code directly on your Raspberry Pi via IntelliJ’s UI. It’s a really time saver and makes the overall development experience substantially nicer.
From the IntelliJ welcome screen, click on the Configure in the bottom right corner. This should open a drop down menu, from that menu, click on Plugins. Select the Marketplace tab at the top of the window and start typing Embedded Linux JVM Debugger, and click the Install button. The plugin should start downloading and installing, once finished, click the Okay button to finish up and return the welcome screen.
Now that we have our environment set up, let’s get programming!
The Programming Part
Before we get into the code, we have to step through the project wizard, to set everything up.
Project Setup
Click on the + New Project
button to get started. You’ll be greeted with a huge amount of options to choose from. For our use case, it’s pretty easy, we will choose Kotlin from the list on the left. Then set the options from the top:
- Choose a Name for your Raspberry Pi project, and a Location to save it (any name you want and any where you want)
- Choose the Console Application under Project Template
- Choose Gradle Kotlin for the Build System
- Choose a Project JDK that matches what you installed on the Raspberry Pi earlier, if you don’t already have a JDK installed, click on the Download JDK option, and choose one from the list. OpenJDK is a great choice here, but you really can’t go wrong.
- Click Next
On this next screen, you can leave everything default:
Click Finish and it’s time to get started!
Initial Test Run
This will open up a new window that looks like:
If you don’t see the Project side panel, just click the vertical Project text on the left, this will open it up.
From there, expand the folders (ProjectPi > src > main > kotlin) in the project panel until you find a main.kt file. Double click on that, which will display a main function which prints out Hello World. This will be your starting point for any code you add to your project, you’ll want to add it here.
To test run your program on your computer, you can click on the little green play button to the left of the fun main
line, and choose Run Mainkt. This will open the Run panel on the bottom of the screen, and print “Hello World”.
Now that it all works on our PC, let’s try running it on the Raspberry Pi!
Testing on the Raspberry Pi
Thanks to the Embedded JVM plugin we installed earlier, getting the program running on a Raspberry Pi is as simple as setting up a new IntelliJ run configuration.
Clicking where it says MainKt in the upper right of IntelliJ will open the run configuration drop down.
Click Edit Configurations and then click the + button in the upper left of the new window. From there, Embedded Linux JVM and give it a name. Enter the name of the raspberry pi from before as the Host Name. Then fill our your Raspberry Pi’s username and password. Change the Module to WHATEVER_YOUR_PROJECT_NAME.main and set the Main Class to MainKt.
Before clicking OK, click on the Validate Connection button. If everything is setup correctly, this should succeed.
Now back in the main IntelliJ interface, if you run the new configuration, a panel will open on the bottom of the screen again, but it’ll now be running on the Raspberry Pi!
Controlling the Raspberry Pi
So that’s all fine and dandy, we have a programming running on the Raspberry Pi, but we still need to set up the ability to control the it’s hardware, like GPIOs. For this we will leverage the wonderful Java library Pi4J and optional Kotlin bindings Pi4K (you can always write your own versions of this if needed/wanted).
Note: In this tutorial, I’m not going to dig into the Raspberry Pi hardware, because that’s another huge topic itself. Further information for how the Pi4J library interacts with the hardware can be found here.
This is a pretty easy 3 step process
- Add Pi4J and Pi4K to your project’s dependencies
- Use the new dependencies in your code
- Run your code
Adding Pi4J and Pi4K as Dependencies
Your project is using the Gradle build system, it’s modern and popular (it’s the go to when building Android apps). So let’s open up the build.gradle.kts file, this is the build file of your project, it’s where we configure our project’s build tasks dependencies, etc. Firstly, we have to add Jitpack and sonatype as repositories. (Line 12 and 13 below), then add both Pi4K and Pi4J as dependencies (Line 17 and 18 below).
After making these changes to the build.gradle.kts file, a little elephant with two arrows will appear in the upper right. This is the Load Gradle Changes button, clicking on this will rebuild your project and automatically download and install the new dependencies.
Using the New Dependencies in your Code
Now that we have all the dependencies downloaded, all we have to do is use them. Pi4K is a wrapper library around Pi4J which makes it easier to use with Kotlin. Let’s add some code to our main function which will pulse an LED on the Raspberry Pi’s GPIO1. Like I said before, I won’t get into the Raspberry Pi hardware here, but their are examples for how to wire it up online.
Delete the hello world line from your main.kt and replace it with the following to pulse your LED: digitalOutput(GPIO_01).pulse(1000)
Now if you run it while using your Raspberry Pi Run Configuration, your code should deploy, and run and your LED should blink every second! Nice!
But what if you don’t currently have your Pi, or need to test on your computer? Running the above code directly on your computer results in this error:
Not great, so what are we to do? Are we out of luck? Luckily for us, Pi4J has a “Simulation” mode, which let’s us run the code on our computer, allowing us to test on our computer.
Bonus: Simulating a Raspberry Pi
Simulation mode is great for testing out code and iterating rapidly, without needing a real Raspberry Pi. Be ware though that this mode just mocks up the hardware, so you’ll definitely want to test on a real Raspberry Pi at some point.
To setup simulation mode, all you have to do is define an Environment Variable in your MainKt Run Configuration. To do this, click the Run Configuration drop down near the top right corner of IntelliJ, then click Edit Configurations again. This time we are going to select MainKt on the left side of the new window, and then paste the following in the Environment Variables section: PI4J_PLATFORM=SIMULATED
.
Clicking OK will save the changes, and dismiss this window. Now all you have to do is run your program again using the MainKt run configuration! This time it’ll run on your computer (not the Raspberry Pi) and it won’t crash! If you are using the pulse program from above, it’ll just infinitely run until you stop it (feel free to stop it at any time).
Deploying to the Pi
We’re almost done! We have figured out how to setup the Kotlin dev environment, wrote some code to control the Raspberry Pi, and finally tested out our code by running directly on the Raspberry Pi itself. The only thing left is to actually deploy our code to the Raspberry Pi so we don’t have to always go through IntelliJ to start it.
Creating a Fat Jar (Uber Jar)
To do this we will have to create a “Fat Jar”, or sometimes called an “Uber Jar”. Kotlin and Java code is usually bundled up into a nice and simple file called a Jar. These Jar files are then executed by the JVM, running our programming for us. The only problem is by default, Jar files only really contain the code we wrote and nothing else, so to make a deployable Jar file, we have to bundle our dependencies into our Jar. This process is called “creating a Fat Jar”. This Fat Jar will have everything our program needs to run in one file, so it makes it super easy to deploy. Luckily for us, there’s a Gradle Plugin which makes this really simple called ShadowJar.
Setting up ShadowJar
Like I said, ShadowJar is nice and easy to setup. All you need to do is open your build.gradle.kts file again and add it as one of your plugins. ShadowJar is hosted in the JCenter repository (which is a superset of MavenCentral) so to make our lives simpler, you can just replace mavencentral with jcenter (Line 12 below). Then all you have to do is add ShadowJar to your plugins (Line 6 below), and click the Gradle sync button.
Actually Creating your Fat Jar
After your Gradle sync, you’ll notice nothing has happened, you project looks the same. There is one difference though, ShadowJar has added two new build tasks to your project. The one we are interested in is called shadowJar. Running this new task will do all the work for us and generate a Fat Jar. Now the easiest way to run it in IntelliJ is to open the Gradle panel on the right, and expand all the tasks until you find the shadowJar one.
Double clicking on this task will run it, and generate our Fat Jar. It will be created in the Project_NAME > build > libs folder.
Now all we have to do is get this jar file onto the Raspberry Pi.
Deploying your Fat Jar
To copy your new Fat Jar over the the Raspberry Pi, you use the scp
command from your terminal, or a file transfer program of your choice.
Running your Fat Jar
Running your program is simple, once you have the Fat Jar on the Raspberry Pi. You just need to SSH into your Raspberry Pi, and navigate to wherever you copied your Fat Jar to. Then you just need to run the following: java -jar NAME_OF_FAT_JAR.jar
This will start your Kotlin program! To stop, either you can disconnect your SSH session or press ctrl + c
.
Since this post is already long, I don’t want to get deep into it, but if you want to have a long running program, you can use tmux or screen to create different terminal sessions that will persist even after you disconnect your SSH session.
Done
Congratulations! You now know how to write and deploy Kotlin code to a Raspberry Pi! Please let me know if this was helpful to you!