The Putz
Published © GPL3+

Hexiwear RF Energy Detector

Adapts the Hexiwear to become glasses that can see the radio frequency energy around you, showing strength and frequency.

IntermediateFull instructions provided2 hours1,118
Hexiwear RF Energy Detector

Things used in this project

Hardware components

Hexiwear
NXP Hexiwear
Hexiwear Unit and Docking Station
×1
RF Meter Click MIKROE-2034
1 MHz-8 GHz RF Power Meter, using Analog Devices AD8318
×3
Coax Cable
Any coax to connect the RF splitters. The two paths on each splitter should have a 3 inch difference in length between them in order to estimate frequency
×2
Antenna, Rubber duck style, or a wire
Any antenna to pick up signals
×1
Audio Indicator
Optional Beeper instead of using Hexiwear Vibro
×1
RF Splitter
Any wideband RF splitter, including TV splitters can be substituted, Like Walmart Monoprice 110013
×3

Software apps and online services

ARM mbed.org Online Compiler
Putty
For serial com monitor
Hexi Blinky Example
Hexi OLED Text Example
Hexi Vibro Example

Hand tools and fabrication machines

RF Signal Generator
Optional, to calibrate frequency and power
Soldering iron (generic)
Soldering iron (generic)
Optional, to solder in beeper instead of using Hexiwear Vibro motor
Oscilloscope
For troubleshooting & verification

Story

Read more

Custom parts and enclosures

HexiWear RF Scanner

Draft of RF Scanner Enclosure

Schematics

Schematic Diagram

Hook Up Diagram for HexiWear, RF Clicks, RF Splitters, Coax, and Antenna

Code

main

C/C++
Main Program, Reads two RF Clicks and shows power and frequency on display along with alarm status based on thresholds of RF energy levels
#include "mbed.h"
#include "Hexi_OLED_SSD1351.h"
#include "Hexi_KW40Z.h"
#include "string.h"
#include "math.h"

 DigitalOut cs1(PTC4); // Dock 1
 DigitalOut greenLed(LED2,1); // To indicate some signals present
 DigitalOut redLed(LED1,1);  // To indicate siganls above alarm threshold
 DigitalOut spi_clk(PTC5);  // CLK Coms to RF Click
 DigitalIn spi_dat(PTC7);   // DATA Coms to RF Click
 DigitalOut vibro(PTB9);    // TO indicate signals above alarm threshold
 DigitalIn up_btn(PTA12,PullDown);
 DigitalIn down_btn(PTA13,PullDown);
 DigitalOut cs2(PTC3); // Dock 2

Serial pc(USBTX,USBRX);
 /* Instantiate the Hexi KW40Z Driver (UART TX, UART RX) */ 
KW40Z kw40z_device(PTE24, PTE25);

/* Instantiate the SSD1351 OLED Driver */ 
SSD1351 oled(PTB22,PTB21,PTC13,PTB20,PTE6, PTD15); /* (MOSI,SCLK,POWER,CS,RST,DC) */

