Construct 3 and Arduino UNO Communication

6

Stats

782 visits, 985 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Published on 26 Feb, 2024. Last updated 28 May, 2024

YOU CAN FIND ALL THE TUTORIAL FILES ALREADY DONE HERE! https://drive.google.com/drive/folders/1rsX0B4-FVEz7sqbKhTE4KWZDgFgdbHJM?usp=sharing

If you are like me two weeks ago, you're probably wondering how to connect your Arduino UNO to Construct 3, to turn on LEDs or use any Arduino element with Construct as a controller.

There are multiple ways that allow you to do this, but I didn't quite manage to make any of them work.

Here's the one that worked for me (and the easiest!).

The basics:

SENDING A MESSAGE TO ARDUINO

Construct 3 sends an instruction using WebSocket to the Node.js server > Node.js server "translates" it into a serial port input > Arduino receives the serial port input.

The Tutorial:

In this tutorial, we will create a Construct 3 project that allows us to send a signal to the Arduino to turn on an LED, and use an Arduino button as a trigger for code in Construct 3. This tutorial assumes you have a basic understanding of Arduino coding and electronics.

We will begin by connecting a button to pin 2 and an LED to pin 13.

Once the electronics setup is complete, we can proceed.

We will start by creating a Node.js server. Begin by visiting https://nodejs.org/en and downloading/installing the latest version.

Once this is done, create a folder for your server and open CMD on your computer.

Use "cd" to navigate through folders with CMD. If you're unfamiliar with how to do this, here's a simple tutorial made by Russell Thackston: https://www.youtube.com/watch?v=9zMWXD-xoxc&ab_channel=RussellThackston

Once you've located the folder you created previously, type the following commands.

(One by one, and wait until the command is done to input the next one)

npm init -y

npm install serialport

npm install express

npm install ws

type nul > server.js

Once this is done, if no errors are encountered, you should be able to see new files in your folder!

Open now server.js using notepad or whatever program you use.

Paste the following code (THIS HAS BEEN UPDATED TO ALLOW THE PROGRAM TO INSTANTLY DETECT WHICH PORT USES ARDUINO UNO!):

const { SerialPort } = require('serialport');
const { ReadlineParser } = require('@serialport/parser-readline');
const { Server } = require('ws');

async function findArduinoPort() {
  try {
    const ports = await SerialPort.list();
    if (ports.length === 0) {
      throw new Error('No serial ports found');
    }
    
    for (const port of ports) {
      console.log(port); // Log the ports to see their details
      if (port.manufacturer && (port.manufacturer.includes('Arduino') || port.manufacturer.includes('wch.cn'))) {
        return port.path;
      }
    }
    throw new Error('Arduino not found');
  } catch (error) {
    console.error('Error listing ports:', error);
  }
}

function startServer(portPath) {
  const port = new SerialPort({ path: portPath, baudRate: 9600 });

  port.on('open', () => {
    console.log('Serial Port Opened');
  });

  port.on('error', function(err) {
    console.log('Error: ', err.message);
  });

  // The ReadlineParser will emit data once a newline is received
  const parser = port.pipe(new ReadlineParser());

  // Set up WebSocket server
  const wss = new Server({ port: 8080 });

  wss.on('connection', function connection(ws) {
    console.log('A client connected');

    // When a WebSocket message is received
    ws.on('message', function incoming(message) {
      console.log('received from WebSocket client: %s', message);

      // Write to the Arduino serial port with a newline
      port.write(message + '\n', function(err) {
        if (err) {
          return console.log('Error on write: ', err.message);
        }
        console.log('message written to Arduino');
      });
    });

    // When data is received from the Arduino, send it to the WebSocket client
    parser.on('data', function(data) {
      console.log('received from Arduino: ', data);
      ws.send(data);
    });
  });

  wss.on('error', function(err) {
    console.log('WebSocket Server Error: ', err.message);
  });

  console.log('WebSocket server started on ws://localhost:8080');
}

// Keep the script running
function keepAlive() {
  setTimeout(keepAlive, 1000);
}

