arrow-left

All pages
gitbookPowered by GitBook
1 of 7

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Battery LED w/ Teensy LC

[WIP]

hashtag
Introduction

This "Project Guide" is written to show some of the capabilites of NavQ. In conjunction with a Teensy LC and a strip of WS2812B LEDs, you can add a forward-facing battery indicator light to your drone.

The battery on my drone is quite low!

hashtag
Prerequisites

hashtag
Software

The software needed to run this project on your NavQ is as follows:

  1. ROS Noetic

  2. MAVROS

You can install this software using the guides here:

hashtag
Hardware

The hardware needed is the same as the hardware from the I2C guide here:

hashtag
Code

At the moment, we're just going to paste the code here, and a more detailed guide will be written later.

hashtag
Teensy code

This code should be uploaded to the Teensy using the Arduino IDE.

hashtag
NavQ code

The ROS node should be placed in the home folder ('/home/navq/')

The service file should be located in /etc/systemd/system/.

The Launch script should be located in /usr/local/bin/.

hashtag
Making the ROS node run on boot

Once all of the necessary files are placed in their respective directories, you need to make the systemd service run at boot. To do this, run in the terminal:

ROS1chevron-right
Controlling your drone from NavQ using MAVROSchevron-right
I2Cchevron-right
file-archive
789B
batt_led.zip
archive
arrow-up-right-from-squareOpen
Teensy batt_led code
file-download
951B
batt_led.py
arrow-up-right-from-squareOpen
ROS node
file-download
157B
batt_led.service
arrow-up-right-from-squareOpen
"systemd" service file
file-download
223B
batt_led.sh
arrow-up-right-from-squareOpen
Launch script

PWM (Onboard RGB LED)

hashtag
Controlling PWM on NavQ

The PWM chips are tied to the onboard LED on NavQ. There are three PWM chips: pwmchip0, pwmchip1, and pwmchip2. Each of these "chips" have one PWM line attached to them: pwm0. To use these PWM lines, you will need to use the sysfs interface.

hashtag
Using the sysfs interface to control the onboard LED

circle-info

Currently, you must be root to access these PWM chips. In the future we will use a udev rules file to change the permissions. This will allow the navq user to write to the psuedofiles for these chips.

hashtag
Step 1

Log into the root user on NavQ by running this command:

hashtag
Step 2

Navigate to /sys/class/pwm and run the following commands:

hashtag
Step 3

Now that our PWM lines are exported for each chip, we can change the duty cycle of the PWM lines and enable them. The default frequency is 2730667 Hz. For a 50% duty cycle, we will use half of this number: 1365333. Apply this duty cycle to each chip by running the following commands:

hashtag
Step 4

We will now enable each line. The colors for each chip are as follows:

pwmchip0: RED

pwmchip1: GREEN

pwmchip2: BLUE

To enable the colors, run the following commands:

Running these commands in succession should enable the LEDs in a RED, GREEN, BLUE pattern until you reach a white LED.

hashtag
Controlling the onboard LEDs programmatically

circle-info

Comnig soon

$ sudo systemctl enable batt_led
$ sudo su -
<enter password>
$ echo 0 > pwmchip0/export
$ echo 0 > pwmchip1/export
$ echo 0 > pwmchip2/export
$ echo 1365333 > pwmchip0/pwm0/duty_cycle
$ echo 1365333 > pwmchip1/pwm0/duty_cycle
$ echo 1365333 > pwmchip2/pwm0/duty_cycle
$ echo 1 > pwmchip0/pwm0/enable
$ echo 1 > pwmchip1/pwm0/enable
$ echo 1 > pwmchip2/pwm0/enable

Communications Interfaces

There are many communications interfaces supported on NavQ through the JST-GH connectors on the HoverGames Interposer Board. The page links below are guides for each one

GPIOchevron-right
SPIchevron-right
I2Cchevron-right
CANchevron-right

SPI

[Work In Progress]

hashtag
SPI userspace driver

In the October Demo image, we have enabled SPI in the kernel to allow HoverGames participants to communicate with SPI devices. The October Demo image will be released soon.

circle-info

This page is a work in progress.

CAN

[WIP] A guide on communicating over CAN/SLCAN using NavQ and UCANS32K146

hashtag
Introduction

If you're thinking about using the CAN protocol on your drone, this guide will walk you through using our UCANS32K146 to create a CAN interface.

