Some days ago I have shared some experiments I have recently done with Qwik and Arduino on my LinkedIn and Twitter profiles.
A lot of people asked me more details about it, so I wrote this article to explain what I did.
Anyway, as the post title suggests, we can control Arduino, Raspberry and other micro-controllers directly from a front-end application built in JavaScript 😱.
Johnny Five
Some times ago I have played with johnny-five, a JavaScript Robotics & IoT platform.
In short words, we can communicate with our Arduino or Raspberry by using JavaScript with a very friendly syntax.
For example, to blink a LED you can :
1) Connect a LED to PIN 13 of your Arduino board:
2) Create a JavaScript module, i.e. index.js
:
const { Board, Led } = require("johnny-five");
// connect your board
const board = new Board();
// when board is ready
board.on("ready", () => {
// Create a standard `led` component instance
const led = new Led(13);
// "blink" the led in 500ms
// on-off phase periods
led.blink(500);
});
3) Run the code in your terminal
node index.js
I have used Node v.18
Here you can find more details about the installation of Johnny Five and how the previous example works:
• Johnny Five Get Started
• Johnny Five Examples
Qwik
Qwik is a full-stack web framework to create super-performing and SEO friendly applications.
One of its most interesting features is the server$
functions, that allow you to create a function that is always executed on the server.
server$ is a form of RPC (Remote Procedure Call) mechanism between the client and server, just like a traditional HTTP endpoint but strongly typed thanks to Typescript, and easier to maintain.
Source: Qwik server$ Documentation
Following I show you a very basic example of server$
function:
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
// executed on server
const serverGreeter = server$((firstName: string) => {
const greeting = `Hello ${firstName}`;
return greeting;
});
export default component$(() => {
// Signal to contains the input value
const text = useSignal('');
return (
<>
<label>
Your Name:
<input bind:value={text} />
</label>
<button
onClick$={async () => {
// invoke the server$ function
// passing the input text value
// when button is clicked
const greeting = await serverGreeter(text.value);
alert(greeting);
}}
>
greet
</button>
</>
);
});
Blink LED with Johnny Five & Qwik
Since the Qwik $server
function always run on server, we can use any package designed to run in a Node.js environment.
So my first thought was:
maybe I can use Johnny Five directly on Qwik to control my Arduino
And yes, it worked! 😍
Let me show you how I did:
1) First, connect a LED to PIN 13 of your Arduino Board:
2) Create a new Qwik Project:
# create the project
npm create qwik@latest
# Run the project
npm run dev
This process creates a basic Qwik Project with a couple of routes.
3) Now we can open and update the default route component (routes/index.tsx
):
create a button whose click we invoke the server function
import the "johnnyfive" package, create a Board instance and use its API to define the PIN 13 and blink the connected LED:
// routes/index.tsx
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
import five, { Board, Led } from 'johnny-five'
const board = new five.Board();
const arduinoBlink = server$(() => {
// Define LED PIN
const led = new Led(13);
// Blink
led.blink(555);
});
export default component$(() => {
return (
<>
<button
onClick$={async () => {
// Blink LED
// Invoke the server function
// when button is clicked
await arduinoBlink();
}}
> BLINK LED </button>
</>
);
});
LCD display
Johnny Five allow us to easily use sensors, LCDs, Servo / Motors, Joysticks and several other devices.
For example you can easily write into a LCD display as well:
// Define LCD PINS
const lcd = new five.LCD({ pins: [7, 8, 9, 10, 11, 12] });
// Move the cursors to positio 0,0 and display a text
lcd.cursor(0, 0).print('Hello Qwik!');
So, as you can imagine you can use this snippet of code in a Qwik server$
function as we did to blink the LED.
1) First, we can create a JS module in which we write the functions that contains the logic to communicate with the hardware and that are invoked by the server$
function:
// arduino.server.ts
import { server$ } from '@builder.io/qwik-city';
import five, { Board, Led } from 'johnny-five'
const board = new five.Board();
export const arduinoBlinkFn = () => {
const led = new Led(13);
led.blink(555);
};
export const arduinoLCDFn = server$((
text1: string, text2: string
) => {
// Define LCD PINS
const lcd = new five.LCD({ pins: [7, 8, 9, 10, 11, 12] });
// display text1 in the first line of the display
lcd.cursor(0, 0).print(text1);
// display text2 in the second line
lcd.cursor(1, 0).print(text2);
});
2) Now we can simply create the UI in Qwik using JSX syntax, adding a couple of text inputs and a button to send both texts to the device.
The arduinoLCDFn()
server function is invoked when the button is clicked, passing the values of both text inputs.
// routes/index.tsx
import { component$, useSignal } from '@builder.io/qwik';
import { server$ } from '@builder.io/qwik-city';
import { arduinoBlinkFn, arduinoLCDFn } from '~/arduino.server.utils';
const arduinoBlink = server$(() => {
arduinoBlinkFn()
});
const arduinoLCD = server$((
text1: string, text2: string
) => {
arduinoLCDFn(text1, text2)
});
export default component$(() => {
const textRow1 = useSignal('');
const textRow2 = useSignal('');
return (<>
<button
onClick$={async () => {
await arduinoBlink();
}}
> BLINK LED </button>
<input type="text" bind:value={textRow1} placeholder="row 1" />
<input type="text" bind:value={textRow2} placeholder="row 2" />
<button
onClick$={async () => {
await arduinoLCDFn(textRow1.value, textRow2.value);
}}
> WRITE ON LCD </button>
</>);
});
Here the final result:
Conclusion
Of course it's nothing special but this example demonstrates the simplicity and flexibility with which we can use any JavaScript modules within the server function.
How cool is that?
What do you think?
Top comments (5)
Super nerdy project Fabio, I love that! and I have an Arduino at home, maybe I should give it a try ahah
thank you very much Francesco.
I'm curious to see what you'll invent 😅
I need a tool that makes you code while sleeping.
🤣
TOP level article as usual, thanks