int main() {
    unsigned int i;
    unsigned int mydata1,mydata2;
    unsigned int max1,max2;
    unsigned int min1,min2;
    unsigned int mysum1,mysum2;
    unsigned int ave1,ave2;
    unsigned int lut[]={0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 1024, 2048};
    unsigned int ave_samples1[10];
    unsigned int ave_samples2[10];
    unsigned int icount;
    unsigned int j;
    unsigned int num_ave;
    unsigned char trigger_vibro;
    unsigned int vibro_count;
    unsigned int loop_count;
    float pwr1;
    float frq;
    int delta;
    unsigned int longterm_ave;
    unsigned long longterm_sum;
    int threshold;
    float threshold_dbm;
    
     char text[20];  /* Text Buffer */ 
     vibro=0;
     greenLed=0;
     wait(0.25);
     greenLed=1;
     wait(0.25);
     greenLed=0;
     wait(0.25);
     greenLed=1;
   
   
     
 printf("\n\r--------------------\n\rProgram Started!\n\r---------------------------\n\r");    
    /* Get OLED Class Default Text Properties */
    oled_text_properties_t textProperties = {0};
    oled.GetTextProperties(&textProperties);    

    /* Turn on the backlight of the OLED Display */
    oled.DimScreenON();
    
    /* Fills the screen with solid black */         
    oled.FillScreen(COLOR_BLACK);

    /* Display Text at (x=7,y=0) */
    strcpy((char *) text,"Radio Energy");
    oled.Label((uint8_t *)text,7,0);
        
    /* Change font color to blue */ 
    textProperties.fontColor   = COLOR_BLUE;
    oled.SetTextProperties(&textProperties);

    /* Set text properties to white and right aligned for the dynamic text */
    textProperties.fontColor = COLOR_WHITE;
    textProperties.alignParam = OLED_TEXT_ALIGN_RIGHT;
    oled.SetTextProperties(&textProperties);    

    num_ave=10;
    min1=9999;
    min2=9999;
    max1=0;
    max2=0;
    icount=0;
    trigger_vibro=0;
    loop_count=0;
    threshold=3000;  // Default Red LED threshold
    
    while (true) {
       loop_count++;
       // Process Statistics
       min1=9999;
       min2=9999;
       max1=0;
       max2=0;
       mysum1=0;
       mysum2=0;
       for(j=0;j<num_ave;j++)
       {
         mysum1=mysum1+ave_samples1[j];
         mysum2=mysum2+ave_samples2[j];
         if(ave_samples1[j]<min1)min1=ave_samples1[j];
         if(ave_samples2[j]<min2)min2=ave_samples2[j];
         if(ave_samples1[j]>max1)max1=ave_samples1[j];
         if(ave_samples2[j]>max2)max2=ave_samples2[j];
        }         
        ave1=mysum1/num_ave;
        ave2=mysum2/num_ave;
        if(icount>=num_ave) icount=0;
         
         if (min1<2400)// Hard coded threshold for green LED
         {
             greenLed=0;
         }else
         {
             greenLed=1;
         }

        if (min1<threshold)
        {
            redLed=0;
            greenLed=1;
            trigger_vibro=1;
        }else
        {
            trigger_vibro=0;
        }

    if(trigger_vibro)
    {
        vibro_count=1;
        redLed=0;
        vibro=1;
    }
    else
    {
        vibro_count++;
        if(vibro_count>200)
        {
            vibro=0;
            redLed=1;
        }
    }
        


// We are doing a Bit Bang SPIbecause mbed.org spi.frequency(F) runs clock at >15 MHz, regardless of F
// RF Click can not sampel at that speed
// Clock 2 ycls, then clock 12 to read 12 bits of data out
    // Chips must be deselected
    cs1 = 1;
    cs2 = 1;
    
 // Read Dock 1
    cs1 = 0;
    mydata1=0;
    for (i=0;i<14;i++)  
    {
        spi_clk=0;
        spi_clk=1;
        if(i>2)
        {
            if(spi_dat.read())
            {      
            mydata1=mydata1+lut[13-i+1];
            }
        }
    }
    spi_clk=0;
   
// Read Dock 2   
    cs1=1;
    cs2=0;
    mydata2=0;
    for(i=0;i<14;i++)
    {
        spi_clk=0;
        spi_clk=1;
   
        if(i>2)
        {
            if(spi_dat.read())
            {
                    mydata2=mydata2+lut[13-i+1];
            }
        }
    }  
    spi_clk=0;
   cs2=1;

// Fill a running buffer   
ave_samples1[icount]=mydata1;
ave_samples2[icount]=mydata2;
icount++;
 longterm_sum=longterm_sum+ave1;
 if(loop_count>20000)  // Only update tghe display ocassionally, as sampling ADC more important to catch RF energy in pulses
 {
    // Update red LED threshold if user uis pressing buttons to change
    if(up_btn.read())threshold=threshold+100;
    if(down_btn.read())threshold=threshold-100;
    if(threshold>3300) threshold=3300;  //No signal ADC values
    if(threshold<100) threshold=100;
    
    threshold_dbm=(-0.020*threshold)+23;  // Calculate threshold in dBm from counts
    longterm_ave=longterm_sum/(loop_count-1);
    longterm_sum=0;
    loop_count=0;   
    pwr1=(-0.020*mydata1)+23.0;  // this converts counts to dBm (RF power referenced in dB to 1 mW)
    delta=mydata2-mydata1;   // Calculate difference between main channel and other channel
    frq=0.436+.0015*delta-5.886e-7*delta*delta;  // This calculates approximate frequency
    sprintf(text,"Set:%.1fdBm", threshold_dbm);
    /* Display time reading in 35px by 15px textbox at(x=2, y=40) */
    oled.TextBox((uint8_t *)text,2,25,80,15); //Increase textbox for more digits
    sprintf(text,"Now:%.1fdBm",pwr1);
    oled.TextBox((uint8_t *)text,2,45,80,25);
  
    if(frq<0.7)  // Its flat below 700 MHz, cant really declare a frequency
    {
       sprintf(text,"F=    <0.7 GHz");
    }
    else
    {
       sprintf(text,"F=    %.1f",frq);
    }
    oled.TextBox((uint8_t *)text,2,65,80,25);
   // Print some debug info to serial port
   printf("flr: %i frq:%.2f Min: %i\tNow: %.1f\tAve: %i\tMax: %i\t\tMin: %i\tNow: %i\tAve: %i\tMax: %i\t\n\r",longterm_ave,frq,min1,pwr1,ave1,max1,min2,mydata2,ave2,max2);
   }
 }
 
    printf("\n\r ---- Program Complete ----- \n\r");
}

Credits

The Putz

The Putz

2 projects • 3 followers

Comments