Since there isn't a native CAN bus on the NavQ, we can use a protocol called SLCAN to communicate CAN messages across a UART connection. We have built a binary for the UCANS32K146 that acts as an SLCAN transfer layer. This means that we can add a CAN bus to NavQ by just connecting the UCANS32K146 to the UART3 port.

Diagram of setup

hashtag
Setting up SLCAN on NavQ

circle-info

SLCAN support is enabled in the October image coming out this month.

To enable SLCAN on NavQ, run these commands:

Now you can use SocketCAN or python-can to send and recieve CAN messages over the slcan0 interface. As an example, here is how to send a CAN message from the command line:

hashtag
Flashing your UCANS32K146 with the SLCAN conversion binary

circle-info

This binary is not yet available. This page will be updated with a link to the binary when it is ready.

Follow the guide at the link below to flash the SLCAN binary to your UCAN board:

I2C

A comprehensive guide on using the NavQ as an I2C master (work in progress)

hashtag
I2C Example

The NavQ includes an I2C port in one of the JST-GH connectors. You may use this port to communicate to other devices in your drone system. In this example, we will go over the process of connecting a Teensy LC to the NavQ over I2C to control some WS2812 LEDs.

hashtag
TODO

  1. Add guide for using C/Python SMBus libraries for controlling I2C

  2. Add more pictures/visuals

  3. Explain teensy code

hashtag
Prerequisites

hashtag
Hardware

  1. Teensy LC

  2. NeoPixel LED Strip (Ex. )

  3. JST-GH connectors and pre-terminated wires

hashtag
Software

  1. Teensy side

    1. Arduino IDE

    2. TeensyDuino

hashtag
Preparing the JST-GH connector

To create the I2C connector, you'll need to order some JST-GH hardware. Here is a link to a digikey page where you can purchase connectors:

And here is a page where you can purchase the jumpers:

circle-info

NOTE: For the I2C connector, you'll need the 9-pin JST-GH connector.

In the hardware overview (link here: ), you can see the pinout for the I2C connector. Here is another screenshot of it:

The 5VP pin is on the left-most side of the connector, and GND is on the right-most side. I2C2_SDA is pin 4, and I2C2_SCL is pin 5. The JST-GH connector is positioned with the retention clip facing away from you when you are determining the left/right sides.

hashtag
Wiring the Teensy

You'll need to do some soldering for the first step in this project. In the two pictures below, the NeoPixels are connected to the LED 5V, LED GND, and LED SIG pins. The JST-GH connector to the NavQ connects to the SDA/SCL pins and 5V + GND pads on the back of the Teensy.

circle-info

Tip: you can solder the pre-terminated JST-GH wires directly to the pads and the through-hole pins to make things easier.

One thing to keep in mind is that even though the Teensy LC does not include pullup resistors to 3.3v for the I2C lines, pullups are not required since the NavQ has internal 4.7k pullups on it's own I2C bus (on the SoM).

hashtag
Pictures

Here are a couples images of this setup:

hashtag
Teensy code

We have written some simple example code that changes the color of the NeoPixel LEDs when the Teensy recieves I2C data. In the example below, the slave address of the Teensy is 0x29, and the color of the LEDs change from green to white when a 0x1 byte is sent to the Teensy. If any other byte is sent to the Teensy, the color changes back to green.

circle-info

Make sure that you install the Adafruit_NeoPixel library in the Arduino IDE.

circle-info

The i2c_t3 library is included with the TeensyDuino software. Make sure to use "Wire1" instead of "Wire" since we are using the SDA1/SCLK1 pins on the Teensy.

hashtag
NavQ commands

hashtag
Add navq user to i2c group

To use the i2c commands without root, you'll need to add the navq user to the i2c group. To do this, you can run the following command:

hashtag
Checking connection

Once your Teensy is connected using the I2C JST-GH connector, you need to confirm that the NavQ recognizes the Teensy as an I2C device. To do this, you can run the following command on the NavQ:

You should see a device at address 0x29. If there is no device at address 0x29, you'll need to check your wiring.

hashtag
Sending data to the Teensy

To send data to the Teensy, you can use the following command:

This will change the LEDs to white. You can swap the 0x1 with a 0x0 or any other byte to switch back to green.

hashtag
Controlling I2C bus with Python/C

Controlling the I2C bus with console commands is great, but what about when we want to integrate those commands into code? Well, with Python and C, we can control the Teensy over I2C by using some libraries supplied in both the Linux kernel and through pip.

