Super Simple Sound Doppler Peiler

Hardware en software.
Bericht
Auteur
Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#781 Bericht door Dopp »

Hallo Allemaal,

Alvast een verbeterde versie van de USB Arduino nano Agrelo converter

The function NewBearing() works now..

A squelch problem from the PA8W zerocrossdetector
also eleminated now..

So the squelch stays closed if is is jumping about yes oer no squelch.


Take and look and have fun..

Code: Selecteer alles

 /*
  ((C))PA3BNX Arduino Agrelo  to USB converter
   19-09-2017 Not all ready yet!
   2^5 data bits from PA8W and Strobe  
   I think tap from 4017 the 5 bits(4017 pins 15,13,14,6,4) and tap (40174 pin 9) as Strobe/Squelch
   Through a CD4050 non 6x level inverter  
   2^4 data bits and strobe from other dopplers
   Purpose is to give Agrelo Serial out with a cheap arduino(Uno,Nano)
   on existing doppler.
   -------
   Use a inverting transistor to interface bits and strobe from doppler to arduino
   -------
   Arduino outputs Agrelo like %DDD<cr><lf>
   Replacement  1995-N7LUE.pdf Agrelo Interface BY ROBERT SWAIN
   4 or 5 counter hardware bits from 4040  or 4060 in hardware doppler
   and the strobe Zerocross pin.
   Strobe is positive edge triggerd on pa8w doppler  pin9 at 40174 chip
     
   
   //Options also possible with arduino ?
   Arduino could also do GPS Module and output NMEA on software serial port ?
   Arduino could also do FluxCompas HMC5883  TWI interface ?
   22-09-2017
   04-08-2018
   20-11-2019
   26-11-2019
   29-11-2019
   08-12-2019
   10-12-2019
   16-12-2019
   17-12=2019
   potmeter zero offset degrees so hardware pelorus same as agrelo pelorus ???  22-11-2019
   hc4050= Hex non-inverting HIGH-to-LOW level shifter  also non pullup r's
   25-12-2019
   PA8W fuction for keeping squelch at %999 due to error in zerocrossdetector pa8w doppler
*/

//Const

const byte pinData=B01111100;//7-0  //6 Data pins = 8, 4, 2, 1, .5 kHz
const byte pinStrobe = B10000000;         //Strobe   7-0
const byte pinOffset = 0;                 //Pin offset Potmeter

//Const
const int cNodegrees = 999;             //Squelch
const int cReset = 888;                 //Reset averaged with last degrees value only
const unsigned long cSquelchOpenMax = 5000;       //Max averaged time in Averaged sub (mSec)

//Int
int Offset = 0; //For PA8W Doppler 2.3

unsigned long SquelchOpenStart = millis() + cSquelchOpenMax;

//Bool
const bool bHC4050 = true;             //Use 4050 high low inverter So no PullUp R on input pins
const bool bDemo = false;              //Simulates agrelo output
const bool bAverage = true;           //Averaged Yes or No

bool bMultiPathAverage = false;


int PA8W(int x)//Squelch problem PA9W ZeroCrossDetector
{
 int i;
 static byte c=0;
 static int oldies[3]={cNodegrees,cNodegrees,cNodegrees};

oldies[c]=x;
c++;
if (c>2) {c=0;} 
 
for (i=0;i<3;i++)
 {  
  //Serial.println(i);
  if (oldies[i]==cNodegrees)
  {
   x=cNodegrees;
  }
 }


return x;

}//Last PA8W

void Message()
{
   Serial.println(F("((C))PA3BNX v1.00 USB Agrelo Doppler Interface"));
   Serial.println(F("---------------------------------------------------"));
  if (bDemo == true) {
    Serial.println(F("DemoMode"));
  }
  if (bHC4050==true){Serial.println(F("HC4050 Mode"));}
  
  Serial.print(F("Data pins MSB to LSB="));
  for (byte i=0; i<8; i++)
  {
    if (bitRead(pinData,i)==1)
    {
     Serial.print(i) ; Serial.print(" ");
    }
  }
  Serial.println();
  
  for (byte i=0 ;i<8;i++) 
   {
    if (bitRead(pinStrobe,i)==1)
   { 
    Serial.print(F("Strobe pin=")); Serial.println(i);
   }
  }
  Serial.println(F("Squelch=LED_BUILDIN"));
  Serial.print(F("Offset pin=A"));Serial.println(pinOffset);
}//==================Last Message==========================



int GetDemo(int x1, int x2)
{
  const byte m=55;
  static byte i;
  int x;

  i++;
  x = random(x1, x2);
  if (i > m)
  {
    i=0;
    return cNodegrees;
  }
  else
  {
    return x;
  }
}//=============================Last Demo==============================

bool GetOffset()
{
 int tmp; 
 int x;
//   3.3V = ca 755
 x=map(analogRead(pinOffset),0,755,-180,180);
 
 //Only print if you turn the potmeter
 tmp=abs(Offset-x);
 if (tmp > 5)     
 {
  Offset=x ;
  Serial.print(F("Offset="));Serial.println(Offset);
  return true;
 }
  else
 { 
  return false;
 }
}//========================================Last GetOffset===============================

int Calibrate(int x)
{
  if (x == cNodegrees) {
    return x;
  }
  else
  {
    return LimitDegrees360(x + Offset);
  }
}//========================================Last Calibrate================================

//Return Agrelo formatted string % and always 3 digits
String Format3Degrees(int d) {
  String str;
  int digits[3];
  int reminder;
  digits[0] = d / 100;
  reminder = d % 100;
  digits[1] = reminder / 10;
  reminder = reminder % 10;
  digits[2] = reminder;
  str += '%';
  str += digits[0];
  str += digits[1];
  str += digits[2];
  return str;
}//==============================Last Format3Degrees==================================

