1. Home
  2. Docs
  3. How-To
  4. Connect Hexabitz to Exter...
  5. Connect to a Raspberry Pi Single-Board Computer

Connect to a Raspberry Pi Single-Board Computer

Hexabitz HF1R0x module enables you to seamlessly interface your Hexabitz modules to a Raspberry Pi 3B/3B+/4B single-board computer. Check out the module announcement here. Follow up this step-by-step tutorial to get your modular Raspberry Pi creations up!

Hardware Setup

Take your Hexabitz array and HF1R0 module then solder them together.

You have jumper JP1 and JP2 at position 1 & 2 when your Hexabitz array is soldered at the right-side of HF1R0
or at position 2 & 3 when your hexabitz array is soldered at the left-side of HF1R0 as shown in the picture below:

Software Setup

This tutorial will discuss how to setup a small demo project involving a Raspberry Pi 4, HF1R0 and H01R00. By the end of this article, you will be able to hook up your Hexabitz project to any Raspberry Pi in minutes and explore the numerous possibilities of projects that were not possible before.

  • Before we can proceed further, make sure you have everything you need. We have listed all the items that might be required:
    • Type C USB cable for powering up the Pi 4
    • Raspberry Pi 4
    • Micro SD Card
    • Micro SD Card Adapter
    • A WiFi Router
    • HF1R0 Module
    • H01R0 Modules
    • Power Supply (5V 3A)
    • Soldering Iron, Flux and Soldering Wire
    • A Laptop
  • We need to setup the Raspberry Pi. Follow the instructions in the link below step-by-step. Here is an  introduction to the latest Pi 4: https://projects.raspberrypi.org/en/projects/raspberry-pi-setting-up
  • Download Raspbian Buster Lite.
    For every computer hardware, we need its software (firmware). For Raspberry pi 4, we call this firmware “Raspbian”. Raspbian is the foundation’s official supported operating system. You can download “Raspbian Buster Lite” for this demo over here: https://www.raspberrypi.org/downloads/raspbian/ . The Raspbian Buster Lite image contained in the ZIP archive is over 0.5 GB in size. If you find that the download appears to be corrupt or the file is not unzipping correctly, please try using 7Zip (Windows) or The Unarchiver (Macintosh). Both are free of charge and have been tested to unzip the image correctly.

  • Download balenaEtcher to flash your SD Card:
    You will need to use an image writing tool to install the image you have downloaded on your SD card. balenaEtcher is a graphical SD card writing tool that works on Mac OS, Linux and Windows, and it is the easiest option for most users. balenaEtcher also supports writing images directly from the zip file, without any unzipping required. To write your image with balenaEtcher:
    • Download the latest version of balenaEtcher (https://www.balena.io/etcher/) and install it.
    • Connect an SD card reader with the SD card inside.
    • Open balenaEtcher and select from your hard drive the desired Raspberry Pi .img or .zip file which you want to be written on the SD card.
    • Select the SD card you wish to write your image to.
    • Review your selections and click ‘Flash!’ to begin writing data to the SD card.
    • Configure the WiFi and SSH for your Pi 4:
      To configure the WiFi and SSH for your Pi 4, you need to insert the SD card into your laptop.
      You’ll have to locate the boot directory, on our Mac it’s in /Volumes/boot.
      Create a file in this directory called wpa_supplicant.conf. The file should contain the following details:network={
      ssid=”YOUR_NETWORK_NAME”
      psk=”YOUR_PASSWORD”
      key_mgmt=WPA-PSK
      }

                    For SSH, you need to create an empty file called ssh. In Linux, you can create it using “touch ssh”. In Windows, you can create an                      empty file using notepad and save it under the /Volumes/boot directory

  • Insert the microSD card to Raspberry Pi 4:
    Now it’s time to physically set up your Raspberry Pi.  Flip over Raspberry Pi 4 and locate the microSD card socket underneath. Insert the microSD card carefully. It will only fit in one way around, so if it’s struggling,  flip the microSD card over. Once it’s inserted all the way in, it’s time to start up your Raspberry Pi.

  • Power up
    Plug in your Raspberry Pi power supply by inserting a power Type C USB cable into the Raspberry Pi 4 Type C Connector. You will see a red LED and a green LED blinking. For troubleshooting follow this link: https://elinux.org/R-Pi_Troubleshooting
  • Connecting to Pi
    We don’t need a keyboard or a monitor to access the Pi. We can use ssh to login to Raspberry Pi. You will need putty for Windows 10. Follow the link below:
    https://www.raspberrypi.org/documentation/remote-access/ssh/windows.md Raspberry Pi 4 has following default credentials for ssh:
    username: pi
    password: raspberryType (for Linux or Mac):

    ssh pi@raspberry.local
  • Setting up the build environment
    Follow these commands to prepare the Pi 4 for building your hexabitz libraries and future development

    sudo apt-get update
    
    sudo apt-get install autoconf cmake build-essential git
  • Setting up the Hexabitz module
    After you are done, take your Hexabitz array and unpack HF1R0 module and solder them together. Make sure to connect your Hexabitz array at the right spot as explained in the Hardware Setup section. In this demo, we have jumper JP1 and JP2 at position 1 & 2 and our Hexabitz array is soldered between port 2 and port 3 of HF1R0.
  • Downloading and Installing Pi 4 Hexabitz package
    If you just want to test your modules and don’t want to build latest Hexabitz binaries, then you can install the dpkg package for your Pi module, by following the steps below:

    cd ~
    
    mkdir hexabitz
    
    git clone https://github.com/HexabitzPlatform/HF1R0x-Firmware.git
    
    cd HF1R0x-Firmware/output/pi4
    
    sudo dpkg -i hexabitz-1.5-Linux.deb

    After this, you will have a binary “hexabitz-demo”, “libhexabitz.so.1.5” shared library and Hexabitz header files copied to your /usr/bin, /usr/lib/ and /usr/include folder respectively. You can run the binary using:

    hexabitz-demo
  • Building the Hexabitz latest binaries
    If you have followed the steps above and want to proceed building the latest binaries and shared libraries then follow the steps below:

    cd HF1R0x-Firmware/build
    
    make

    After “make”, you will have a binary “hexabitz-demo” and “libhexabitz.so.1.5” shared library to play around. You can run the binary using: ./hexabitz-demo

    Note:

    The executable demo file can be run by typing ./Hexabitz-demo or ./Hexabitz-demo-H01R0 in terminal. The name of executable output file depends on what it was called in the git branch, and it will appear after you write (make) for compilation process.

  • Building your own Code using Hexabitz development libraries:
    If you have your own example code (test.cpp) and want to build using Hexabitz, then you must have followed the step “Downloading and Installing Pi 4 Hexabitz Package”. To compile your source code:

    g++ --std=c++17 test.cpp -I/usr/include/hexabitz
    
    

Coding Your Own Projects using Our C++ Library!

Hexabitz developers has kept in mind the needs of coders, hobbyists, geeks, and even those who don’t want to code and just want to download and run some projects.

Basically, the HF1R0 is an open source project which enables the community to use the projects that are available off-the-shelf, make your own projects using the library core, or modify the library for your own custom needs and requirements.

The Library has basically two main components:

  1. Service Class (Singleton Class)
  2. Module’s Classes (like H01R0, H08R6)

The few helper classes are:

  1. ProxyModule Class
  2. hstd::Message Class

Let’s Start with Service Class (singleton class). 

  1. static Service *getInstance(void);
    This method enables to access the Service Class. It returns a pointer to itself which can be used to access various public methods of singleton.
  2. int init(const char *pathname);
    int init(const std::string& pathname);
    These are the first things that you need to call whenever you want to use any method.
  3. void setOwn(std::shared_ptr<ProxyModule> module);
    std::shared_ptr<ProxyModule> getOwn(void);
    Using these methods, we register a particular Module class and tell the library which module we’re acting like. 
  4. int send(hstd::Message m);
    int receive(hstd::Message& m, long timeout = -1);
    These methods allow us to send or receive a hstd::Message. The send method returns 0 if it is succesful. Similary, the receive method returns 0 if it has received a valid message or -ETO if timeout values specified in “timeout” argument (in milliseconds) has expired.
  5. int ping(hstd::uid_t destID);
    It sends a ping message to a particular node that has address “destID”.
  6. int Explore(void);
    It is the most  important and complex method of the library. It explores all the nodes in the network and stores all the information in a non-volatile memory.

Now, Lets start building a module class for H01R0. Every module class needs to be inherited from ProxyModule. 

class H01R0: public ProxyModule {

The ProxyModule stores the ID (aka address) and part number of the module. Since this information is common to every module, we have used the Inheritance module of OOPS. In the constructor, we need to initialize these two fields. We have automated these for you as you can see below:

H01R0(void): ProxyModule(BOS::H01R0)
{
   id_ = Service::getInstance()->getIDOfPartNum(getPartNum(), 1);
   std::cout << "ID to BOS::H01R0: " << id_ << std::endl;
}

That’s it. Now we need to define some methods to do some operations. Let’s consider defining a method which will set the RGB LED value of the module.

bool H01R0::setRGB(int red, int green, int blue, int intensity)
{
   hstd::Message msg = hstd::make_message(id_, CODE_H01R0_COLOR);
   msg.getParams().append(static_cast<uint8_t>(1));
   msg.getParams().append(static_cast<uint8_t>(red));
   msg.getParams().append(static_cast<uint8_t>(green));
   msg.getParams().append(static_cast<uint8_t>(blue));
   msg.getParams().append(static_cast<uint8_t>(intensity));
   return send(msg);
}

For this, we need to make an instance of hstd::Message. We can use hstd::make_message() function to automate setting of certain fields of Hexabitz message. 

One of the overload of hstd::make_message() requires us to provide the destination address of the module and code of the message that we want to send. 

After this, we keep on appending the arguments as per specification of our module for CODE_H01R0_COLOR (First byte => 1, Second byte => Red Value (0-255), third, fourth bytes => Green and Blue Value (0-255)  respectively and last bytes => intensity value (again 0-255)).

And then we send the message using send method of our class. The send method of the Module class basically calls the send method of our Service Singleton Class.

Adding New Module Classes

Here’s an example of building another module class for H0FR6 Module.

First, we need to inherit the module from ProxyModule.

We define it on H0FR6.h file

class H0FR6: public ProxyModule {

We need to initialize ID and part number of the module fields for one module or array of modules as you can see below:

H0FR6(void): ProxyModule(BOS::H01R0)
{
  id_ = Service::getInstance()->getIDOfPartNum(getPartNum(), 1);
  std::cout << "ID to BOS:: H0FR6: " << id_ << std::endl;
}
H0FR6(unsigned nth): ProxyModule(BOS::H0FR6)
{
  id_ = Service::getInstance()->getIDOfPartNum(BOS::H0FR6, nth);
  std::cout << "ID to BOS:: H0FR6: " << id_ << std::endl;
}

 Then we need to define some new methods to do some operations of (H0FR60) Module. Let’s consider defining the methods which will enable and disable the Hexabitz Solid State Relay Module (H0FR60).

bool H0FR6::relayon(int timeout)
{
  hstd::Message msg = hstd::make_message(id_, CODE_H0FR6_ON);
  msg.getParams().append(static_cast<uint8_t>(1));
  msg.getParams().append(static_cast<uint8_t>(timeout));
  return send(msg);
}
bool H0FR6::relayoff(void)
{
  hstd::Message msg = hstd::make_message(id_, CODE_H0FR6_OFF);
  msg.getParams().append(static_cast<uint8_t>(1));
  return send(msg);
}

In the first method, we need to make an instance of hstd::Message. We can use hstd::make_message() function to automate setting of certain fields of Hexabitz message.

One of the overloads of hstd::make_message() asks us to provide the destination address of the module and Code of the message that we want to send.

After this, we keep on appending the arguments according to specifications of our module for CODE_H0FR6_ON (First byte => 1, Second byte => time out Value (in Milli Seconds)).

Then we send the message using send method of our class. The send method of the Module class calls the send method of our Service Singleton Class.

In the second method, void can be used in the function’s parameter list to clearly specify that the function takes no actual parameters when called.

In addition, we can define the PWM method to run the module in PWM mode at a specific duty cycle.

bool H0FR6::rpwm(int dutycycle)
{
  hstd::Message msg = hstd::make_message(id_, CODE_H0FR6_PWM);
  msg.getParams().append(static_cast<uint8_t>(1));
  msg.getParams().append(static_cast<uint8_t>(dutycycle));
  return send(msg);
}

Notes:

  1. We define these methods on H0FR6.cpp file after obtaining the code of messages from H0FR60 firmware and defining them.
    #define CODE_H0FR6_ON                           1500
    
    #define CODE_H0FR6_OFF                          1501
    
    #define CODE_H0FR6_TOGGLE                 1502
    
    #define CODE_H0FR6_PWM                       1503
  1. We should go to H0FR6.h file and add the new methods.
    class H0FR6: public ProxyModule {
    
    public:
    
    bool relayon(int timeout);
    
    bool relayoff(void);
    
    bool rpwm(int dutycycle);
  1. If you are coding array of modules. you should declare it as you can see below:
    H0FR6 module2(1);
    
    H0FR6 module2(2);
    
    H0FR6 module3(3);

    When you need to call a method, you can write it as:

    module2.relayon(600);
  1. You need to connect with CLI by putty program and type default array to remove the topology and restore the native firmware when you decide to start a new project.
  2. After executing your code and connecting, if the following message appears:(error faild to parse cache bin), and the process has stopped. This indicates that the explore process didn’t succeed or you need to download a new firmware to the module, and this file will be created automatically.

How can we help?