(async () => {
  try {
    const arduinoPortPath = await findArduinoPort();
    if (arduinoPortPath) {
      console.log('Arduino found on port:', arduinoPortPath);
      startServer(arduinoPortPath);
    } else {
      console.log('Arduino not found');
    }
  } catch (error) {
    console.error('Failed to find Arduino port:', error);
    // Retry after a delay
    setTimeout(() => {
      (async () => {
        try {
          const arduinoPortPath = await findArduinoPort();
          if (arduinoPortPath) {
            startServer(arduinoPortPath);
          }
        } catch (error) {
          console.error('Retry failed: ', error);
        }
      })();
    }, 5000); // Retry every 5 seconds
  }
  
  // Start the keep-alive loop
  keepAlive();
})();

Once this is done, you can close the programm.

Create now a new file named "RUNSERVER.cmd" on the same folder. Inside this file input the following command and close it: "node server.js" (without the ")

This will allow you to open the server just clicking on this file and not loading it on cmd.

Now if you open the file it should say something like "WebSocket server started on..."

This means everything is working.

Now open Arduino IDE. In here, the code will change for everyone but for using only leds and buttons, just paste this code right here:

const int buttonPin = 2; // Pin number for the button
const int ledPin = 13; // Most Arduinos have an LED on pin 13
int lastButtonState = HIGH; // the previous state of the button
int currentButtonState; // the current state of the button

void setup() {
 pinMode(buttonPin, INPUT_PULLUP); // Initialize the button pin as an input with an internal pull-up resistor
 pinMode(ledPin, OUTPUT); // Initialize the LED pin as an output
 Serial.begin(9600); // Start serial communication at 9600 baud rate
}

void loop() {
 currentButtonState = digitalRead(buttonPin); // read the button state

 // compare the button state to its previous state
 if (currentButtonState != lastButtonState) {
 // if the state has changed, increment the counter
 if (currentButtonState == LOW) {
 // if the current state is LOW then the button went from off to on:
 Serial.println("Button pressed");
 }
 // Delay a little bit to avoid bouncing
 delay(10);
 }
 // save the current state as the last state, for next time through the loop
 lastButtonState = currentButtonState;

 if (Serial.available() > 0) {
 String command = Serial.readStringUntil('\n'); // Read the incoming data as a string until a newline character is found
 if (command == "LED ON") {
 digitalWrite(ledPin, HIGH); // Turn on the LED
 } else if (command == "LED OFF") {
 digitalWrite(ledPin, LOW); // Turn off the LED
 }
 }
}

Once finished, send the code to your Arduino. IMPORTANT, You now need to close Arduino IDE, if two programs are reading from the serial it doesn't work.

Now on construct it's really easy. Start by adding a Button or some type of player input, and the WebSocket Object.

Here's the basic code:

In this code, the user must click on the button to connect to the WebSocket server. This step is crucial because a connection always requires user interaction. When the button is clicked, the Arduino sends a message to the server. Upon receiving a message, it updates a variable to the name of the WebSocket text sent by the Arduino.

It's important to "trim" this received text because, without this step, it WILL NOT WORK. Once this command is received, the button can be programmed to perform any desired action.

How do we activate the LEDs now? Simply add an action to send WebSocket text. In this specific case, use "Open LED" or "Close LED" to control the LEDs.

EXAMPLE:

That's it! I'm sure there's infinetly easier ways of doing it, but this is the one i managed to make it work. Hopefully this tutorial will help people have less headaches on the future, and happy programming!

  • 11 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • Coool! Thank you very much for sharing!

  • Hey, it's so lovely that you have put a tutorial for us! Thanks for that! I'm very new for all this, but I want to make a auto watering system, and by CS3 I want to make the UI for it. Is this will be possible? The changes I will have to make is to add more things in server and then in CS use "send text"/"receive text"?

    • Yeah this is very easy to do just by changing the basics. On the server .js you dont need to change anything. You just need to change ur Arduino code. If you need help, chatgpt does a great job at It. Im glad u like It if you need anything feel free to ask!

  • Very well explained and it totally works. You are awesome for sharing it free!

  • I can't get pas the part where you create a new file after adding the first set of code into server.js file. I tried creating a .js file, a cmd file, and a text document all with the line "node server.js" I get nothing with the cmd, and I get an error line 1 character 6 for the other 2 files.