//Limit Degrees 0 to 360 degrees
int LimitDegrees360(int d) {
  //Limit degrees 0 to 360 here
  //If 999 then return 999
  if (d == cNodegrees)
  {
    return d;
  }
  else
  {
    int x;
    x = d % 360;
    if (x < 0)
    {
      x += 360;
    }
    return x;
  }
}//===================================Last LimitDegrees360==============================

void SquelchLed13(int d)
{
 if (d !=cNodegrees)
  {
   digitalWrite(LED_BUILTIN,HIGH);
  }  
   else
  {
   digitalWrite(LED_BUILTIN,LOW);
  }
}//============================Last SquelchLed13 ==================== 

int NewBearing()
{
byte cc[]={0,0,0,0,0};
byte x;
int d = cNodegrees ;  //Degrees
unsigned long start1;
unsigned long start2;
unsigned long t = 2000;

start1 = micros() + (t - 1900);
start2 = micros() + t; 

do
 {
 // 7 to 0 
 if ((PIND & pinStrobe) != pinStrobe) 
  {
    goto f;
    break;//Found a not active strobe
  }
 }
while (micros() < start1);
return d;
f:

do
{
  x=PIND;
  //Serial.print(x);Serial.println("--");
  if ((x & pinStrobe) == pinStrobe ) //Wait for a strobe
  {
    //Serial.print(x);Serial.println("----");
    
    //if ((x & B01000000) > B01000000 ){cc[0]=1;}    
    //if ((x & B00100000) > B00100000){cc[1]=2;} 
    //if ((x & B00010000) > B00010000){cc[2]=4;} 
    //if ((x & B00001000) > B00001000){cc[3]=8;} 
    //if ((x & B00000100) > B00000100){cc[4]=16;} 

    if ((x & 64) == 64){cc[0]=1;}    
    if ((x & 32) == 32 ){cc[1]=2;} 
    if ((x & 16) == 16){cc[2]=4;} 
    if ((x & 8) == 8){cc[3]=8;} 
    if ((x & 4) == 4){cc[4]=16;} 

   d=cc[0]+cc[1]+cc[2]+cc[3]+cc[4]; 
   d=int(d * 11.25); 
    
   break;
  }
}
while(micros()<start2) ;


return d;

}//----------------------------Last New Bearing---------------------------------------------


//----------------------------------------Average Degrees------------------------------------
int Average(int d) {
  //If d = 999 (cNoDegrees) then reset average and return last avDegrees witch is 999
  //If d = 888 (cReset) then Reset all and put last avDegrees back in arrays

  //Always return avDegrees and Set bMultiPath

  //Integer
  static unsigned int sum[4] = {0, 0, 0, 0}; //Sum of counts for each kwadrant can be now 2^16=65536
  static int c[4] = {0, 0, 0, 0};     //Amount of count
  static int totalCount = 0;          //Sum of all counts
  static int avDegrees = cNodegrees;  //Averaged degrees
  int xx[4] = {0, 0, 0, 0};           //Adjacent kwadrants counts
  int z = 0;                          //Most adjacent headings
  int z1 = 0;                         //Other two kwandants headings Multipath
  int y = 0;                          //Index where the most headings are

  //Reset/clear and return cNodegrees or last avDegrees

  //01-06-2015 No Averaging
  if (bAverage == false) {
    return d;
  }

  //No Overflow in sum[]
  if (totalCount >= 180)
  {
    for (byte i = 0; i < 4; i++)
    {
      sum[i] = 0;
      c[i] = 0;
    }
  }

  switch (d) {
    case cNodegrees:
      //Reset and Clear
      for (byte i = 0; i < 4; i++)
      {
        sum[i] = 0;
        c[i] = 0;
      }
      bMultiPathAverage = false;
      avDegrees = cNodegrees;
      return avDegrees; //Exit now
    case cReset: //Reset and fill with avDegrees
      //Reset
      for (byte i = 0; i < 4; i++)
      {
        sum[i] = 0;
        c[i] = 0;
      }
      //Fill with last avDegrees
      d = avDegrees; //Put last degrees in again
  }

  if (d >= 0 && d < 90) {
    sum[0] += d;
    c[0]++;
  }
  if (d >= 90 && d < 180) {
    sum[1] += d;
    c[1]++;
  }
  if (d >= 180 && d < 270) {
    sum[2] += d;
    c[2]++;
  }
  if (d >= 270 && d <= 360) {
    sum[3] += d;
    c[3]++;
  }

  //No degrees found so exit function
  totalCount = c[0] + c[1] + c[2] + c[3];
  if (totalCount == 0)
  {
    bMultiPathAverage = false;
    avDegrees = cNodegrees;
    return avDegrees;
  }

  //Find 2 adjacent kwadrants with hold most heading counts

  //Count all adjacents kwadrants
  xx[0] = c[0] + c[1];
  xx[1] = c[1] + c[2];
  xx[2] = c[2] + c[3];
  xx[3] = c[3] + c[0];

  //Find out in witch two kwadrants the most headings are
  for (byte i = 0; i < 4; i++) {
    if (xx[i] > z) {
      z = xx[i]; //Most adjacent Headings counts
      y = i;   //Witch 2 adjacent Array Index from xx[1]
    }
  }

  //Check for multipath kwadrants
  switch (z) {
    case 0:
      z1 = 2;
      break;
    case 1:
      z1 = 3;
      break;
    case 2:
      z1 = 0;
      break;
    case 3:
      z1 = 1;
      break;
  }

  if (xx[z] == xx[z1])
  {
    bMultiPathAverage = true;
  }
  else
  {
    bMultiPathAverage = false;
  }

  //Average the 2 most counts kwadrants
  switch (y) {
    case  0:
      avDegrees = (sum[0] + sum[1]) / xx[y];
      break;
    case 1:
      avDegrees = (sum[1] + sum[2]) / xx[y];
      break;
    case 2:
      avDegrees = (sum[2] + sum[3]) / xx[y];
      break;
    case 3:
      if (c[3] == 0 && c[1] > 0)
      {
        avDegrees = sum[1] / c[1];
      }
      else if (c[1] == 0 && c[3] > 0)
      {
        avDegrees = sum[3] / c[3];
      }
      else if (c[3] > 0 && c[1] > 0)
      {
        avDegrees = LimitDegrees360(((sum[3] / c[3]) + ((sum[0] / c[0]) + 360) / 2));
      }

      break;
  }

  return avDegrees;
}//===================================Last Average======================================


