Mirko Denecke
Published © GPL3+

Kinetis FlexIO Ultrasonic Radar

360° Ultrasonic Radar for DIY applications, with self written FlexIO driver.

IntermediateFull instructions provided12 hours2,202

Things used in this project

Hardware components

NXP Kinetis FRDM-K82F Board
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×8
NXP 74HC4050
×2
WS2812 8 LED Ring
×1
Prototype PCB 80mm x 120mm
×1
Prototype PCB 50mm x 70mm
×2
Male Header 80 Position 2 Row (0.1")
Male Header 80 Position 2 Row (0.1")
×1
Screw M3x6
×4
Hex Spacer 10mm M3
×4

Software apps and online services

Kinetis Design Studio Version 3.2.0
KSDK 2.0.0

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

LED Ring Spacer

Sensor Spacer

Schematics

Schematic

Code

Main code

C/C++
See also at https://github.com/mirkix/ultrasonicradar
/*
 * Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 *
 **/

#include "fsl_flexio.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_flexio_ws2812.h"
#include "fsl_flexio_hcsr04.h"

/* WS2812 LEDs */
#define LED_180 0
#define LED_225 1
#define LED_270 2
#define LED_315 3
#define LED_0 4
#define LED_45 5
#define LED_90 6
#define LED_135 7

#define NUM_LEDS 8

static uint16_t range[8] = {0};
static struct FLEXIO_WS2812_LED leds[NUM_LEDS];

void updateleds() {
	for(uint8_t i = 0; i < NUM_LEDS; i++) {
		FLEXIO_WS2812_Update(&leds[i]);
	}
	FLEXIO_WS2812_TransmitBuffer();
}

void updaterange() {
	leds[LED_0].b = 255;
	updateleds();
	range[0] = FLEXIO_HCSR_Ping(0, GPIOA, 5);	// 0
	leds[LED_0].b = 0;
	leds[LED_0].r = 255 - (range[0] / 2);
	leds[LED_0].g = range[0] / 2;
	leds[LED_180].b = 255;
	updateleds();
	range[4] = FLEXIO_HCSR_Ping(5, GPIOA, 14);	// 180
	leds[LED_180].b = 0;
	leds[LED_180].r = 255 - (range[4] / 2);
	leds[LED_180].g = range[4] / 2;
	leds[LED_45].b = 255;
	updateleds();
	range[1] = FLEXIO_HCSR_Ping(2, GPIOA, 13);	// 45
	leds[LED_45].b = 0;
	leds[LED_45].r = 255 - (range[1] / 2);
	leds[LED_45].g = range[1] / 2;
	leds[LED_225].b = 255;
	updateleds();
	range[5] = FLEXIO_HCSR_Ping(6, GPIOC, 7);	// 225
	leds[LED_225].b = 0;
	leds[LED_225].r = 255 - (range[5] / 2);
	leds[LED_225].g = range[5] / 2;
	leds[LED_90].b = 255;
	updateleds();
	range[2] = FLEXIO_HCSR_Ping(3, GPIOA, 12);	// 90
	leds[LED_90].b = 0;
	leds[LED_90].r = 255 - (range[2] / 2);
	leds[LED_90].g = range[2] / 2;
	leds[LED_270].b = 255;
	updateleds();
	range[6] = FLEXIO_HCSR_Ping(7, GPIOA, 16);	// 270
	leds[LED_270].b = 0;
	leds[LED_270].r = 255 - (range[6] / 2);
	leds[LED_270].g = range[6] / 2;
	leds[LED_135].b = 255;
	updateleds();
	range[3] = FLEXIO_HCSR_Ping(4, GPIOA, 17);	// 135
	leds[LED_135].b = 0;
	leds[LED_135].r = 255 - (range[3] / 2);
	leds[LED_135].g = range[3] / 2;
	leds[LED_315].b = 255;
	updateleds();
	range[7] = FLEXIO_HCSR_Ping(8, GPIOA, 15);	// 315
	leds[LED_315].b = 0;
	leds[LED_315].r = 255 - (range[7] / 2);
	leds[LED_315].g = range[7] / 2;
	updateleds();
}

int main(void) {
  /* Init board hardware. */
  BOARD_InitPins();
  BOARD_BootClockRUN();
  BOARD_InitDebugConsole();

  for(uint8_t i = 0; i < NUM_LEDS; i++) {
	  leds[i].r = 0;
	  leds[i].g = 0;
	  leds[i].b = 0;
  }

  struct FLEXIO_WS2812_LED led;
  led.r = 0;
  led.g = 0;
  led.b = 0;

  /* Init and enable FlexIO */
  CLOCK_EnableClock(kCLOCK_Flexio0);
  flexio_config_t user_config = {
  .enableFlexio = true,
  .enableInDoze = false,
  .enableInDebug = false,
  .enableFastAccess = false
  };
  FLEXIO_Init(FLEXIO0, &user_config);
  FLEXIO_Enable(FLEXIO0, true);
  FLEXIO_WS2812_Init();

  /* Init GPIOs */
  gpio_pin_config_t config =
  {
     kGPIO_DigitalOutput,
     0,
  };
  GPIO_PinInit(GPIOA, 5U, &config);
  GPIO_WritePinOutput(GPIOA, 5U, 0U);
  GPIO_PinInit(GPIOA, 13U, &config);
  GPIO_WritePinOutput(GPIOA, 13U, 0U);
  GPIO_PinInit(GPIOA, 12U, &config);
  GPIO_WritePinOutput(GPIOA, 12U, 0U);
  GPIO_PinInit(GPIOA, 17U, &config);
  GPIO_WritePinOutput(GPIOA, 17U, 0U);
  GPIO_PinInit(GPIOA, 14U, &config);
  GPIO_WritePinOutput(GPIOA, 14U, 0U);
  GPIO_PinInit(GPIOC, 7U, &config);
  GPIO_WritePinOutput(GPIOC, 7U, 0U);
  GPIO_PinInit(GPIOA, 16U, &config);
  GPIO_WritePinOutput(GPIOA, 16U, 0U);
  GPIO_PinInit(GPIOA, 15U, &config);
  GPIO_WritePinOutput(GPIOA, 15U, 0U);

  while(1) {
	  /* Read serial char */
	  char ch = GETCHAR();

      switch(ch) {

      /* All LEDs red */
      case 'r':
    	  led.r = 255;
    	  led.g = 0;
    	  led.b = 0;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;

      /* All LEDs green */
      case 'g':
    	  led.r = 0;
    	  led.g = 255;
    	  led.b = 0;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;

      /* All LEDs red */
      case 'b':
    	  led.r = 0;
    	  led.g = 0;
    	  led.b = 255;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;

      /* All LEDs off */
      case 'o':
    	  led.r = 0;
    	  led.g = 0;
    	  led.b = 0;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;

      /* Serial test */
      case 's':
    	  PRINTF("Serial test\r\n");
    	  break;

      /* Start measurement */
      case 'p':
    	  updaterange();
    	  PRINTF("%d,%d,%d,%d,%d,%d,%d,%d\r\n", range[0], range[1], range[2], range[3], range[4], range[5], range[6], range[7]);
    	  break;
      }
  }
}

fsl_flexio_ws2812.h HC-SR04 FlexIO Driver

C/C++
FlexIO driver for HC-SR04 ultrasonic rangefinder using two FlexIO Timer and four FlexIO Shifter.
See also at https://github.com/mirkix/ultrasonicradar
#ifndef SOURCE_FSL_FLEXIO_WS2812_H_
#define SOURCE_FSL_FLEXIO_WS2812_H_

#include <stdint.h>

#define FLEXIO_WS2812_BUFFER_SIZE 25

struct FLEXIO_WS2812_LED {
	uint8_t r;
	uint8_t g;
	uint8_t b;
};

void FLEXIO_WS2812_SendByte(uint8_t byte);
void FLEXIO_WS2812_Init();
void FLEXIO_WS2812_TransmitBuffer();
void FLEXIO_WS2812_Update(const struct FLEXIO_WS2812_LED *led);

#endif /* SOURCE_FSL_FLEXIO_WS2812_H_ */

fsl_flexio_hcsr04.c HC-SR04 FlexIO Driver

C/C++
FlexIO driver for HC-SR04 ultrasonic rangefinder using two FlexIO Timer and four FlexIO Shifter.
See also at https://github.com/mirkix/ultrasonicradar
/*
 * fsl_flexio_hcsr04.c
 *
 *  Created on: 29.06.2016
 *      Author: mirko
 */

#include "fsl_flexio_hcsr04.h"

void FLEXIO_HCSR_Init(uint8_t echo) {
	flexio_timer_config_t timerConfig;
	flexio_shifter_config_t shifterConfig;

	memset(&timerConfig, 0, sizeof(timerConfig));
	memset(&shifterConfig, 0, sizeof(shifterConfig));

	/* Timer for capture (128bits)*/
	timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(3);
	timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
	timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
	timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
	timerConfig.pinSelect = 2;
	timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
	timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
	timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
	timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnTriggerInputShiftTriggerInput;
	timerConfig.timerReset = kFLEXIO_TimerResetNever;
	timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompareTriggerLow;
	timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerRisingEdge;
	timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
	timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
	timerConfig.timerCompare = 256U;
	FLEXIO_SetTimerConfig(FLEXIO0, 2, &timerConfig);

	/* Timer shifter (1 tick = 2cm)*/
	timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_PININPUT(echo);
	timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
	timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
	timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
	timerConfig.pinSelect = 2;
	timerConfig.pinPolarity = kFLEXIO_PinActiveHigh;
	timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
	timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
	timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
	timerConfig.timerReset = kFLEXIO_TimerResetOnTimerTriggerRisingEdge;
	timerConfig.timerDisable = kFLEXIO_TimerDisableOnPreTimerDisable;
	timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerRisingEdge;
	timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
	timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
	timerConfig.timerCompare = 6960U;
	FLEXIO_SetTimerConfig(FLEXIO0, 3, &timerConfig);

	/* Shifter bit 96-127 */
	shifterConfig.timerSelect = 2;
	shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
	shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
	shifterConfig.pinSelect = 1;
	shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
	shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
	shifterConfig.inputSource = kFLEXIO_ShifterInputFromNextShifterOutput;
	shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
	shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
	FLEXIO_SetShifterConfig(FLEXIO0, 0, &shifterConfig);

	/* Shifter bit 64-95 */
	shifterConfig.timerSelect = 2;
	shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
	shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
	shifterConfig.pinSelect = 1;
	shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
	shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
	shifterConfig.inputSource = kFLEXIO_ShifterInputFromNextShifterOutput;
	shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
	shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
	FLEXIO_SetShifterConfig(FLEXIO0, 1, &shifterConfig);

	/* Shifter bit 32-63 */
	shifterConfig.timerSelect = 2;
	shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
	shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
	shifterConfig.pinSelect = 1;
	shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
	shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
	shifterConfig.inputSource = kFLEXIO_ShifterInputFromNextShifterOutput;
	shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
	shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
	FLEXIO_SetShifterConfig(FLEXIO0, 2, &shifterConfig);

	/* Shifter bit 0-31 */
	shifterConfig.timerSelect = 2;
	shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnPositive;
	shifterConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
	shifterConfig.pinSelect = echo;
	shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
	shifterConfig.shifterMode = kFLEXIO_ShifterModeReceive;
	shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
	shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
	shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnEnable;
	FLEXIO_SetShifterConfig(FLEXIO0, 3, &shifterConfig);
}

uint16_t FLEXIO_HCSR_Ping(uint8_t echo, GPIO_Type *base, uint32_t pin) {
	volatile uint16_t i = 0;
	/* Set FlexIO echo pin */
	FLEXIO_HCSR_Init(echo);

	/* Create HC-SR04 trigger signal */
	GPIO_WritePinOutput(base, pin, 1U);
	while(i < 200) {
		i++;
	}
	i = 0;
	GPIO_WritePinOutput(base, pin, 0U);

	/* Wait for result*/
	while((FLEXIO_GetShifterStatusFlags(FLEXIO0) & 15) != 15) {
		;
	}

	/* Count bits * 2 = cm */
	return (__builtin_popcount(FLEXIO0->SHIFTBUF[0]) + __builtin_popcount(FLEXIO0->SHIFTBUF[1]) + __builtin_popcount(FLEXIO0->SHIFTBUF[2]) + __builtin_popcount(FLEXIO0->SHIFTBUF[3])) * 2;
}

fsl_flexio_ws2812.h WS2812 FlexIO Driver

C/C++
FlexIO driver for WS2812 LEDs using two FlexIO Timer and one FlexIO Shifter.
See also at https://github.com/mirkix/ultrasonicradar
#ifndef SOURCE_FSL_FLEXIO_WS2812_H_
#define SOURCE_FSL_FLEXIO_WS2812_H_

#include <stdint.h>

#define FLEXIO_WS2812_BUFFER_SIZE 25

struct FLEXIO_WS2812_LED {
	uint8_t r;
	uint8_t g;
	uint8_t b;
};

void FLEXIO_WS2812_SendByte(uint8_t byte);
void FLEXIO_WS2812_Init();
void FLEXIO_WS2812_TransmitBuffer();
void FLEXIO_WS2812_Update(const struct FLEXIO_WS2812_LED *led);

#endif /* SOURCE_FSL_FLEXIO_WS2812_H_ */

fsl_flexio_ws2812.c WS2812 FlexIO Driver

C/C++
FlexIO driver for WS2812 LEDs using two FlexIO Timer and one FlexIO Shifter.
See also at https://github.com/mirkix/ultrasonicradar
/*
 * fsl_flexio_ws2812.c
 *
 *  Created on: 29.06.2016
 *      Author: mirko
 */

#include "fsl_flexio_ws2812.h"
#include "fsl_flexio.h"

static uint8_t flexio_ws2812_bufferindex = 0;
static uint8_t flexio_ws2812_bufferiindex = 0;
static uint32_t flexio_ws2812_buffer[FLEXIO_WS2812_BUFFER_SIZE] = {0};

void FLEXIO_WS2812_Init() {
	flexio_timer_config_t timerConfig;
	flexio_shifter_config_t shifterConfig;

	memset(&timerConfig, 0, sizeof(timerConfig));
	memset(&shifterConfig, 0, sizeof(shifterConfig));

	/* Timer for shifter load */
	timerConfig.triggerSelect = FLEXIO_TIMER_TRIGGER_SEL_TIMn(5);
	timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveLow;
	timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
	timerConfig.pinConfig = kFLEXIO_PinConfigOutput;
	timerConfig.pinSelect = 10;
	timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
	timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
	timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset;
	timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnTriggerInputShiftTriggerInput;
	timerConfig.timerReset = kFLEXIO_TimerResetNever;
	timerConfig.timerDisable = kFLEXIO_TimerDisableOnTimerCompare;
	timerConfig.timerEnable = kFLEXIO_TimerEnableOnTriggerRisingEdge;
	timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
	timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
	timerConfig.timerCompare = 62U;
	FLEXIO_SetTimerConfig(FLEXIO0, 4, &timerConfig);

	/* Timer for shift clock (350ns) */
	timerConfig.triggerSelect = 0;
	timerConfig.triggerPolarity = kFLEXIO_TimerTriggerPolarityActiveHigh;
	timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal;
	timerConfig.pinConfig = kFLEXIO_PinConfigOutputDisabled;
	timerConfig.pinSelect = 10;
	timerConfig.pinPolarity = kFLEXIO_PinActiveLow;
	timerConfig.timerMode = kFLEXIO_TimerModeSingle16Bit;
	timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset;
	timerConfig.timerDecrement = kFLEXIO_TimerDecSrcOnFlexIOClockShiftTimerOutput;
	timerConfig.timerReset = kFLEXIO_TimerResetNever;
	timerConfig.timerDisable = kFLEXIO_TimerDisableNever;
	timerConfig.timerEnable = kFLEXIO_TimerEnabledAlways;
	timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled;
	timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled;
	timerConfig.timerCompare = 20U;
	FLEXIO_SetTimerConfig(FLEXIO0, 5, &timerConfig);

	/* Shifter for WS2812 data */
	shifterConfig.timerSelect = 4;
	shifterConfig.timerPolarity = kFLEXIO_ShifterTimerPolarityOnNegitive;
	shifterConfig.pinConfig = kFLEXIO_PinConfigOutput;
	shifterConfig.pinSelect = 9;
	shifterConfig.pinPolarity = kFLEXIO_PinActiveHigh;
	shifterConfig.shifterMode = kFLEXIO_ShifterModeTransmit;
	shifterConfig.inputSource = kFLEXIO_ShifterInputFromPin;
	shifterConfig.shifterStop = kFLEXIO_ShifterStopBitDisable;
	shifterConfig.shifterStart = kFLEXIO_ShifterStartBitDisabledLoadDataOnShift;
	FLEXIO_SetShifterConfig(FLEXIO0, 7, &shifterConfig);
}

void FLEXIO_WS2812_TransmitBuffer() {
	for(uint8_t i = 0; i < FLEXIO_WS2812_BUFFER_SIZE; i++) {
		/* Check if next 32bit can be transfered */
		while(!(FLEXIO_GetShifterStatusFlags(FLEXIO0) & (1 << 7)))
		{
			;
		}

		/* Transfer local buffer into shift buffer */
		FLEXIO0->SHIFTBUF[7] = flexio_ws2812_buffer[i];

		/* Clear buffer when send */
		flexio_ws2812_buffer[i] = 0U;
	}

	/* Clear index when all bits are send */
	flexio_ws2812_bufferindex = 0;
	flexio_ws2812_bufferiindex = 0;
}

void FLEXIO_WS2812_InsertBuffer(uint8_t value) {
	/* Check if bit is set */
	if(value) {
		/* Insert bit */
		flexio_ws2812_buffer[flexio_ws2812_bufferindex] |= 1 << flexio_ws2812_bufferiindex;
	}
	/* Increase index for bit position */
	flexio_ws2812_bufferiindex++;

	/* If 32bit reached switch to next 32bit buffer */
	if(flexio_ws2812_bufferiindex >= 32) {
		flexio_ws2812_bufferindex++;
		flexio_ws2812_bufferiindex = 0;
	}
}

void FLEXIO_WS2812_SendByte(uint8_t byte) {
	/* WS2812 byte coding, see WS2812 datasheet */
	for(uint8_t i = 0;  i < 8; i++) {
		if(byte & 1 << (7 - i)) {
			FLEXIO_WS2812_InsertBuffer(1);
			FLEXIO_WS2812_InsertBuffer(1);
			FLEXIO_WS2812_InsertBuffer(0);
			FLEXIO_WS2812_InsertBuffer(0);
		} else {
			FLEXIO_WS2812_InsertBuffer(1);
			FLEXIO_WS2812_InsertBuffer(0);
			FLEXIO_WS2812_InsertBuffer(0);
		}
	}
}

void FLEXIO_WS2812_Update(const struct FLEXIO_WS2812_LED *led) {
	/* Send g, r and b byte, see WS2812 datasheet */
	FLEXIO_WS2812_SendByte(led->g);
	FLEXIO_WS2812_SendByte(led->r);
	FLEXIO_WS2812_SendByte(led->b);
}

ultrasonicradar.py

Python
Small Python program to show the radar data.
Start with: python ultrasonicradar.py
See also at https://github.com/mirkix/ultrasonicradar
import numpy as np
import matplotlib.pyplot as plt
import serial

# Open serial interface
ser = serial.Serial('/dev/ttyACM0', 115200)

# 8 bars
N = 8

# Create 8 bars, 45 degrees each
theta = np.linspace(0.0 - (np.pi / 8), 2 * np.pi - (np.pi / 8), N, endpoint=False)

# Result 0cm
radii = [0, 0, 0, 0, 0, 0, 0, 0]
width = np.pi / 4

# Create plot
ax = plt.subplot(111, projection='polar')

while 1:
	# Start measurement
	ser.write(b'p')

	# Read result
	line = ser.readline()

	# Split string into values
	sonicrange = line.split(',')
	for i in xrange(len(sonicrange)):
		radii[i] = float(sonicrange[i])

	# Clear plot
	ax.clear()

	# Create new plot
	ax = plt.subplot(111, projection='polar')
	
	# North up	
	ax.set_theta_zero_location('N')

	# Theta increases in the clockwise direction
	ax.set_theta_direction(-1)

	# Set range 0 to 256 cm	
	ax.set_ylim(0, 256)

	# Create bars for 0, 45, 90, 135, 180, 225, 270, 315 degrees
	ax.bar(theta, radii, width=width, bottom=0.0)
	
	# Wait
	plt.pause(0.01)

	# Draw
	plt.draw()

Main code

C/C++
See also at https://github.com/mirkix/ultrasonicradar
/*
 * Copyright (c) 2013 - 2016, Freescale Semiconductor, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * o Redistributions of source code must retain the above copyright notice, this list
 *   of conditions and the following disclaimer.
 *
 * o Redistributions in binary form must reproduce the above copyright notice, this
 *   list of conditions and the following disclaimer in the documentation and/or
 *   other materials provided with the distribution.
 *
 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
 *   contributors may be used to endorse or promote products derived from this
 *   software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 *
 **/

#include "fsl_flexio.h"
#include "fsl_debug_console.h"
#include "board.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "fsl_flexio_ws2812.h"
#include "fsl_flexio_hcsr04.h"

#define LED_180 0
#define LED_225 1
#define LED_270 2
#define LED_315 3
#define LED_0 4
#define LED_45 5
#define LED_90 6
#define LED_135 7

static uint16_t range[8] = {0};
static struct FLEXIO_WS2812_LED leds[8];

void updateleds() {
	for(uint8_t i = 0; i < 8; i++) {
		FLEXIO_WS2812_Update(&leds[i]);
	}
	FLEXIO_WS2812_TransmitBuffer();
}

void updaterange() {
	leds[LED_0].b = 255;
	updateleds();
	range[0] = FLEXIO_HCSR_Ping(0, GPIOA, 5);	// 0
	leds[LED_0].b = 0;
	leds[LED_0].r = 255 - (range[0] / 2);
	leds[LED_0].g = range[0] / 2;
	leds[LED_180].b = 255;
	updateleds();
	range[4] = FLEXIO_HCSR_Ping(5, GPIOA, 14);	// 180
	leds[LED_180].b = 0;
	leds[LED_180].r = 255 - (range[4] / 2);
	leds[LED_180].g = range[4] / 2;
	leds[LED_45].b = 255;
	updateleds();
	range[1] = FLEXIO_HCSR_Ping(2, GPIOA, 13);	// 45
	leds[LED_45].b = 0;
	leds[LED_45].r = 255 - (range[1] / 2);
	leds[LED_45].g = range[1] / 2;
	leds[LED_225].b = 255;
	updateleds();
	range[5] = FLEXIO_HCSR_Ping(6, GPIOC, 7);	// 225
	leds[LED_225].b = 0;
	leds[LED_225].r = 255 - (range[5] / 2);
	leds[LED_225].g = range[5] / 2;
	leds[LED_90].b = 255;
	updateleds();
	range[2] = FLEXIO_HCSR_Ping(3, GPIOA, 12);	// 90
	leds[LED_90].b = 0;
	leds[LED_90].r = 255 - (range[2] / 2);
	leds[LED_90].g = range[2] / 2;
	leds[LED_270].b = 255;
	updateleds();
	range[6] = FLEXIO_HCSR_Ping(7, GPIOA, 16);	// 270
	leds[LED_270].b = 0;
	leds[LED_270].r = 255 - (range[6] / 2);
	leds[LED_270].g = range[6] / 2;
	leds[LED_135].b = 255;
	updateleds();
	range[3] = FLEXIO_HCSR_Ping(4, GPIOA, 17);	// 135
	leds[LED_135].b = 0;
	leds[LED_135].r = 255 - (range[3] / 2);
	leds[LED_135].g = range[3] / 2;
	leds[LED_315].b = 255;
	updateleds();
	range[7] = FLEXIO_HCSR_Ping(8, GPIOA, 15);	// 315
	leds[LED_315].b = 0;
	leds[LED_315].r = 255 - (range[7] / 2);
	leds[LED_315].g = range[7] / 2;
	updateleds();
}

int main(void) {
  /* Init board hardware. */
  BOARD_InitPins();
  BOARD_BootClockRUN();
  BOARD_InitDebugConsole();

  for(uint8_t i = 0; i < 8; i++) {
	  leds[i].r = 0;
	  leds[i].g = 0;
	  leds[i].b = 0;
  }

  struct FLEXIO_WS2812_LED led;
  led.r = 0;
  led.g = 0;
  led.b = 0;

  /* Init and enable FlexIO */
  CLOCK_EnableClock(kCLOCK_Flexio0);
  flexio_config_t user_config = {
  .enableFlexio = true,
  .enableInDoze = false,
  .enableInDebug = false,
  .enableFastAccess = false
  };
  FLEXIO_Init(FLEXIO0, &user_config);
  FLEXIO_Enable(FLEXIO0, true);
  FLEXIO_WS2812_Init();

  /* Init GPIOs */
  gpio_pin_config_t config =
  {
     kGPIO_DigitalOutput,
     0,
  };
  GPIO_PinInit(GPIOA, 5U, &config);
  GPIO_WritePinOutput(GPIOA, 5U, 0U);
  GPIO_PinInit(GPIOA, 13U, &config);
  GPIO_WritePinOutput(GPIOA, 13U, 0U);
  GPIO_PinInit(GPIOA, 12U, &config);
  GPIO_WritePinOutput(GPIOA, 12U, 0U);
  GPIO_PinInit(GPIOA, 17U, &config);
  GPIO_WritePinOutput(GPIOA, 17U, 0U);
  GPIO_PinInit(GPIOA, 14U, &config);
  GPIO_WritePinOutput(GPIOA, 14U, 0U);
  GPIO_PinInit(GPIOC, 7U, &config);
  GPIO_WritePinOutput(GPIOC, 7U, 0U);
  GPIO_PinInit(GPIOA, 16U, &config);
  GPIO_WritePinOutput(GPIOA, 16U, 0U);
  GPIO_PinInit(GPIOA, 15U, &config);
  GPIO_WritePinOutput(GPIOA, 15U, 0U);

  while(1) {
	  char ch = GETCHAR();

      switch(ch) {
      case 'r':
    	  led.r = 255;
    	  led.g = 0;
    	  led.b = 0;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;
      case 'g':
    	  led.r = 0;
    	  led.g = 255;
    	  led.b = 0;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;
      case 'b':
    	  led.r = 0;
    	  led.g = 0;
    	  led.b = 255;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;
      case 'o':
    	  led.r = 0;
    	  led.g = 0;
    	  led.b = 0;
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_Update(&led);
    	  FLEXIO_WS2812_TransmitBuffer();
    	  break;
      case 's':
    	  PRINTF("Serial test\r\n");
    	  break;
      case 'p':
    	  updaterange();
    	  PRINTF("%d,%d,%d,%d,%d,%d,%d,%d\r\n", range[0], range[1], range[2], range[3], range[4], range[5], range[6], range[7]);
    	  break;
      }
  }
}

Ultrasonic Radar

Credits

Mirko Denecke

Mirko Denecke

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

Comments