Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Mirko Denecke
Published © CC BY-SA

Flying BeagleBone Green

BBBmini is a state of the art Linux autopilot / flightcontroller Cape for the BeagleBone. It can be used for Copter, Planes or Rovers.

IntermediateFull instructions provided10 hours15,882

Things used in this project

Hardware components

SeeedStudio BeagleBone Green
BeagleBoard.org SeeedStudio BeagleBone Green
×1
BBBMINI PCB
BBBmini cape PCB
×1
GY-9250
MPU-9250 IMU board
×1
GY-63
MS5611 Baro board
×1
Microchip MCP2562 E/P CAN TRX
CAN transceiver
×1
Seeed Studio Grove - OLED Display 1.12''
BBBmini status display
×1
HC-SR04 ultrasonic rangefinder
Distance measurement
×1
GPS ublox NEO-M8N
GPS with up to 10Hz update rate
×1
Telemetry radio
Telemetry connection between BBBmini and ground computer
×1
Capacitor 100 nF
Capacitor 100 nF
×2
Resistor 10kΩ 0,1%
×2
Resistor 20kΩ 0,1%
×2
Resistor 1k ohm
Resistor 1k ohm
×2
Resistor 2kΩ
×2
Resistor 120Ω
×1
Female Header 8 Position 1 Row (0.1")
Female Header 8 Position 1 Row (0.1")
×3
Male Header 80 Position 2 Row (0.1")
Male Header 80 Position 2 Row (0.1")
×2
Male Header 40 Position 1 Row (0.1")
Male Header 40 Position 1 Row (0.1")
×2
M3 x 6mm Polyamid screw
To mount sensor breakout boards
×10
M3 x 10mm hexa Polyamid spacer
To mount sensor breakout boards
×7
Quadcopter frame
×1
ESC and motor set
4 x ESCs 4 x Motors
×1
Lipo pack 2200mAh
Flight Lipo pack
×1
Lipo charger
It is recommended to buy a better one.
×1
Gemfan 5030 Multirotor ABS Propellers Bulk Pack (10 Pairs)
Propeller
×1
HK Pilot Power VI Module, Distribution Board And Dual UBEC ALL-In-One (120A and 10s)
×1
6 Channel RC Transmitter and receiver
Choose system, depends on your budget. FrSky X9P plus with X8R is tested, but a high budget system. RC receiver must have PPM, S.BUS or spektrum satellit output.
×1

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

BBBmini schematic

PCB top

PCB top view build with Kicad

PCB bottom

PCB bottom view build with Kicad

BBBmini Kicad and Gerber files

This link provide all Kicad source files for the BBBmini it also provides GERBER files which could be send to a PCB manufacturer.

Code

PRU Firmware RC output and RC input

Assembly x86
This is the firmware I have written in assembly for a PRU. It generates 12 channel PWM signals with better than 1us accuracy and variable frequency for each channel. It also can read S.BUS, PPM SUM or spektrum satellite signals with 5ns accuracy.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

 
// RC AllInOnePRU
// 
// 1 channel RCInput with 5ns accuracy
// 12 channel RCOutput with 1us accuracy 

// Timer
#define TICK_PER_US 200
#define TICK_PER_MS 200000

// PWM

// 920 us
#define PWM_PULSE_DEFAULT (920 * TICK_PER_US)

// 50 Hz
#define PWM_FREQ_DEFAULT (20 * TICK_PER_MS)

// Ringbuffer size
#define RCIN_RINGBUFFERSIZE 300

// PRU Constants Table
#define ECAP C3
#define RAM C24
#define IEP C26

// IEP
#define IEP_TMR_GLB_CFG 0x0
#define IEP_TMR_GLB_STS 0x4
#define IEP_TMR_CNT 0xc

#define IEP_CNT_ENABLE 0x0
#define IEP_DEFAULT_INC 0x4

// ECAP
#define ECAP_TSCTR 0x0
#define ECAP_CTRPHS 0x4
#define ECAP_CAP1 0x8
#define ECAP_CAP2 0xc
#define ECAP_CAP3 0x10
#define ECAP_CAP4 0x14
#define ECAP_ECCTL1 0x28
#define ECAP_ECCTL2 0x2a
#define ECAP_ECEINT 0x2c
#define ECAP_ECFLG 0x2e
#define ECAP_ECCLR 0x30
#define ECAP_ECFRC 0x32
#define ECAP_REVID 0x5c

// ECCTL1
#define ECAP_CAP1POL 0
#define ECAP_CTRRST1 1
#define ECAP_CAP2POL 2
#define ECAP_CTRRST2 3
#define ECAP_CAP3POL 4
#define ECAP_CTRRST3 5
#define ECAP_CAP4POL 6
#define ECAP_CTRRST4 7
#define ECAP_CAPLDEN 8
#define ECAP_PRESCALE 9
#define ECAP_FREE_SOFT 14

// ECCTL2
#define ECAP_CONT_ONESHT 0
#define ECAP_STOP_WRAP 1
#define ECAP_RE_ARM 3
#define ECAP_TSCTRSTOP 4
#define ECAP_SYNCI_EN 5
#define ECAP_SYNCO_SEL 6
#define ECAP_SWSYNC 8
#define ECAP_CAP_APWM 9
#define ECAP_APWMPOL 10

// ECEINT, ECFLG
#define ECAP_INT 0
#define ECAP_CEVT1 1
#define ECAP_CEVT2 2
#define ECAP_CEVT3 3
#define ECAP_CEVT4 4
#define ECAP_CNTOVF 5
#define ECAP_PRDEQ 6
#define ECAP_CMPEQ 7

// RAM
#define CH_ENABLE_RAM_OFFSET (0 * 4)
#define CH_1_PULSE_TIME_RAM_OFFSET (1 * 4)
#define CH_1_T_TIME_RAM_OFFSET  (2 * 4)
#define CH_2_PULSE_TIME_RAM_OFFSET (3 * 4)
#define CH_2_T_TIME_RAM_OFFSET  (4 * 4)
#define CH_3_PULSE_TIME_RAM_OFFSET (5 * 4)
#define CH_3_T_TIME_RAM_OFFSET  (6 * 4)
#define CH_4_PULSE_TIME_RAM_OFFSET (7 * 4)
#define CH_4_T_TIME_RAM_OFFSET  (8 * 4)
#define CH_5_PULSE_TIME_RAM_OFFSET (9 * 4)
#define CH_5_T_TIME_RAM_OFFSET  (10 * 4)
#define CH_6_PULSE_TIME_RAM_OFFSET (11 * 4)
#define CH_6_T_TIME_RAM_OFFSET  (12 * 4)
#define CH_7_PULSE_TIME_RAM_OFFSET (13 * 4)
#define CH_7_T_TIME_RAM_OFFSET  (14 * 4)
#define CH_8_PULSE_TIME_RAM_OFFSET (15 * 4)
#define CH_8_T_TIME_RAM_OFFSET  (16 * 4)
#define CH_9_PULSE_TIME_RAM_OFFSET (17 * 4)
#define CH_9_T_TIME_RAM_OFFSET  (18 * 4)
#define CH_10_PULSE_TIME_RAM_OFFSET (19 * 4)
#define CH_10_T_TIME_RAM_OFFSET  (20 * 4)
#define CH_11_PULSE_TIME_RAM_OFFSET (21 * 4)
#define CH_11_T_TIME_RAM_OFFSET  (22 * 4)
#define CH_12_PULSE_TIME_RAM_OFFSET (23 * 4)
#define CH_12_T_TIME_RAM_OFFSET  (24 * 4)

#define MAX_CYCLE_TIME_OFFSET (25 * 4)

#define RCIN_RING_HEAD_OFFSET 0x1000
#define RCIN_RING_TAIL_OFFSET 0x1002
#define RCIN_RINGBUFFER_RAM_OFFSET 0x1004

// RCOut pins
#define RC_CH_1_PIN r30.t10
#define RC_CH_2_PIN r30.t8
#define RC_CH_3_PIN r30.t11
#define RC_CH_4_PIN r30.t9
#define RC_CH_5_PIN r30.t7
#define RC_CH_6_PIN r30.t6
#define RC_CH_7_PIN r30.t5
#define RC_CH_8_PIN r30.t4
#define RC_CH_9_PIN r30.t3
#define RC_CH_10_PIN r30.t2
#define RC_CH_11_PIN r30.t1
#define RC_CH_12_PIN r30.t0

// RCOut enable bits
#define RC_CH_1_ENABLE register.ch_enable.t0
#define RC_CH_2_ENABLE register.ch_enable.t1
#define RC_CH_3_ENABLE register.ch_enable.t2
#define RC_CH_4_ENABLE register.ch_enable.t3
#define RC_CH_5_ENABLE register.ch_enable.t4
#define RC_CH_6_ENABLE register.ch_enable.t5
#define RC_CH_7_ENABLE register.ch_enable.t6
#define RC_CH_8_ENABLE register.ch_enable.t7
#define RC_CH_9_ENABLE register.ch_enable.t8
#define RC_CH_10_ENABLE register.ch_enable.t9
#define RC_CH_11_ENABLE register.ch_enable.t10
#define RC_CH_12_ENABLE register.ch_enable.t11

// Register struct
.struct RegisterStruct
   .u32 ch_enable
   .u32 ch_1_next_time
   .u32 ch_2_next_time
   .u32 ch_3_next_time
   .u32 ch_4_next_time
   .u32 ch_5_next_time
   .u32 ch_6_next_time
   .u32 ch_7_next_time
   .u32 ch_8_next_time
   .u32 ch_9_next_time
   .u32 ch_10_next_time
   .u32 ch_11_next_time
   .u32 ch_12_next_time
   .u32 time
   .u32 time_max 
   .u32 time_cycle
   .u32 rcin_ram_pointer
   .u32 rcin_ram_pointer_index
   .u32 rcin_ram_pointer_index_max
   .u32 rcin_ram_pointer_head
   .u32 rcin_ram_pointer_tail
   .u32 temp
   .u32 temp1
   .u32 test
 .ends
 .assign RegisterStruct, R4, *, register

.macro RCOUT_PWM
.mparam RC_CH_X_PIN, CH_X_NEXT_TIME, CH_X_ENABLE, CH_X_PULSE_TIME_RAM_OFFSET, CH_X_T_TIME_RAM_OFFSET
pwm:
   // Handle arithmetic and counter overflow, check if there is something to do
   sub register.temp, CH_X_NEXT_TIME, register.time
   mov register.temp1, 0xF0000000
   qbgt pwmend, register.temp, register.temp1

      mov CH_X_NEXT_TIME, register.time

      // Set pin or clear pin?
      qbbs pwmclear, RC_CH_X_PIN

         // Load pulse duration
         lbco register.temp, RAM, CH_X_PULSE_TIME_RAM_OFFSET, 4

         // Calculate time to next event
         add CH_X_NEXT_TIME, CH_X_NEXT_TIME, register.temp

         // Check if channel is enabled 
         qbbc pwmend, CH_X_ENABLE
            
            // Set pin
            set RC_CH_X_PIN
         jmp pwmend

      pwmclear:
         // Load pulse time
         lbco register.temp1, RAM, CH_X_PULSE_TIME_RAM_OFFSET, 4

         // Load T time
         lbco register.temp, RAM, CH_X_T_TIME_RAM_OFFSET, 4

         // Calculate time to next event (T - pulse duration)
         sub register.temp, register.temp, register.temp1
         add CH_X_NEXT_TIME, CH_X_NEXT_TIME, register.temp
         
         // Clear pin
         clr RC_CH_X_PIN
pwmend:
.endm

.macro RCIN_ECAP_INIT
   // Initialize ECAP
   mov register.temp, (1 << ECAP_CTRRST1) | (1 << ECAP_CAP1POL) | (1 << ECAP_CTRRST2) | (1 << ECAP_CAPLDEN)
   sbco register.temp, ECAP, ECAP_ECCTL1, 4
   mov register.temp, (1 << ECAP_STOP_WRAP) | (1 << ECAP_TSCTRSTOP) | (2 << ECAP_SYNCO_SEL)
   sbco register.temp, ECAP, ECAP_ECCTL2, 4
.endm

.macro RCIN_ECAP
   // New value?
   lbco register.temp, ECAP, ECAP_ECFLG, 4
   qbbc rcin_ecap_end, register.temp.t2

      // Copy S0 and S1 duration to temp and temp1
      lbco register.temp, ECAP, ECAP_CAP1, 8

      // Copy S0 and S1 duration to RAM
      sbbo register.temp, register.rcin_ram_pointer, 0, 8

      // Clear event flags
      mov register.temp, (1 << ECAP_CEVT1) | (1 << ECAP_CEVT2)
      sbco register.temp, ECAP, ECAP_ECCLR, 4

      // Set new tail value
      RCIN_WRITE_TAIL register.rcin_ram_pointer_index

      // Update pointer
      add register.rcin_ram_pointer_index, register.rcin_ram_pointer_index, 1
      add register.rcin_ram_pointer, register.rcin_ram_pointer, 8

      // Check end of ringbuffer
      qblt rcin_ecap_end, register.rcin_ram_pointer_index_max, register.rcin_ram_pointer_index
         mov register.rcin_ram_pointer, RCIN_RINGBUFFER_RAM_OFFSET 
         mov register.rcin_ram_pointer_index, 0
rcin_ecap_end:
.endm

.macro RCIN_WRITE_HEAD
.mparam RCIN_HEAD
   sbbo RCIN_HEAD, register.rcin_ram_pointer_head, 0, 2
.endm

.macro RCIN_WRITE_TAIL
.mparam RCIN_TAIL
   sbbo RCIN_TAIL, register.rcin_ram_pointer_tail, 0, 2
.endm

.macro MAX_CYCLE_TIME
   lbco register.temp1, IEP, IEP_TMR_CNT, 4
   sub register.temp, register.temp1, register.time_cycle
   mov register.time_cycle, register.temp1
   max register.time_max, register.time_max, register.temp
   sbco register.time_max, RAM, MAX_CYCLE_TIME_OFFSET, 4
.endm

.macro INIT
   // Reset PWM pins
   mov r30, 0x0

   // Clear register
   zero &register, SIZE(register)

   // Initialize max cycle time
   mov register.temp, 0
   sbco register.temp, RAM, MAX_CYCLE_TIME_OFFSET, 4

   // Initialize ringbuffer
   mov register.rcin_ram_pointer, RCIN_RINGBUFFER_RAM_OFFSET
   mov register.rcin_ram_pointer_index_max, RCIN_RINGBUFFERSIZE 
   mov register.rcin_ram_pointer_head, RCIN_RING_HEAD_OFFSET
   mov register.rcin_ram_pointer_tail, RCIN_RING_TAIL_OFFSET
   mov register.temp, 0
   RCIN_WRITE_HEAD register.temp
   RCIN_WRITE_TAIL register.temp

   // Load balancing
   mov register.ch_1_next_time, 1000
   mov register.ch_2_next_time, 2000
   mov register.ch_3_next_time, 3000
   mov register.ch_4_next_time, 4000
   mov register.ch_5_next_time, 5000
   mov register.ch_6_next_time, 6000
   mov register.ch_7_next_time, 7000
   mov register.ch_8_next_time, 8000
   mov register.ch_9_next_time, 9000
   mov register.ch_10_next_time, 10000
   mov register.ch_11_next_time, 11000
   mov register.ch_12_next_time, 12000

   // Disable all PWMs
   mov register.ch_enable, 0x0
   sbco register.ch_enable, RAM, CH_ENABLE_RAM_OFFSET, 4

   // Initialize PWM pulse (920us)
   mov register.temp, PWM_PULSE_DEFAULT
   sbco register.temp, RAM, CH_1_PULSE_TIME_RAM_OFFSET, 4 
   sbco register.temp, RAM, CH_2_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_3_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_4_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_5_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_6_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_7_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_8_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_9_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_10_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_11_PULSE_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_12_PULSE_TIME_RAM_OFFSET, 4

   // Initialize PWM frequency (50Hz)
   mov register.temp, PWM_FREQ_DEFAULT
   sbco register.temp, RAM, CH_1_T_TIME_RAM_OFFSET, 4 
   sbco register.temp, RAM, CH_2_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_3_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_4_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_5_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_6_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_7_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_8_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_9_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_10_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_11_T_TIME_RAM_OFFSET, 4
   sbco register.temp, RAM, CH_12_T_TIME_RAM_OFFSET, 4

   // Initialize counter (1 step = 5ns) 
   mov register.temp, 1 << IEP_DEFAULT_INC
   sbco register.temp, IEP, IEP_TMR_GLB_CFG, 4

   // Reset counter
   mov register.temp, 0xffffffff
   sbco register.temp, IEP, IEP_TMR_CNT, 4

   // Start counter 
   lbco register.temp, IEP, IEP_TMR_GLB_CFG, 4
   or register.temp, register.temp, 1 << IEP_CNT_ENABLE
   sbco register.temp, IEP, IEP_TMR_GLB_CFG, 4
.endm

.origin 0
init:
   INIT
   RCIN_ECAP_INIT
mainloop:
   lbco register.ch_enable, RAM, CH_ENABLE_RAM_OFFSET, 4
   lbco register.time, IEP, IEP_TMR_CNT, 4
   RCOUT_PWM RC_CH_1_PIN, register.ch_1_next_time, RC_CH_1_ENABLE, CH_1_PULSE_TIME_RAM_OFFSET, CH_1_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_2_PIN, register.ch_2_next_time, RC_CH_2_ENABLE, CH_2_PULSE_TIME_RAM_OFFSET, CH_2_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_3_PIN, register.ch_3_next_time, RC_CH_3_ENABLE, CH_3_PULSE_TIME_RAM_OFFSET, CH_3_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_4_PIN, register.ch_4_next_time, RC_CH_4_ENABLE, CH_4_PULSE_TIME_RAM_OFFSET, CH_4_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_5_PIN, register.ch_5_next_time, RC_CH_5_ENABLE, CH_5_PULSE_TIME_RAM_OFFSET, CH_5_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_6_PIN, register.ch_6_next_time, RC_CH_6_ENABLE, CH_6_PULSE_TIME_RAM_OFFSET, CH_6_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_7_PIN, register.ch_7_next_time, RC_CH_7_ENABLE, CH_7_PULSE_TIME_RAM_OFFSET, CH_7_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_8_PIN, register.ch_8_next_time, RC_CH_8_ENABLE, CH_8_PULSE_TIME_RAM_OFFSET, CH_8_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_9_PIN, register.ch_9_next_time, RC_CH_9_ENABLE, CH_9_PULSE_TIME_RAM_OFFSET, CH_9_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_10_PIN, register.ch_10_next_time, RC_CH_10_ENABLE, CH_10_PULSE_TIME_RAM_OFFSET, CH_10_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_11_PIN, register.ch_11_next_time, RC_CH_11_ENABLE, CH_11_PULSE_TIME_RAM_OFFSET, CH_11_T_TIME_RAM_OFFSET
   RCOUT_PWM RC_CH_12_PIN, register.ch_12_next_time, RC_CH_12_ENABLE, CH_12_PULSE_TIME_RAM_OFFSET, CH_12_T_TIME_RAM_OFFSET
   RCIN_ECAP
//   MAX_CYCLE_TIME
jmp mainloop

PRU Firmware HC-SR04 ultrasonic rangefinder

C/C++
This ist the firmware I have written for a PRU in C. It is a hardhware driver for a HC-SR04 ultrasonic rangefinder.
/*
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    HC-SR04 Ultrasonic Distance Sensor by Mirko Denecke <mirkix@gmail.com>

*/

#include <stdint.h>

#include "pru_ctrl.h"

volatile register uint32_t __R30;
volatile register uint32_t __R31;

// Trigger pin
#define TRIGGER 1<<14

// Echo pin
#define ECHO 1<<14

#define TICKS_PER_US 200
#define TICKS_PER_MS (1000 * TICKS_PER_US)

#define TICKS_PER_CM 11600

#define COUNTER_MIN_DISTANCE (2 * TICKS_PER_CM)
#define COUNTER_MAX_DISTANCE (400 * TICKS_PER_CM)

enum RangeFinder_Status {
        RangeFinder_NotConnected = 0,
        RangeFinder_NoData,
        RangeFinder_OutOfRangeLow,
        RangeFinder_OutOfRangeHigh,
        RangeFinder_Good
};

struct range {
    uint32_t distance;
    uint32_t status;
};

#pragma LOCATION(ranger, 0x0)
volatile struct range ranger;

main()
{
    // Init data
    ranger.distance = 0;
    ranger.status = RangeFinder_NoData;

    // Reset trigger
    __R30 &= ~(TRIGGER);

    // Wait 100ms
    __delay_cycles(250 * TICKS_PER_MS);

    // Disable counter
    PRU0_CTRL.CONTROL_bit.CTR_EN = 0;

    // Clear counter
    PRU0_CTRL.CYCLE_bit.CYCLECOUNT = 0xFFFFFFFF;

    while(1)
    {
        // Enable trigger
        __R30 |= TRIGGER;

        // Wait 15us
        __delay_cycles(3000);

        // Reset trigger
        __R30 &= ~(TRIGGER);

        // Wait for echo
        while((__R31 & ECHO) == 0)
        {
            if(PRU0_CTRL.CYCLE_bit.CYCLECOUNT > (600 * TICKS_PER_CM))
            {
                ranger.status = RangeFinder_NoData;
            }
        }

        // Start counter
        PRU0_CTRL.CONTROL_bit.CTR_EN = 1;

        // Count echo length
        while(__R31 & ECHO)
        {
            ;
        }

        // Stop counter
        PRU0_CTRL.CONTROL_bit.CTR_EN = 0;

        // Check status
        if(PRU0_CTRL.CYCLE_bit.CYCLECOUNT < COUNTER_MIN_DISTANCE)
        {
            ranger.distance = 0;

            // Set status out of range low
            ranger.status = RangeFinder_OutOfRangeLow;
        }
        else if(PRU0_CTRL.CYCLE_bit.CYCLECOUNT > COUNTER_MAX_DISTANCE)
        {
            ranger.distance = 0;

            // Set stauts
            ranger.status = RangeFinder_OutOfRangeHigh;
        }
        else
        {
            // Calculate distance in cm
            ranger.distance = PRU0_CTRL.CYCLE_bit.CYCLECOUNT / TICKS_PER_CM;

            //  Set status out of range high
            ranger.status = RangeFinder_Good;
        }

        // Clear counter
        PRU0_CTRL.CYCLE_bit.CYCLECOUNT = 0xFFFFFFFF;

        // Wait 20ms
        __delay_cycles(20 * TICKS_PER_MS);
    }
}

BBBmini

Additional information about BBBmini

ArduPilot

BeagelBone PRU development tool

Small tool I have written to load, start, stop PRUs from Linux command line.

Credits

Mirko Denecke

Mirko Denecke

2 projects • 21 followers
Dipl. Ing. (FH) degree in Computer and Electrical Engineering

Comments