void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  analogReference(DEFAULT);
  pinMode(LED_BUILTIN, OUTPUT); //Squelch indicator 

   //DDRD= pinData; 


   //Data Pins
  
    for(byte x=0;x <8;x++)  
    {
      if( bitRead(pinData,x )==1) 
      {
        if (bHC4050==true) 
         {
          //Serial.print(x); Serial.print(" ");
          pinMode( x, INPUT);
         }
        else
         {
          pinMode(x,INPUT_PULLUP); 
         }
       }
     }
         
  for(byte x=0;x<8;x++)
  {
   if (bitRead(pinStrobe,x)==1)
   {
    if (bHC4050==true)
     {
      pinMode(x, INPUT);
     } 
      else
     {
      pinMode(x,INPUT_PULLUP);
     }
   }
  }
 
  Message();

  GetOffset();

  Average(cNodegrees); //Init Average()  returns cNoDegrees  


}//------------------------------Last Setup==============================================

void loop() {
  //Put your main code here, to run repeatedly:
  static int OldDegrees;
  int x = cNodegrees;
    
  //Get potmeter calibration offset
  
  if (GetOffset()==true)
  { 
    if (OldDegrees !=cNodegrees)
    {
      Serial.print(Format3Degrees(Calibrate(OldDegrees)));
      Serial.println("  ----Calibrate----");
    }
  }
  
   
  if (bDemo==true)
  {
    x=GetDemo(110, 290); //begin and end degrees
  }
  else
  {
    //Squelch can be detected through degrees and showed by trigger LED_BUILTIN
    x=NewBearing();
    x=PA8W(x);//Squelch problem PA8W Doppler
  } 
    
 
  //Get Averaged Degrees
  if (bAverage==true)
  {
   x=Average(x);
  }
  
  //Detect when squelch = closed
  if (OldDegrees==cNodegrees)
  {
    SquelchOpenStart = millis() + cSquelchOpenMax;
  }

  //bMultiPathAverage, bAverage, cReset ????
  //Reduce data over RS232
  if (bMultiPathAverage ==false)
  {
    if (OldDegrees != x )
    {
      //Serial.println(Format3Degrees(x));
      Serial.println(Format3Degrees(Calibrate(x)));
      SquelchLed13(x); 
      OldDegrees=x;
    }
  }

  //Reset average after a while averaging ???
   if (millis() > SquelchOpenStart)
    {
     SquelchOpenStart = millis() + cSquelchOpenMax;
     Average(cReset);//Save only last Averaged degrees value 
     Serial.println ("TimeReset");
    }
         
  delay(10);

}//================================Last Loop ================================================



73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#782 Bericht door Dopp »

Hallo Allemaal,

Gelukkig en voorspoedig nieuwjaar allemaal.

Vandaag nog weer met USB interface zitten spelen...