hashtag
Python

First, you'll need to install the smbus pip package. To do this, just run in your terminal:

Once that is installed, you can run a simple script to select a 1 or 0 to send to the NavQ to change the color of the LEDs.

The expected output of this script is as follows:

By selecting 1 or 0, you can change the color of the LEDs to white or green.

hashtag
C

To control the I2C bus with C, you can use the following code:

$ sudo modprobe slcan
$ sudo slcand -o -t sw -s8 /dev/ttymxc2 -S 115200
$ sudo ip link set up slcan0
$ cansend slcan0 123#deadbeef
etc
Headers
  • Soldering kit

  • NavQ side
    1. i2c-tools (installable from apt)

    https://www.amazon.com/WS2812-Channel-Color-Driven-Development-Arduino/dp/B081BBF4R3/ref=sr_1_48?dchild=1&keywords=neopixel+led+strip&qid=1599144002&sr=8-48arrow-up-right
    Hardware Overview
    I2C JST-GH connector
    You can clearly see the soldering on the top of the teensy - SDA/SCL, and LED headers.
    Wire run from Teensy to NavQ
    #include <Adafruit_NeoPixel.h>
    #include <i2c_t3.h>
    
    // MACROS
    #ifdef __AVR__
      #include <avr/power.h>
    #endif
    #define PIN       17
    #define NUMPIXELS 8
    #define DELAYVAL 50
    
    #define SLAVE_ADDRESS 0x29
    
    // INIT PIXELS
    Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
    void receiveEvent(size_t bytes);
    void requestEvent(void);
    
    // MEMORY
    #define MEM_LEN 256
    char databuf[MEM_LEN];
    volatile uint8_t received;
    
    // INIT VARS
    bool latch = false;
    bool color = false;
    
    // SETUP I2C AND PIXELS
    void setup() 
    {
      Wire1.begin(I2C_SLAVE, 0x29, I2C_PINS_22_23, I2C_PULLUP_EXT, 400000);
      received = 0;
      memset(databuf, 0, sizeof(databuf));
      Wire1.onReceive(receiveEvent);
      Wire1.onRequest(requestEvent);
      Serial.begin(9600);
    #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
      clock_prescale_set(clock_div_1)
    #endif
      pixels.begin();
    }
    
    // LOOP
    void loop() 
    {
      latch = !latch;
      for(int i=0; i<NUMPIXELS; i++) 
      {
        if(color)
        {
          if(latch)
            pixels.setPixelColor(i, pixels.Color(5,5,5));
          else
            pixels.setPixelColor(i, pixels.Color(15,15,15));
        }
        else
        {
          if(latch)
            pixels.setPixelColor(i, pixels.Color(0,5,0));
          else
            pixels.setPixelColor(i, pixels.Color(0,15,0));
        }
    
        pixels.show();
        delay(DELAYVAL);
        //Serial.println("loop..");
      }
    }
    
    // I2C DATA RECV CALLBACK
    void receiveEvent(size_t bytes)
    {
      Wire1.read(databuf, bytes);
      if(databuf[0] == 1) color = true;
      else color = false;
      Serial.println(databuf[0]);
      received = bytes;
      Serial.println("recv");
    }
    
    void requestEvent(void)
    {
      Wire1.write(databuf, MEM_LEN);
      Serial.println("req..");
    }
    $ sudo usermod -aG i2c $USER
    $ sudo su
    $ echo 'KERNEL=="i2c-[0-9]*", GROUP="i2c"' >> /etc/udev/rules.d/10-local_i2c_group.rules
    $ i2cdetect -y 1
    $ i2cset -y 1 0x29 0x1
    $ pip3 install smbus
    from smbus import SMBus
    
    addr = 0x29
    bus = SMBus(1)
    
    numb = 1
    
    print("Enter 1 for WHITE or 0 for GREEN")
    while(numb == 1):
        ledstate = input(">>>>   ")
    
        if(ledstate == "1"):
            bus.write_byte(addr, 0x1)
        elif(ledstate == "0"):
            bus.write_byte(addr, 0x0)
        else:
            numb = 0
    navq@imx8mmnavq:~$ python3 i2c.py
    Enter 1 for WHITE or 0 for GREEN
    >>>>   1
    >>>>   0
    #include <linux/i2c-dev.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <fcntl.h>
    
    int main() {
            // Init vars - file descriptor and I2C slave address
            int file;
            int addr = 0x29;
            char filename[20];
    
            // Open the /dev/i2c-1 device filename and apply the address using ioctl
            sprintf(filename, "/dev/i2c-1");
            file = open(filename, O_RDWR);
            if(file < 0) {
                    printf("Failed to open the i2c bus");
                    exit(1);
            }
            if(ioctl(file, I2C_SLAVE, addr) < 0) {
                    printf("Failed to acquire bus access and/or talk to slave.\n");
                    exit(1);
            }
            
            // Create a data buffer, then ask the user for a 0 or 1 to change LED color
            // LED color is changed by writing buf to file
            char buf[10] = {0};
            buf[0] = 0x0;
            while(1==1){
                    printf("Enter a 0 for GREEN and a 1 for WHITE: ");
                    scanf("%X", &buf[0]);
                    if(write(file,buf,1) != 1) {
                            printf("Failed to write to the i2c bus.\n");
                    }
                    printf("\n");
            }
    }
    

    GPIO

    hashtag
    Controlling GPIO through the command line

    There are several GPIO pins on the various JST-GH connectors on NavQ. To control these GPIO pins, follow the instructions below.

    hashtag
    Exporting GPIO pins

    In order to use GPIO pins, we need to export them in Linux first. To do this, we need to know the GPIO number for the pin we want to access. We can compute this number using the following formula:

    For example, if we want to access the GPIO1_IO12 pin on the UART4/I2C/GPIO connector, we would find that the GPIO number is:

    If you want to find out what pins correspond to what GPIO numbers, we have tables in the Hardware Overview/Pinouts and Connector info section here:

    Once you know the GPIO number of the pin you want to access, exporting the pin for use is easy. All you have to do is echo the pin number to /sys/class/gpio/export. For example, if we were to export GPIO1_IO12, we would run the following in our NavQ console:

    circle-exclamation

    Currently we have not created a specific user group to control GPIO pins, so you must be root to export/control pins. If someone in the community would like to submit a process for greating a GPIO user group, please make a post on our hackster.io page and we will add it to the demo image. :)

    hashtag
    Changing the pin direction

    Next, we will want to change the direction of the GPIO pin for our specific use case. There are two options: in and out. To do this for GPIO1_IO12, you can run the following in your NavQ console:

    hashtag
    Reading or Writing the GPIO pin value

    To read or write a value to the GPIO pin, we will follow a similar process to changing the pin direction. A pseudo file named value is created at /sys/class/gpio/gpioXXX/value that holds a 1 or a 0. If you echoed out to the GPIO direction file, you can control the pin. To control the GPIO1_IO12 pin, just run the following in your NavQ console:

    If you echoed in to the GPIO direction file, you can read the value file and find the current state of the pin. To do this for the GPIO1_IO12 pin, you can run the following in your NavQ console:

    hashtag
    Controlling GPIO programmatically (in C)

    hashtag
    Prerequisites

    1. Create new group called gpio

    2. Create new udev rules file

    Create a file at /etc/udev/rules.d/99-gpio.rules and add the following to it:

    This will allow you to access the GPIO pseudofiles without being root.

    hashtag
    Source Code

    circle-info

    Source code coming soon

    Pinouts and Connector infochevron-right
    gpio_number = ((gpio_bank - 1) * 32) + gpio_pin
    gpio_number = ((1 - 1) * 32) + 12
    gpio_number = (0) + 12
    gpio_number = 12
    $ sudo echo 12 > /sys/class/gpio/export
    $ sudo echo in > /sys/class/gpio/gpio12/direction
    $ sudo echo out > /sys/class/gpio/gpio12/direction
    $ sudo echo 0 > /sys/class/gpio/gpio12/value
    $ sudo echo 1 > /sys/class/gpio/gpio12/value
    $ sudo cat /sys/class/gpio/gpio12/value
    // a 0 or a 1 should be printed to your console
    $ sudo groupadd gpio
    $ sudo usermod -aG gpio navq
    SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"
    SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"
    FMUK66 Vehicle Controller | NXP Mobile Roboticsnxp.gitbook.iochevron-right
    Electronic Components | DigiKey ElectronicsDigiKey Electronicschevron-right
    Electronic Components | DigiKey ElectronicsDigiKey Electronicschevron-right
    Logo
    Logo
    Logo