Heb een extra elco van 1 uF aangebracht over de 3.3V voeding van de arduino
zodat de Calibratie portmeter stabielere output geeft.
(Bij mij moet de calibartie op 90 graden staan
om zelfde pelorus roos aan wijzing te geven als de agrelo string (%xxx)




Ook weer zitten spelen met de NewBearing Function

Nu werkt het met allerlei calibration adjusts op de V2.3 PA8W dopplerpeiler.

T=4000 uSec

dus dubbele periode tijd (Normaat 500Hz dus 2 mSec)

Timers veranderd zodat na dat er een strobe van laag of hoog naar laag is
gevonden

De maximale tijd voor weer een rise strobe =
start2 = start1- (micros()-start2);


Code: Selecteer alles


int NewBearing()
{
byte cc[]={0,0,0,0,0};
byte x;
int d = cNodegrees ;  //Degrees
unsigned long start1;
unsigned long start2;
unsigned long t = 4000;

start2 = micros(); 
start1 = start2 + t;

//Find Low state

do
 {
 // 7 to 0 
 if ((PIND & pinStrobe) != pinStrobe) 
  {
    goto f;
    break;//Found a not active strobe
  }
 }
while (micros() < start1);
return d;

f:


start2 = start1- (micros()-start2); 


//Find High state
do
{
  x=PIND;
  if ((x & pinStrobe) == pinStrobe ) //Wait for a strobe
  {
       
     
    if ((x & 64) == 64){cc[0]=1;}    
    if ((x & 32) == 32 ){cc[1]=2;} 
    if ((x & 16) == 16){cc[2]=4;} 
    if ((x & 8) == 8){cc[3]=8;} 
    if ((x & 4) == 4){cc[4]=16;} 

   d=cc[0]+cc[1]+cc[2]+cc[3]+cc[4]; 
   d=int(d * 11.25); 
    
   break;
  }
}
while(micros()<start2) ;


return d;

}//----------------------------Last New Bearing---------------------------------------------
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#783 Bericht door Dopp »

Hallo Allemaal,

Alweer een arduino update

Nu kun je ook met cmd 'AV averaging In schakelen

Vergeet niet een 1uF elco over de voeding te zetten van de arduino.

Oh de led13 van de arduino reageert als de squelch led..

Have fun..

Vandaag ook weer zitten solderen aan de Foxcopter 3 hardware...

Code: Selecteer alles

 /*
  ((C))PA3BNX Arduino Agrelo  to USB converter
   19-09-2017 Not all ready yet!
   2^5 data bits from PA8W and Strobe  
   I think tap from 4017 the 5 bits(4017 pins 15,13,14,6,4) and tap (40174 pin 9) as Strobe/Squelch
   Through a CD4050 non 6x level inverter  
   2^4 data bits and strobe from other dopplers
   Purpose is to give Agrelo Serial out with a cheap arduino(Uno,Nano)
   on existing doppler.
   -------
   Use a inverting transistor to interface bits and strobe from doppler to arduino
   -------
   Arduino outputs Agrelo like %DDD<cr><lf>
   Replacement  1995-N7LUE.pdf Agrelo Interface BY ROBERT SWAIN
   4 or 5 counter hardware bits from 4040  or 4060 in hardware doppler
   and the strobe Zerocross pin.
   Strobe is positive edge triggerd on pa8w doppler  pin9 at 40174 chip
     
   
   //Options also possible with arduino ?
   Arduino could also do GPS Module and output NMEA on software serial port ?
   Arduino could also do FluxCompas HMC5883  TWI interface ?
   22-09-2017
   04-08-2018
   20-11-2019
   26-11-2019
   29-11-2019
   08-12-2019
   10-12-2019
   16-12-2019
   17-12=2019
   potmeter zero offset degrees so hardware pelorus same as agrelo pelorus ???  22-11-2019
   hc4050= Hex non-inverting HIGH-to-LOW level shifter  also non pullup r's
   25-12-2019
   29-12-2019 Agrelo Send Rate timer
   PA8W fuction for keeping squelch at %999 due to error in zerocrossdetector pa8w doppler
   ToDo maybe
   Second software serial for picodopp display adding 6-1-2020 ?
   Eerpom save AV cmd ?
   */

//Const

const byte pinData=B01111100;//7-0  //5 Data pins = 8, 4, 2, 1, .5 kHz
const byte pinStrobe = B10000000;         //1 Strobe pin Strobe   7-0
const byte pinOffset = 0;                 //Pin offset Potmeter

//Const
const String strMulti = "%---";         //Multipath
const int cNodegrees = 999;             //Squelch
const int cReset = 888;                 //Reset averaged with last degrees value only
const unsigned long cSquelchOpenMax = 7500;       //Max averaged time in Averaged sub (mSec)
const unsigned long cDisplayAgreloTime = 1500;    //No faster then 1 sec agrelo updates

//Int
int Offset = 0; //For PA8W Doppler 2.3

unsigned long SquelchOpenStart = millis() + cSquelchOpenMax;
unsigned long DisplayAgreloTime = millis() + cDisplayAgreloTime;

//Bool
const bool bHC4050 = true;             //Use 4050 high low inverter So no PullUp R on input pins
const bool bDemo = false;              //Simulates agrelo output
bool bAverage = true;                  //Averaged Yes or No

bool bMultiPathAverage = false;

//Remote Control cmd AV 
String inputString;
bool bStringComplete;


//=============SerialRx Event=========================== 
void serialEvent() {
  while (Serial.available()) {
    //get the new byte:
    char inChar=(char)Serial.read();
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar=='z'||inChar=='\r'||inChar=='\n'||inputString.length() > 4 ){
      bStringComplete=true;
     }
     else
     {
      //add it to the inputString:
      inputString+=inChar;
     } 
  }
}


int PA8W(int x)//Squelch problem PA9W ZeroCrossDetector
{
 int i;
 static byte c=0;
 static int oldies[3]={cNodegrees,cNodegrees,cNodegrees};

oldies[c]=x;
c++;
if (c>2) {c=0;} 
 
for (i=0;i<3;i++)
 {  
   if (oldies[i]==cNodegrees)
  {
   x=cNodegrees;
  }
 }
 
return x;

}//Last PA8W

void Message()
{
   Serial.println(F("((C))PA3BNX v1.02 USB Agrelo Doppler Interface"));
   Serial.println(F("---------------------------------------------------"));
   Serial.print(F("cmd AV Average="));Serial.println(bAverage);
    
  if (bDemo == true) {
    Serial.println(F("DemoMode"));
  }
  if (bHC4050==true){Serial.println(F("HC4050 Mode"));}
    
  Serial.print(F("Data pins MSB to LSB="));
  for (byte i=0; i<8; i++)
  {
    if (bitRead(pinData,i)==1)
    {
     Serial.print(i) ; Serial.print(" ");
    }
  }
  Serial.println();
  for (byte i=0 ;i<8;i++) 
   {
    if (bitRead(pinStrobe,i)==1)
   { 
    Serial.print(F("Strobe pin=")); Serial.println(i);
   }
  }
  Serial.println(F("Squelch=LED_BUILDIN"));
  Serial.print(F("Max AverageTime="));Serial.println(cSquelchOpenMax);
  Serial.print(F("DisplayAgreloSendInterval="));Serial.println(cDisplayAgreloTime);
  Serial.print(F("Cal Offset pin=A"));Serial.println(pinOffset);
}//==================Last Message==========================



int GetDemo(int x1, int x2)
{
  const byte m=55;
  static byte i;
  int x;

  i++;
  x = random(x1, x2);
  if (i > m)
  {
    i=0;
    return cNodegrees;
  }
  else
  {
    return x;
  }
}//=============================Last Demo==============================

bool GetOffset()
{
 int tmp; 
 int x;
//   3.3V = ca 755
 x=map(analogRead(pinOffset),0,755,-180,180);
 
 //Only print if you turn the potmeter
 tmp=abs(Offset-x);
 if (tmp > 3)     
 {
  Offset=x ;
  Serial.print(F("Offset="));Serial.println(Offset);
  return true;
 }
  else
 { 
  return false;
 }
}//========================================Last GetOffset===============================

int Calibrate(int x)
{
  if (x == cNodegrees) {
    return x;
  }
  else
  {
    return LimitDegrees360(x + Offset);
  }
}//========================================Last Calibrate================================

//Return Agrelo formatted string % and always 3 digits
String Format3Degrees(int d) {
  String str;
  int digits[3];
  int reminder;
  digits[0] = d / 100;
  reminder = d % 100;
  digits[1] = reminder / 10;
  reminder = reminder % 10;
  digits[2] = reminder;
  str += '%';
  str += digits[0];
  str += digits[1];
  str += digits[2];
  return str;
}//==============================Last Format3Degrees==================================

//Limit Degrees 0 to 360 degrees
int LimitDegrees360(int d) {
  //Limit degrees 0 to 360 here
  //If 999 then return 999
  if (d == cNodegrees)
  {
    return d;
  }
  else
  {
    int x;
    x = d % 360;
    if (x < 0)
    {
      x += 360;
    }
    return x;
  }
}//===================================Last LimitDegrees360==============================

void SquelchLed13(int d)
{
 if (d !=cNodegrees)
  {
   digitalWrite(LED_BUILTIN,HIGH);
  }  
   else
  {
   digitalWrite(LED_BUILTIN,LOW);
  }
}//============================Last SquelchLed13 ==================== 

int NewBearing()
{
byte cc[]={0,0,0,0,0};
byte x;
int d = cNodegrees ;  //Degrees
unsigned long start1;
unsigned long start2;
unsigned long t = 4000;

start2 = micros(); 
start1 = start2 + t;

//Find Low state

do
 {
 // 7 to 0 
 if ((PIND & pinStrobe) != pinStrobe) 
  {
    goto f;
    break;//Found a not active strobe
  }
 }
while (micros() < start1);
return d;

f:


start2 = start1- (micros()-start2); 


//Find High state
do
{
  //Serial.print(x);Serial.println("--");
  x=PIND;
  if ((x & pinStrobe) == pinStrobe ) //Wait for a strobe
  {
       
    //if ((x & B01000000) > B01000000 ){cc[0]=1;}    
    //if ((x & B00100000) > B00100000){cc[1]=2;} 
    //if ((x & B00010000) > B00010000){cc[2]=4;} 
    //if ((x & B00001000) > B00001000){cc[3]=8;} 
    //if ((x & B00000100) > B00000100){cc[4]=16;} 

    
    if ((x & 64) == 64){cc[0]=1;}    
    if ((x & 32) == 32 ){cc[1]=2;} 
    if ((x & 16) == 16){cc[2]=4;} 
    if ((x & 8) == 8){cc[3]=8;} 
    if ((x & 4) == 4){cc[4]=16;} 

   d=cc[0]+cc[1]+cc[2]+cc[3]+cc[4]; 
   d=int(d * 11.25); 
    
   break;
  }
}
while(micros()<start2) ;


return d;

}//----------------------------Last New Bearing---------------------------------------------


//----------------------------------------Average Degrees------------------------------------
int Average(int d) {
  //If d = 999 (cNoDegrees) then reset average and return last avDegrees witch is 999
  //If d = 888 (cReset) then Reset all and put last avDegrees back in arrays

  //If bAverage=false then return just d and set MultiPathAverage to false

  //Always return avDegrees and Set bMultiPath

  //Integer
  static unsigned int sum[4] = {0, 0, 0, 0}; //Sum of counts for each kwadrant can be now 2^16=65536
  static int c[4] = {0, 0, 0, 0};     //Amount of count
  static int totalCount = 0;          //Sum of all counts
  static int avDegrees = cNodegrees;  //Averaged degrees
  int xx[4] = {0, 0, 0, 0};           //Adjacent kwadrants counts
  int z = 0;                          //Most adjacent headings
  int z1 = 0;                         //Other two kwandants headings Multipath
  int y = 0;                          //Index where the most headings are

  //Reset/clear and return cNodegrees or last avDegrees

  //01-06-2015 No Averaging
  if (bAverage == false) {
    bMultiPathAverage=false;
    return d;
  }

  //No Overflow in sum[]
  if (totalCount >= 180)
  {
    for (byte i = 0; i < 4; i++)
    {
      sum[i] = 0;
      c[i] = 0;
    }
  }

  switch (d) {
    case cNodegrees:
      //Reset and Clear
      for (byte i = 0; i < 4; i++)
      {
        sum[i] = 0;
        c[i] = 0;
      }
      bMultiPathAverage = false;
      avDegrees = cNodegrees;
      return avDegrees; //Exit now
    case cReset: //Reset and fill with avDegrees
      //Reset
      for (byte i = 0; i < 4; i++)
      {
        sum[i] = 0;
        c[i] = 0;
      }
      //Fill with last avDegrees
      d = avDegrees; //Put last degrees in again
  }

  if (d >= 0 && d < 90) {
    sum[0] += d;
    c[0]++;
  }
  if (d >= 90 && d < 180) {
    sum[1] += d;
    c[1]++;
  }
  if (d >= 180 && d < 270) {
    sum[2] += d;
    c[2]++;
  }
  if (d >= 270 && d <= 360) {
    sum[3] += d;
    c[3]++;
  }

  //No degrees found so exit function
  totalCount = c[0] + c[1] + c[2] + c[3];
  if (totalCount == 0)
  {
    bMultiPathAverage = false;
    avDegrees = cNodegrees;
    return avDegrees;
  }

  //Find 2 adjacent kwadrants with hold most heading counts

  //Count all adjacents kwadrants
  xx[0] = c[0] + c[1];
  xx[1] = c[1] + c[2];
  xx[2] = c[2] + c[3];
  xx[3] = c[3] + c[0];

  //Find out in witch two kwadrants the most headings are
  for (byte i = 0; i < 4; i++) {
    if (xx[i] > z) {
      z = xx[i]; //Most adjacent Headings counts
      y = i;   //Witch 2 adjacent Array Index from xx[1]
    }
  }

  //Check for multipath kwadrants
  switch (z) {
    case 0:
      z1 = 2;
      break;
    case 1:
      z1 = 3;
      break;
    case 2:
      z1 = 0;
      break;
    case 3:
      z1 = 1;
      break;
  }

  if (xx[z] == xx[z1])
  {
    bMultiPathAverage = true;
  }
  else
  {
    bMultiPathAverage = false;
  }

  //Average the 2 most counts kwadrants
  switch (y) {
    case  0:
      avDegrees = (sum[0] + sum[1]) / xx[y];
      break;
    case 1:
      avDegrees = (sum[1] + sum[2]) / xx[y];
      break;
    case 2:
      avDegrees = (sum[2] + sum[3]) / xx[y];
      break;
    case 3:
      if (c[3] == 0 && c[1] > 0)
      {
        avDegrees = sum[1] / c[1];
      }
      else if (c[1] == 0 && c[3] > 0)
      {
        avDegrees = sum[3] / c[3];
      }
      else if (c[3] > 0 && c[1] > 0)
      {
        avDegrees = LimitDegrees360(((sum[3] / c[3]) + ((sum[0] / c[0]) + 360) / 2));
      }

      break;
  }

  return avDegrees;
}//===================================Last Average======================================


void setup() {
  // put your setup code here, to run once:

  Serial.begin(9600);
  analogReference(DEFAULT);
  pinMode(LED_BUILTIN, OUTPUT); //Squelch indicator 


   //DDRD= pinData; 


   //Data Pins
  
    for(byte x=0;x <8;x++)  
    {
      if( bitRead(pinData,x )==1) 
      {
        if (bHC4050==true) 
         {
          //Serial.print(x); Serial.print(" ");
          pinMode( x, INPUT);
         }
        else
         {
          pinMode(x,INPUT_PULLUP); 
         }
       }
     }
         
  for(byte x=0;x<8;x++)
  {
   if (bitRead(pinStrobe,x)==1)
   {
    if (bHC4050==true)
     {
      pinMode(x, INPUT);
     } 
      else
     {
      pinMode(x,INPUT_PULLUP);
     }
   }
  }
 
  Message();

  GetOffset();

  Average(cNodegrees); //Init Average()  returns cNoDegrees  


}//------------------------------Last Setup==============================================

void loop() {
  //Put your main code here, to run repeatedly:
  //String
  static String lastString;
  //Integer
  static int OldDegrees = cNodegrees;
  int x = cNodegrees;
  unsigned long t;     
  
  
//Call SerialEvent once in a while
serialEvent();         

if (bStringComplete==true)
{
  if (inputString=="AV")
  {
   if (bAverage==false)
   {
    Serial.println(F("Average=true"));
    bAverage=true;
    Average(cNodegrees);
   }
   else
   {
    Serial.println(F("Average=false"));
    bAverage=false;
    bMultiPathAverage=false;
   }
   //Now clear inputString because all done 
   inputString="";
   bStringComplete=false;
   }
}

  //Get potmeter calibration offset
  if (GetOffset()==true)
  { 
    if (OldDegrees !=cNodegrees)
    {
      Serial.print(Format3Degrees(Calibrate(OldDegrees)));
      Serial.println("  ----Calibrate----");
    }
  }
  
   
  if (bDemo==true)
  {
    x=GetDemo(110, 290); //begin and end degrees
  }
  else
  {
    //Squelch can be detected through degrees and showed by trigger LED_BUILTIN
    x=NewBearing();
    x=PA8W(x);//Squelch problem PA8W Doppler
  } 
    
 
   //Average or not if bAverage=false 
   x=Average(x);
  
  
  //Detect when squelch = closed
  t=millis();
  if (OldDegrees==cNodegrees)
  {
    SquelchOpenStart = t + cSquelchOpenMax;
    DisplayAgreloTime = t-1;//Fast Display if squelch opens
  }

  //bMultiPathAverage, bAverage, cReset ????
  //Reduce agrelo data over RS232
  //------------------------------------------
  if (t > DisplayAgreloTime)
  {
   
   DisplayAgreloTime = t + cDisplayAgreloTime;
   
   if (bMultiPathAverage == false)
   {
    if (OldDegrees != x )
    {
      //Serial.println(Format3Degrees(x));
      lastString=(Format3Degrees(Calibrate(x)));
      Serial.println(lastString);
      SquelchLed13(x); 
      OldDegrees=x;
    }
   else
    {
     if (lastString != strMulti && x != cNodegrees)
      {
       Serial.println(strMulti);
       lastString = strMulti;
      }
    }  
   }

  }
//---------------------------------------------
  
  //Reset average after a while averaging ???
   t=millis();
   if (t > SquelchOpenStart)
    {
     SquelchOpenStart = t + cSquelchOpenMax;
     Average(cReset);//Save only last Averaged degrees value 
     Serial.print ("TimeReset="); Serial.println(cSquelchOpenMax);
    }
         
 delay(10);

}//================================Last Loop ================================================


73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#784 Bericht door Dopp »

Hallo Allemaal,

Mijn experimenteer Audio PA

Printje 7 Watt van Velleman.

Nu heb ik een makkelijk bruikbaar versterker unit
om te testen mijn tafel microfoon

Met alle aansluitingen zoals koptelefoon 3.5mm
Ls din voor andere speaker

Tulp en 5 pin Din input...
Bijlagen
Experimenteer PA<br />voor in de shack
Experimenteer PA
voor in de shack
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#785 Bericht door Dopp »

Hallo Allemaal,

Hierbij een screen shot

van mijn wave file player program.

Korte wave files en start en stop een pootje van de rs232 hoog of laag.
Bijlagen
MyKittPlayerPrg.png
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
PE2AAB
Moderator
Berichten: 7089
Lid geworden op: 12 apr 2005, 19:06
Roepletters: PE2AAB
Locatie: Aalst - Waalre
Contacteer:

Re: Super Simple Sound Doppler Peiler

#786 Bericht door PE2AAB »

Hoi Lodewijk,

Werkt jouw software ook met de KerberosSDR?
'73 Rick, PE2AAB www.pe2aab.nl

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#787 Bericht door Dopp »

Hallo Allemaal,


Ben een tijd niet QRV geweest enzo..

Weinig inspiratie enzo in de hobby

Maar veranderd misschien wel weer.

Nee niks met Kereberos Software..


Zag wel dat er nieuw filmpjes zijn

Zoals Blue tooth AOA etc


Inside Bluetooth 5.1 – Direction Finding and More
https://www.youtube.com/watch?v=kpioWvMZMqw

CoreHW Rabbit SP16T BT5.1 Indoor Positioning Optimized RF Switch
https://www.youtube.com/watch?v=7YYu_gok9QE

Virtual Video Visit Episode 4, The Kerberos 4 Coherent SDR new to ML&S
https://www.youtube.com/watch?v=KQf1h9hzanM

Groeten

PA3BNX
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#788 Bericht door Dopp »

Hallo Allemaal,

Nog een leuk filmpje over storingen opsporen bij mobile netwerk beheerders.


35C3 - Die verborgene Seite des Mobilfunks

https://www.youtube.com/watch?v=CSZWTaTu9As
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#789 Bericht door Dopp »

Hallo Allemaal,


Heb de draad weer opgepakt hier.
Ben weer bezig met de foxcopters

met name het bedienkastje met arduino nano en lcd5110 nokia display
voor mijn ruiten wisser foxcopters. (mobiele antenne rotors) voor auto-vossen-jachten.

Heb voor testen tijdelijk een potmeter aangesloten i.p.v.
de reedrelaitjes in de foxcopter zelf voor graden uitlezen.

Kastje is van hout en hardboard geverfd met magneet slotje en piano schanier deksel

Arduino zit op een klein steekbordje.
Relaitjes zijn gewoon een dubbel arduino koop relais met opto's.
(Leuk is dat er op dat relais printje ook smd ledjes zitten handig bij het testen)

Aansluiting naar foxcopter gewoon met een standard db9 connector.


Nu de software naar mijn zin maken hi...


Software kan pendelen tussen 2 graden
links en rechts om lopen
en met de adjust potmeter naast de knopjes direct lopen naar
een ingestelde gedraaide stand

Die potmeter is dus a.h.w. een flexible as met de rotorantenne stand.

Er zit dus een dubbel relais in om de ruiten-wissen-motor
link/rechts en stop


Een lm317 2-amp met instel potmeter voor regelbare spanning
om de ruiten wissen motor op gewenste snelheid te zetten.

en een 9 volt stabilisator. (Spannings regelaar zitten aan een koelplaatje alu natuurlijk)

Op het nokia 5110 scherm veschijnt een Pelorus
die met een pijl de stand aangeeft (windroos) en in 3 digits het aantal graden.

Dit alles past/werkt dus op mijn al eerder gebouwde foxcopters 2 en 3



Groeten allemaal
Bijlagen
FoxCopter2-3-testkastje.png
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#790 Bericht door Dopp »

Hallo Allemaal


Zijn er nog BallonVossenJacht zelfbouwers en
meedoeners die al bezig zijn met nieuwe contrapties op de peilauto's ?


Vond nog een leuke DIY STM32 Antenna rotor

Portugees
DIY antenna rotator C omplte STM32 project.
https://www.youtube.com/watch?v=vWxhcFQp87Y

Deze draait wel te langzaam voor op een peilauto dak denk ik...


Ben bezig met de software van de Foxcopter 2/3


Begint nu leuk te werken ...

Not yet 100% okay !!


Draaien aan de potmeter en dan draaid de rotor naar betreffende stand
en stopt.

Of begin en eindpunt instellen en dan daar tussen Swingen (Pendelen).


Of gewoon handmatig toets Geel(stop), blauw(CW). rood(CCW).

De MenuToets(Wit) gaat naar menu Swing/Pendelen

Rotor draait maximaal 15 sec in dezelfde richting.


Zie plaatjes van Nokia LCD 5110 Screen.




Groeten
Bijlagen
nokia lcd5110 Foxcopter
nokia lcd5110 Foxcopter
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#791 Bericht door Dopp »

Hallo Allemaal,

Nog een leuk kort antenna rotor filmpje

mobile directional antenna rotator

https://youtu.be/ZqkdOfleg3A
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#792 Bericht door Dopp »

Hallo Allemaal,

Heb vandaag op mijn oude rode doppler kabel antenne-
test kastje 2 bnc chaissis delen aan gebracht
zodat ik coaxckabel met BNC's kan testen
zonder multimeter..

Een bnc kortgeloten en andere heeft voeding van de led.

Dus sluiting of onderbreking nu snel gevonden
als je kabel niet vertrouwd of gestruikeld bent
over de kabel tijden vossen jacht...
Bijlagen
DopplerTest+BNC.png
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#793 Bericht door Dopp »

Hallo Allemaal,

Hoor dat er in/voor Dutch Mill een nieuwe radar komt voor 2022 in Herwijnen



Ik heb nog steeds in gebruik mijn oude muismat
destijds bij een Veron of VRZA excursie gekregen bij DutchMill
voor 2000

Heb die mooie PPI op de muismat zelf gezien...

Met kunst en vliegwerkt wordt momenteel de DutchMill
Radar operationeel gehouden..

Er moet niks stuk gaan want reserve ondedelen zijn er niet...
Bijlagen
DutchMill2020.png
DutchMill2020.png (365.16 KiB) 9450 keer bekeken
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
Dopp
Berichten: 1242
Lid geworden op: 08 mei 2011, 18:03
Roepletters: PA3BNX

Re: Super Simple Sound Doppler Peiler

#794 Bericht door Dopp »

Hallo Allemaal

Update in programma SoundDoppler.exe v1.58


Naar aanleiding van PA8W GatedSampling arduino doppler (Goed idee van Wil PA8W).
De bedoeling is om modulatie resten weg te halen maar ook om
optimale fase jump punten van 4 antenne doppler systeem te vinden in het switched-capicitor-filter.

In de sounddoppler.exe software met geluidskaart heb je natuurlijk veel meer punten dan de 4 kwadranten
capaciteiten (Samples capaciteiten) bij een arduino met 4 elcootjes.

Hierbij de methode die ik gebruik om in het SwitcHCapFilter (SCF) van de doppler-peiler
4 zogeheten sweet spots laat staan
waarna ik dan de SinCosDetector de richting laat bepalen.

Dus ik kan met de variable SweetSpot(graden 0-90) de offset instellen
en daarna de 3 andere plekken bepalen
Alleen deze waarde in array laat ik dan staan de andere zet ik op 0

Door de constante variable z een waaarde van bv 1 te geven laat ie 2 elementen naast elkaar staan per sweetspot


Als SweetSpot -1 (Auto 4 Maxspots) is
dan wordt de array opgedeeld in 4 kwadranten en in ieder kwadrant
1 maximale waarde gezocht en die gevonden waardes behouden en alle anderen op 0 gezet.

Zie de Subroutine en plaatjes van SCF screen

opm: Sorry Wil Subroutine heet nog PA8_SweetSpot() hi (Heeft geen diepere betekenis hi)

-------------------------------------------------------------------------------------------------------------
Public Sub PA8W_SweetSpot()
''ToDo 18-10-2020 Find 4 sweet spots in arraySwitchCap() 1 in each kwadrant

''Const Integer
Const z As Integer = 0

''Integer
Dim x As Integer
Dim ff As Integer

Dim x1 As Integer
Dim x2 As Integer
Dim x3 As Integer

Dim t1 As Integer
Dim t2 As Integer
Dim t3 As Integer
Dim t4 As Integer

''Long
Dim v As Long

''Float
Dim f As Double


f = UboundArrSwitchCap / 4
x1 = CInt(Math.Round(f))
x2 = CInt(Math.Round((2 * f)))
x3 = CInt(Math.Round((3 * f)))


If SweetSpot < 0 Then
''4 Max points in array 1 in each kwadrant

v = 0
For x = 0 To x1
''Find max
If Abs(arrSwitchCap(x)) >= v Then
v = arrSwitchCap(x)
t1 = x
End If
Next x

v = 0
For x = x1 To x2
''Find max
If Abs(arrSwitchCap(x)) >= v Then
v = arrSwitchCap(x)
t2 = x
End If
Next x

v = 0
For x = x2 To x3
''Find max
If Abs(arrSwitchCap(x)) >= v Then
v = arrSwitchCap(x)
t3 = x
End If
Next x


v = 0
For x = x3 To UboundArrSwitchCap
''Find max
If Abs(arrSwitchCap(x)) >= v Then
v = arrSwitchCap(x)
t4 = x
End If
Next x


Else

''4 points (90 degrees) with constant offset

ff = CInt(Math.Round((SweetSpot * f) / 90))

t1 = ff
t2 = ff + x1
t3 = ff + x2
t4 = ff + x3


''Limit check
t2 = t2 Mod UboundArrSwitchCap
t3 = t3 Mod UboundArrSwitchCap
t4 = t4 Mod UboundArrSwitchCap

End If

''Modify the ArrSwitchCap
For x = z To UboundArrSwitchCap - z
Select Case x
Case t1 - z To t1 + z
Case t2 - z To t2 + z
Case t3 - z To t3 + z
Case t4 - z To t4 + z
Case Else
arrSwitchCap(x) = 0
End Select
Next x


End Sub

---------------------------------------------------------------------------------------------
Bijlagen
SweetSpotBNX.png
73's
PA3BNX
Lodewijk

Mijn Credo!

Zelfbouw:
Minimaal hardware
en maximaal software.

Gebruikersavatar
pa8w
Berichten: 946
Lid geworden op: 22 dec 2011, 21:30
Roepletters: PA8W
Locatie: Beuningen
Contacteer:

Re: Super Simple Sound Doppler Peiler

#795 Bericht door pa8w »

Nice job Lodewijk!
Het grappige is wel dat het bij een sinusvormig ingangssignaal niets uitmaakt waar je de samples neemt.
Bij een peilsignaal uit een normale audio-uitgang wel.
De grootste winst haal je bij gebruikmaking van een discriminator-uitgang omdat dan de fase-pulsjes het smalst zijn.

Groetjes,
Wil.
Let op: website verhuisd naar: http://www.paluidsprekers.nl/pa8w/index.html

Plaats reactie